velxio/frontend/src/simulation/customChips/syntheticPins.ts

75 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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<string, number>();
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<number>();
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;
}