Repository navigation
v0.5.0
Breaking
triggerInput/trigger_inputandInputEventare removed, in Rust, Node and WASM. A
UserInputis now driven by a queue of timed frames:submitInput(writes)queues them and
inputProgress(out)reports how many event frames are still pending per input. The old calls
map onto frames asCont(s)→{ comp, frames: [{ state: s, coalesce: true }] }and
Pulse(s)→{ comp, frames: [{ state: s }, { state: <all false> }] }; a pulse that should
leave an input's other pins alone gives themnull.- An input write reaches its wires one tick after it is submitted: one tick sooner than before, and
the same on a wire shared with another driver, where it used to arrive a tick early or hide a
one-tick pulse. An input's pins and wires now change in the same tick. - A frame's
statemust have exactly one entry per output pin; the old call padded a short array
withfalse. - CLI fixtures'
triggersfield is no longer read; timed input isinputWritesonly (see
Added). A trigger at tick T becomes a request at tick T + 1 (cont→ one frame,pulse→ the
set frame then an all-false frame), which keeps the links of its trace unchanged. sim verify, which ran the oldtest.jsfixture format, is removed.- In
contract.d.ts,SimulationandSimulationConstructortake a second type parameter,
Async:truefor the Node binding, whose state reads return promises,falsefor WASM. Simulation.fromJsonis removed from the Node and WASM bindings and fromcontract.d.ts; use
new Simulation(JSON.parse(json)).- A board is validated once, when it is compiled, whichever way it comes in, so a malformed board
gets the same error in the CLI, Node and WASM. An unknown type is reported as
UnknownComponentType { idx, ty }, naming the component, and a type id or negated pin index
whose low 16 bits name a real type or pin is rejected instead of narrowed onto it. - In Rust,
ComponentDescriptorholds plain numbers:tyis theu32type id and
neg_inputs/neg_outputsareVec<u32>;BoardBuilder::component_negtakes&[u32].
CompType::id()returnsu32,CompType::try_from_u16is nowCompType::from_id(u32), and
CompTypeno longer implements serde orTryFrom<u16>.NegateOutOfRange::pinis au32,
decode_boardno longer checks type ids, andencode_boardreturns aResult, refusing ids
too wide for the format.
Added
- Input frames carry a
hold(minimum ticks on the pins before the next frame), anullper pin
to keep that pin's value, and acoalesceflag for levels: coalescing frames submitted between
two ticks merge per pin and reach the circuit once.replace: truedrops an input's pending
frames and ends its running hold. Sequencing happens inside the tick loop, so the trace no longer
depends on batch sizes or host timing. - Each input holds at most 65 536 pending event frames; a write over the limit is refused whole.
- On Node,
submitInputvalidates on the JS thread and returns without waiting for the worker. - CLI fixtures accept an
inputWritesfield,[{ tick, writes }], holdingsubmitInputrequests
in the JS shape;run,traceandbenchsubmit each once the simulation has runtick
ticks. - Component state, in Rust, Node and WASM:
stateVersionsfills a caller-owned buffer with a
version per component that changes whenever its state does,readState/writeStateread and
write a RAM's memory (bit-packed words, the layout of a ROM'sops), andreadRecordsreads a
recorder's records together with its count. Reads are coherent at a tick boundary; on Node
readStateandreadRecordsreturn promises, andwriteStateis checked on the JS thread and
queued in order withsubmitInput. - The recorder (type 201) captures a data bus of up to 32 bits on each rising trigger edge into a
ring of its lastcapacityrecords, optionally with the tick of each. It is how a terminal gets
every character its circuit writes, one per tick if need be. - New errors for the state API:
ComponentOutOfRange,StateRange,StateReadOnly,
NotARecorder,RecordsAheadandRecordTicks.
Changed
- On WASM, a malformed descriptor or run config is reported with the field at fault, such as
components[3].inputs must be an array of u32. - The README is rewritten as a shorter guide to what the engine is and how to use it, with a
component table listing each type's inputs, outputs,opsand behavior; the full API types are
in@logigator/sim/contract. It corrects the CLK'sops[0], which is the number of ticks the
clock stays low before a one-tick high, not ticks per half-cycle, and the WASM snapshot's field
names (isDelta,valuesPtr,valuesLen).
Performance
- The WASM build is about half the size:
sim_wasm_bg.wasmis 108 KB instead of 225 KB (45 KB
instead of 95 KB gzipped), as it no longer carries serde, a JSON parser or a stable sort. new Simulation(descriptor)on WASM builds a large board 2–3× faster (a 200k-component board in
~30 ms instead of ~80 ms).
Fixed
run()with anmstoo large to represent, such asInfinity, no longer crashes (a trap in
WASM, a thrown panic in Node); an out-of-rangemsortickscounts as no bound, sorun()
refuses it as unbounded andrunAsync()runs untilstop().sim bench --msrefuses it too.
Full Changelog: v0.4.0...v0.5.0