digital circuits

SICP §3.3.4's digital-circuit simulator, traced one agenda item at a time. A wire holds a signal (0 or 1) and a list of gates to run when the signal changes. A gate computes its output from its current inputs and schedules the new value after its own delay. The agenda is a list of time segments, each holding a queue of pending actions; propagation repeatedly advances the clock to the earliest segment and runs its next item – FIFO order (SICP's own default) or LIFO order (ex. 3.32), your choice.

Pick a circuit – a bare AND gate, a half-adder, a full-adder, or an N-bit ripple-carry adder – and watch it settle. The schematic panel lays out wires and gates by topological level with a barycenter row ordering; the timing diagram shows every wire's history as a waveform, and clicking an input's lane toggles a stimulus there. Two toggles matter beyond FIFO/LIFO: composing an or-gate from inverters and an and-gate (ex. 3.29, De Morgan's law) changes its delay and internal wire count but never its logical function; and skipping add-action!'s initial call (ex. 3.31) turns out to be worse than a merely transient glitch – for any circuit with more than one gate in series, it can leave the final answer permanently wrong, because a gate whose inputs never genuinely change from their zero default never runs even once. The comparison table at the bottom runs the same circuit and stimulus through all four FIFO/LIFO x init-on/init-off combinations side by side.

The pure model (`build-circuit`, the agenda-based `simulate`, the independent combinational-logic oracle `expected`, and the static-timing analysis `longest-from`) lives in wal-sh.tools.digital-circuits.core (host-neutral .cljc, tested on the JVM with test.check: the simulation's settled state agrees with the oracle across random stimuli and circuit kinds, ripple-carry arithmetic is exact, the or-gate composition is logically equivalent to the primitive, and static timing bounds actual settling time). The browser adapter is wal-sh.tools.digital-circuits.browser. Build: gmake tools-cljs; debug in isolation: gmake dev-tool TOOL=digital-circuits.