/** * Synthetic pin numbers for custom-chip output pins. * * A custom-chip output pin wired DIRECTLY to a component (e.g. a wokwi-led) * has no board GPIO on its net, so the wire-graph trace returns null and the * chip can drive nothing through the digital PinManager. We give every such * chip pin a stable synthetic pin NUMBER, far above any real board pin * (max ~69), so the chip's driver and every component on the same net share * one PinManager key — making the chip a first-class pin source. * * The same (chipId, pinName) identity keys the SPICE chip voltage source (see * chipPinDrives + spice/componentToSpice) so the analog engine drives the net * too. Kept in this dependency-light module so both the resolver * (components/DynamicComponent) and the chip runtime (ChipRuntime) can import * it without pulling in React / the store. */ export const SYNTHETIC_CHIP_PIN_BASE = 100000; const synthChipPinMap = new Map(); let nextSyntheticChipPin = SYNTHETIC_CHIP_PIN_BASE; /** Stable synthetic pin number for a custom-chip pin. Allocate-on-first-use. */ export function syntheticChipPin(chipId: string, pinName: string): number { const key = `${chipId}${pinName}`; let n = synthChipPinMap.get(key); if (n === undefined) { n = nextSyntheticChipPin++; synthChipPinMap.set(key, n); } return n; } /** * Stable synthetic pin number for a whole chip-to-chip NET (multi-chip bus), * keyed by the net's canonical id rather than by a single (chipId, pinName). * * Phase 0 of the multi-chip digital bus track (project/multichip-bus/): two or * more chips on one wire must share ONE PinManager key. `syntheticChipPin` * mints a per-endpoint key, which is correct for the single-chip-to-component * case but gives each chip on a bus a different number (root cause A). * `syntheticNetPin` mints ONE number per net so every endpoint resolves to the * same key. It shares the same allocator + numbering space as * `syntheticChipPin` (disjoint string keys via the `net:` prefix), so * `isSyntheticChipPin` and the SPICE drive / boardless-input bridge keep * treating both kinds uniformly. */ const netPins = new Set(); export function syntheticNetPin(netId: string): number { const key = `net:${netId}`; let n = synthChipPinMap.get(key); if (n === undefined) { n = nextSyntheticChipPin++; synthChipPinMap.set(key, n); netPins.add(n); } return n; } /** * True if `pin` is a multi-chip BUS net key (minted by syntheticNetPin), vs a * single-chip synthetic pin or a real board pin. The chip-bus driver-strength * resolution (busNets) only manages these — single-chip-to-component synthetic * pins keep the legacy last-writer-wins path. */ export function isSyntheticNetPin(pin: number): boolean { return netPins.has(pin); } /** True if `pin` is a minted synthetic chip-pin number (vs a real board pin). */ export function isSyntheticChipPin(pin: number): boolean { return pin >= SYNTHETIC_CHIP_PIN_BASE && pin < nextSyntheticChipPin; }