Expand description
STATE (vj-sim::state) — cross-track contract only: the Rust-owned 4-state
arena’s SoA layout query shape, its value-change fan-out primitive, and the one
canonical signal read/write/subscribe interface (ARCHITECTURE §2: “Signal
read/write/subscribe: STATE owns the one canonical primitive; VPI/FST/debugger
are pure consumers”). The arena implementation itself belongs to the state
track, not this contracts wave.
Reconciliation: state.md calls the value-change listener trait ChangeListener;
scheduler.md independently sketches the same contract under the name
ValueChangeSink. Per the task’s naming and because scheduler.md’s signature is
the more concrete of the two, this crate uses ValueChangeSink (ledger SC-071,
RT-005) and does not separately define a ChangeListener.
Task 20 (ST-130) — dependency direction is an invariant, not an accident.
RUNTIME consumes STATE’s reference read/write API
(SignalAccess/ValueChangeSink) and its Bit/OwnedSVInt-adjacent
FourStateValue type, never the reverse: FST/VPI/$display are consumers,
not producers, of these interfaces, and no code anywhere in vj-sim::state
calls into vj-runtime’s FST/VPI/$display formatting. This crate’s own
Cargo.toml (crates/vj-sim/Cargo.toml) lists no vj-runtime
dependency, which is the mechanically-checkable half of this invariant.
This is not a hypothetical edge: vj-runtime’s Cargo.toml already
depends on vj-sim (since the very first crate-skeleton commit), and
vj-runtime::signal_consumer::RuntimeSignalConsumer already consumes
SignalAccess directly. Both halves of the invariant — the real, present
edge in one direction and the absent edge in the other — are guarded by an
automated test: crates/vj-sim/tests/dependency_direction.rs. Confirm
live with cargo tree -p vj-sim -i vj-runtime (expected to report no
path) or cargo test -p vj-sim --test dependency_direction; see
docs/CONTRACTS.md’s “Wave A — wA-state notes” section for the fuller
writeup, including for RUNTIME’s own wave to keep honoring as it grows more
dependencies.
Re-exports§
pub use crate::driver_counts::*;
Modules§
- event_
plan - The design-wide event-pool plan (LRM 1800-2023 15.5, 23.6).
- event_
pool - The event pool: event handles (LRM 1800-2023 15.5.2 - 15.5.5).
- force
force/release(LRM 1800-2023 §10.6.2): each engine’s table of forced cells (ForceTable, owned by itsVcState), applied inside the one write primitive (write::commit_write_at) so that every writer – a blocking or nonblocking assignment, a continuous assignment, a port connection – is overridden the same way.- storage
- The stored bit shape of every value type a signal or local can have.
Structs§
- Alias
Change - A change of a cell the scheduler has to announce because the write that caused it was made through a different name for the same storage.
- Alias
Window - A sub-range of a root cell:
widthbits from bitlo, of memory rowrowwhen the root is a memory (an unpacked array’s element). - Arena
- The one design-wide flat SoA backing store (ST-007: grouped by storage
tier, not a per-signal heap object model).
inlineholds everybit_width <= 64signal as a packedu128(val low 64 / xzmask high 64);wide_aval/wide_bvalhold every wider signal and every memory element, word-aligned, at identical relative offsets in both planes (ST-009);inline_2s/wide_2sare the 2-state-build counterparts (Task 10 exercises them; this task only reserves the fields). - Arena
Snapshot - ST-098: the one generic slice-granular checkpoint/restore primitive’s
data — see this module’s top doc comment, deviation 4, for why
rangeis a fifth field beyond the plan’s literal list, and deviation 5 for whybuild_mode/inline_2s/wide_2sexist beyond that (only one of{inline, wide_aval, wide_bval}/{inline_2s, wide_2s}is ever populated for a given snapshot — whichever plane-pairbuild_modesays is actually live — the other stays emptyVecs). - Change
Delta - The bits one committed update changed, as plane words (
aval/bval, theWideencoding):lo_wordis the plane-word index ofold_a[0], so a windowed update of a huge vector carries only the words it touched. A bit/part-select event control (LRM 9.4.2) compares the selected bits ofoldandnewto decide whether its operand changed, and takes an edge on the select’s least-significant bit. - Change
Result - ST-109’s exact shape:
commit_write’s return value. - Dispatch
- The fixed 3-role VC listener dispatch table (ST-073, ST-074). See this module’s doc comment for why this is 3 named fields, not a collection.
- Drive
Strength Pair - A driver’s own strength for each value it might drive (state.md §4):
s0applies when this driver is driving0,s1when driving1; drivingXreduces tomin(s0, s1)(see [effective_strength]). - Driver
Entry - One driver’s own private contribution slot plus its strength (ST-034):
sourceis aStateCellIdthis driver alone writes to (never shared read-modify-write storage with any other driver or withresolved). - Driver
Set - The K+1 slots design (ST-034):
resolvedis one moreStateCellId(StateEngine::alloc_cell) than theKentries indrivers— never a single shared slot every driver writes through. Hand-built by every test in this task (see this module’s own top doc comment, Scope note). - Frame
Arena - The STATE-owned backing storage for every
process::ActivationRecordthis crate hands out (ledger ST-103, ST-104, ST-110). Exactly three flatVecs, one perArenaRange-typed field anActivationRecordcan embed — see this module’s doc comment for why there are exactly three and not, say, one shared buffer. - Instance
Base - One concrete instance’s base index into the two global arrays, relative
to which every one of its template’s template-relative
super::SlotOffsetvalues must be added (ST-129) to get a real address — that addition is ENGINE’s job, never performed here. - Instance
Handle - The concrete type this plan’s header design decision makes
SimHandlepoint at (Task 8 adds theSimHandleconversion).layout/arenaare private raw pointers; they stay valid for the life of this handle (never merely for the life of theStateEnginethat minted them — see below) for two independent reasons (review fix, Task 7 r1 — the original comment here conflated them and was wrong aboutarena): - NbaWindow
- A nonblocking write to part of a huge signal, in plane words:
aval/bval/maskcover the plane words fromwindowon. - NetLayout
- A net member’s electrical classification, when known (ledger ST-141).
- Region
Assignment - This task’s stand-in for the netlist/analysis track’s not-yet-built
static clustering pass’s real
RegionId/write-set output (ST-122) — a real caller eventually supplies these from that pass; this wave’s own tests hand-build them directly. - Region
Overlap Error - The loud, typed diagnosis
check_region_disjointreturns instead of a generic “overlap detected” (ARCHITECTURE §7 item 9’s “loud, typed, diagnosable” discipline applied here): names the offending cell and both of the (inassignments-slice-order) conflicting regions it was claimed by. - Rollback
Mark - An opaque log-length marker (ST-036) — see
UndoLog::checkpoint_marker. The wrapped index is absolute over the log’s entire lifetime (it includes entriesUndoLog::fossil_collecthas already trimmed), never merely an index into the log’s currently retainedVec— seeUndoLog::rollback_to’s own doc comment for why that distinction is what makes the fossil-horizon check correct. - Slot
Descriptor - One signal’s slot within a
StateLayout(state.md Key Data Structures; ledger ST-141). - Slot
Location - The already-absolute (base already added) address
StateEngine::commit_writereads/writes at; bothInstanceHandle-relative accessor calls andStateCellId-keyed calls resolve down to this shape before calling in. - Slot
Offset - Compile-time layout query result STATE hands to CODEGEN (state.md §3: “baked
into compiled kernels as LLVM constants”; ledger ST-027, ST-037, ST-129,
ST-134, ST-135). Pure Rust (not
#[repr(C)]) — this crosses the CODEGEN/STATE boundary as ordinary Rust values at compile time, not as bytes across the compiled-kernel ABI, so it has no FFI-layout obligation. Task 7 addsPartialEq(previouslyClone, Copy, Debugonly):slot_of(ST-129) is required to return a byte-identicalSlotOffsetacross repeated calls regardless of interveningallocate_instancecalls, and the direct field-by-field way to prove that in a test is a structural equality check, not aDebug-string comparison. Every field is itselfPartialEq(SlotClassalready derives it; the rest are plain integers), so this is a safe, non-lossy derive addition. - Snapshot
Ring - A bounded ring of
ArenaSnapshots: “current” (the most recently pushed entry, ring index 0) plus up todeptholder entries. Never retains more thandepth + 1entries, no matter how many timesSelf::pushis called – the “a design with no$pastretention need pays no retention cost beyond entry 0” guard (seesnapshot_ring_depth_0_design_allocates_no_ringbelow). Whether a ring is allocated at all for a given instance is a decision this type does not make –sched::control::Engineonly ever constructs one when the design has at least one assertion/clocking-block/$pastsite to begin with (§1.4’s “not every instance, to avoid taxing designs with no SVA at all”); a design with none never callsSelf::newand pays nothing. - State
Arena #[repr(C)]FFI view of the arena’s storage planes (ST-145) — the shape a compiled kernel’s accessor-ABI functions index through.wide_aval/wide_bvalarenullin a 2-state-compiled binary.- State
Cell Id - Opaque per-signal handle, STATE-assigned (scheduler.md: “STATE-owned opaque
handle”; ledger ST-109, ST-111, SC-037). Distinct from
vj_abi::SlotId:SlotIdis the ABI-facing, compile-time-constant index CODEGEN bakes into IR;StateCellIdis the in-process (non-FFI) handle the scheduler/determinism/ runtime Rust code passes around at simulation time. STATE’s own implementation is free to make them numerically related, but the two names stay distinct contract types because their callers (CODEGEN vs. the scheduler) are on opposite sides of the ABI boundary. - State
Engine - STATE’s top-level owned state (arena storage + the compiled template set)
— review fix:
arena/templatesareRc-wrapped, notBox-wrapped or embedded by value. ASimHandle/InstanceHandleminted bySelf::allocate_instancemust stay valid for the life of the simulation run and cross the compiled-kernel FFI boundary, so the raw pointers it stores must surviveStateEngineitself being moved — returned by value from a constructor, pushed into aVec, or embedded in a future root object are all ordinary things a caller does (this task’s own regression test exercises exactly this). Witharena/templatesembedded directly, any such move would silently dangle every previously-minted handle — no compiler diagnostic, UB on the next accessor call. - State
Kernel CtxFields - ST-131: this struct names only the fields STATE owns. The full
KernelCtxa compiled kernel actually receives (current sim time, the rest of the suspend/resume contract) is jointly defined by ENGINE/CODEGEN and is out of this crate’s scope — it is not redefined here. This is a documented sub-shape other tracks’ realKernelCtxembeds (by value or by reference), never a claim that STATE owns or defines the whole thing. - State
Layout - Compile-time layout for one unique
(module,params)template (state.md Key Data Structures; ledger ST-140). OneStateLayoutper distinctcrate::netlist::TemplateKey(Task 5’sTemplateTablemaps keys to these);inline_words/wide_wordsare the template-relative word countsArenabulk-allocators (Task 7) reserve per instance. - Template
Registry - Task 7’s owned,
'staticsubstitute fordedup::TemplateTable<'d>(see this module’s top doc comment) — the minimal(TemplateKey, StateLayout)registryStateEngineactually needs after elaboration, once thesv_lang::Design-borrowing dedup walk itself is done. - Template
Table - One entry per unique
(module,params)template;templates’ insertion order is first-seen order during the deterministic DFS walk below — ST-064’s “identical offsets across runs” precondition falls out of that determinism, not a separate sort. - Trireg
Charge trireg’s own charge-decay state (state.md §4/§6): stored inStateEngine’s own side table (instance.rs’strireg_chargefield), never as a normalDriverEntry—triregdecay timing itself is a TIMING-subsystem hook this task only stores state for, not implemented here.- UndoLog
- ST-036: the per-thread undo/reverse log — see this module’s top doc
comment for why it is a plain, caller-owned value (like
()) rather than aStateEngine-owned field. ImplementsPreWriteHook: everycommit_write(cell, new, &mut log)call appends(cell, old, at)here before the store happens (Task 8/ST-091’s own ordering guarantee), giving that hook its first real body. - VcRecord
- The VC-buffer’s one record shape (ST-079, ST-109) — later
drain_committed_changesconsumes this type as-is, never redefined. - Worker
Slot - Opaque handle to one thread’s registered speculative VC buffer, returned
by
StateEngine::register_worker_thread.pub(crate)inner index: see this module’s top doc comment, deviation 1.
Enums§
- Build
Mode - Whether an
Arenabacks a 4-state (aval/bval, X/Z-capable) or 2-state (inline_2s/wide_2s, val-only) compiled binary. Feeds Task 10’s 2-state build path; this task only allocates/exposes the storage, it does not yet implement 2-state read/write semantics. - Charge
Strength trireg’s charge-strength lattice — kept separate fromDriveStrength(state.md §4:triregcharge decay is not part of the ordinary K+1 drive-strength foldcombine_bitperforms).- Default
Scope Error - Task 8 (sva T8,
docs/superpowers/plans/2026-10-03-sva.md): LRM 1800-2023 14.12’sdefault clockingand 16.15’sdefault disable iff– the scoping half only (which single declaration, if any, covers a given scope): resolving the lexical-nesting/override rules both clauses state almost verbatim (“valid only within the scope containing the declaration … as well as any nested module[s] … It does not include instantiated modules” – 14.12; “provides a default … to all concurrent assertions in the scope and subscopes … the default extends to any nested module … However, if a nested module … has a [its own] declaration, then that … overrides any default … from outside” – 16.15). The resolution-rule half of 16.15 (composing this against an assertion’s own explicitdisable iffclause, rules (a)/(b)/(c)) is T27’s job, consumingdefault_disable_of’s result – not reimplemented here. - Drive
Strength - The 4-level drive-strength lattice (state.md §4 simplifies the LRM’s
8-level charge/drive split to these 4 for resolution purposes).
Ord/PartialOrdare hand-written, not derived: the plan pinsSupply > Strong > Pull > Weak, the reverse of this enum’s own declaration order (declaration order is what#[derive(Ord)]would use). - Driver
Error - The loud, typed rejection [
combine_bit]/resolve_net_stepreturn instead of panicking or silently guessing a winner for a net kind this fold cannot resolve (ARCHITECTURE §6.5’s “hard-error, not silently wrong” fornettype...with, applied to this crate’s ownNetKindenum per ARCHITECTURE §7 item 9). - Edge
Kind - Mirrors
sv_lang::EdgeKind’s four variants (ledger SC-045, SC-067, SC-071, NL-047, NL-083). Kept as this crate’s own copy (rather than a re-export) becausevj-sim’s cross-track contract layer does not depend onsv-langin this wave (seedocs/CONTRACTS.mdopen questions); thenetlisttrack owns the real conversion once it wires thesv-langdependency for its own elaboration work. - Four
State Value - STATE’s cross-subsystem four-state value representation (state.md §3/§5,
ledger ST-008, ST-009, ST-099, ST-120):
Narrowmirrors the accessor ABI’s FIXED inlineu128word (ARCHITECTURE §6.2 / ST-008:valin the low 64 bits,unk/xzmask in the high 64 bits, regardless ofbit_width—vj_abi::bit4-compatible; notvj-codegen::value’s internal, width-tighti(2N)LLVM packing, which uses a different bit offset for any width < 64 — seevj_abi::accessor’s doc comment);Widemirrors theaval/bvalword planes (vj_abi::WideView-compatible). Reference/introspection shape only (VPI/$display/debugger/harness) — never the codegen-emitted hot path, which calls the accessor ABI directly. - Huge
Commit - What
huge_commitdecided; the caller (sched::kernel_adapter, which owns the scheduler hooks this crate layer cannot name) carries it out. - Layout
Error - The loud, typed error this and every later layout task returns instead of
silently skipping a member kind this plan claims to handle (ARCHITECTURE
§7 item 9 applied to
SymbolKind). - Listener
Role - The fixed, small listener-role table state.md §5 dispatches value changes to.
- NetKind
- Mirrors
sv_lang::NetKind’s variant set minusInterconnect(state.md §4: an interconnect net never gets a slot at all, so it has noNetLayoutvalue to represent) and minus theUnknownerror placeholder (never a real declared net’s kind). Kept as this crate’s own copy rather than a re-export ofsv_lang::NetKindso this module’s exhaustive-match discipline (ARCHITECTURE §7 item 9) applies to a type this crate owns, independent ofsv_lang’s own variant set ever changing underneath it. - NetShape
- The multi-driver resolution shape a net’s storage takes (ledger ST-141):
how many distinct strength-bearing drivers
NetLayout’s owning net has and whether the full K+1 strength lattice must be evaluated to resolve it. - Slot
Class - The storage tiers state.md §1 splits every slot into (ledger ST-020..ST-024, CG-107, CG-163).
Constants§
- EVENT_
CELL_ WIDTH - Width of a design-declared
eventvariable’s cell (state::layout,vj::run::signal_slots_of) – a 2-stateSlotClass::Widecell that compiled code (vj-codegen::expr::lower_event_trigger) treats as two 64-bit halves: the low half COUNTS triggers, the high half holdstick + 1of the most recent trigger (0 = never), which is whate.triggeredcompares against the current time. Counting rather than toggling matters because blocking writes are flushed once at segment end: two toggles in one segment would cancel and report no change.
Traits§
- Force
Observed - The corresponding runtime guard for external writes (ST-122’s own
acceptance text: “an external write (force/release/vpi_put_value) never
performs a direct disjoint-range write, only a serialized
ForceObserved/on_force_observedpath”).driver::force_driver/release_driver(Task 14, retrofitted by this task) each call every listener registered viaStateEngine::register_force_observed, so a future partitioning/independence assumption can invalidate itself the instant an externalforce/vpi_put_valuetouches a region-crossing net, rather than trusting a now-stale static classification (ARCHITECTURE §4/§9). - PreWrite
Hook - The ST-091/ST-031 “hook present in the calling convention from the first
freeze” requirement made concrete now:
commit_writetakeshook: &mut dyn PreWriteHookas a required parameter, not an optional add-on, so a later real undo-logPreWriteHookimplementer slots in without touching this signature or any of its call sites. - Pure
Kernel - ST-132: a marker trait, no methods. A
ProcessKernelFn/ProcessFnimplementation that also implementsPureKernelis asserting the contract ST-132 requires: it is derivable purely from(base, ctx), with no other mutable state (no hidden thread-local/global) reachable from inside it. This crate cannot compel a compiled kernel to implement this trait (CODEGEN’s own IR emitter, out of this wave’s scope, would need a#[forbid(...)]-style procedural check for a compiler-level guarantee) — STATE’s own enforcement mechanism this wave is the structural lint test below: proving that nothing STATE itself exposes to a kernel author encourages violating the contract (no STATE-owned API hands out a thread-local or global mutable handle a kernel could close over instead of going through(base, ctx)). - Signal
Access - STATE owns the one canonical signal read/write/subscribe primitive
(ARCHITECTURE §2); RUNTIME’s VPI/FST/
$display/debugger hosts are pure consumers of this trait, never a second implementation of signal access (vj-runtime::signal_consumerdemonstrates this by depending on it). - Value
Change Sink - Called by STATE/NETS after any committed write or net resolution (scheduler.md §4: “the single, uniform fan-out point for variable writes AND net resolution”; ledger SC-071, RT-005).
Functions§
- bits_
to_ aval_ bval bits(LSB first) as IEEE 1800 aval/bval word planes, at least one word.- bits_
to_ four_ state - Packs a slice of
sv_lang::Bitinto STATE’s cross-subsystemFourStateValue(ST-010):<= 64bits pack aNarrow(u128)withvalin the low 64 bits andunk/xzmask in the high 64 bits (ARCHITECTURE §6.2 / ST-008’s FIXED accessor layout, independent of width), built bit-by-bit throughBit4::to_val_unk;> 64bits packWide{aval,bval}word planes throughBit4::to_aval_bval(ST-148’s wide-plane polarity table) —bits[0]is bit 0 of both representations. - build_
template_ layout - cell_
for_ slot - check_
region_ disjoint - A build-time check (ST-122) confirming no
StateCellIdappears in more than oneassignmentsentry’scellsset. Does not itself allocate region-disjoint arena sub-ranges (see this module’s top doc comment) — this function’s only job is the checkable invariant.engineis accepted (matching the plan’s pinned signature and this crate’s convention of every region-facing query taking the owningStateEngine) but this wave’s check is purely a property ofassignmentsitself — a future wave that also validates eachStateCellIdagainstengine’s own allocated cell table (StateEngine::alloc_cell) can extend this function without changing its signature. - class_
static_ instance - Classes plan Task 4 (
docs/superpowers/plans/2026-10-03-classes.md, LRM 8.9): the(InstanceId, TemplateKey)pair [StateEngine:: allocate_class_static_singletons] uses for oneClassTemplateId’s static-property singleton segment — a deterministic, pure function ofclass_templatealone (never re-derived differently by two call sites), so every caller (that oneallocate_instancecall, and every later foreign-slot reference aClass::static_prop/obj.static_propaccess mints) agrees on exactly which synthetic instance a given class template’s statics live in. - clocking_
blocks body’s clocking blocks, each with its input (and inout) clock variables, in declaration order – the extra slots of a template, in the order both the layout and the codegen signal map give them.- compile_
source - This track’s own copy of
vj-codegen/src/frontend.rs::compile_source(kept local rather than depending onvj-codegenfor a 4-line helper); reused by every later task’ssv_langfixture tests in this crate. - constant_
expr_ bits - The bits (LSB first) of the constant expression
e, at its own type’s width.Nonewheneis not an integral constant. - copy_
slot_ quiet - Copies
src‘s current value intodstof the same instance without reporting a value change: the sampled value functions’ hidden P/S cells (crate::sva::sampled) are history, not signals – no listener waits on them, no waveform shows them, and their updates must not wake a process.srcmay be a foreign slot (a hierarchically connected signal);dstis always one of the instance’s own cells, of the same class and width assrcby construction (hidden_slotsclones the source’s shape). - default_
clocking_ of - LRM 14.12’s resolved default clocking block for
scope: the nearest enclosing scope’sdefault clocking clocking_identifier;reference or inline[default] clocking ... endclockingdeclaration, as an actualClockingBlockSymbol–Noneif no scope in the chain declares one. - default_
disable_ of - LRM 16.15’s resolved default disable condition for
scope: the nearest enclosing scope’sdefault disable iff expr;declaration, together with theSymbolof the scope it was declared in – “Any signals referenced in the disable iff declaration that are resolved using scopes will be resolved from the scope of the declaration” (16.15), so a later compiling pass (T27) must bindexpr’s names against that scope, never against the querying assertion’s own (potentially more deeply nested) scope.Noneif no scope in the chain declares one (16.15 rule (c), “no inference … equivalent to … a 1’b0 disable condition”). - force_
driver force/release/deassign(ST-055), modeled as a synthetic, singleton-partition dynamic driver: allocates one moreDriverEntry(Supply-strength, so it always wins outright per the lattice above, matchingforce’s LRM override semantics), seeds its private contribution cell withvalue, pushes it ontoset.drivers, and returns itsStateCellIdso the caller can laterrelease_driverit.- four_
state_ of_ constant - Extracts a
FourStateValuefrom asv_lang::ConstantValue, reusingsv_lang’s own constant-folding machinery rather than a parallel evaluator (ST-012):Nonefor any non-integer constant (real/string/null/etc — this function only speaks the 4-state integer representationFourStateValueexists for). - four_
state_ to_ owned_ svint - Builds a
sv_lang::OwnedSVIntof the givenwidth/signedness from aFourStateValue, reusingsv_lang’s own owned-integer type rather than a locally-defined equivalent (ST-011): starts fromOwnedSVInt::create_fill_x(every bit X, matching this function’s honest default for a bit this loop hasn’t visited yet) and threads each bit’s known (0/1) or Z state in viaset_range/create_fill_z— an X bit is left untouched (already correct from the fill), a 0/1/Z bit overwrites its single-bit range. - huge_
commit - Commits the dirty window of
(handle, slot)’s mirror to the planes. - huge_
commit_ full_ done - Called after the
HugeCommit::Fullwrite: the write itself went throughwrite_slot, which invalidated the mirror; a mirror that is still current (revalidate) is made valid again. - huge_
mark - Widens the dirty window of
(handle, slot)’s mirror by the value bits[start, start + len)(clipped to the signal;len <= 0is a no-op, which is what an out-of-range select that wrote nothing passes). - huge_
nba_ window - The windowed form of
sig[start +: len] <= image:imgis the PK image of thelen-bit right-hand side (val plane at bit 0, unk plane at bitlen). The target bits[start, start + len)are clipped to the signal, as a part-select write clips;Nonewhen nothing is left (the write has no effect). CostsO(len), neverO(width). - huge_
prime - The process shadow of the huge signal
(handle, slot)ofwidthbits: the signal’s mirror, valid and current.force_rebuildre-reads the planes even from a valid mirror – for the caller that knows external code wrote them behind the mirror’s back. - own_
slot_ count - The number of slots of
handle’s instance’s own layout – the first foreign slot’s number. - packed_
words bits(LSB first) in codegen’s packed form –(unk << W) | valforW = bits.len()– asceil(2W / 64)little-endian words (at least one): a collection element’s stored form (crate::collections).- read_
by_ hier_ path - ST-118: resolves
paththroughnetlist’s own hierarchical-path table, then STATE’s ownInstantiatedSignalId -> StateCellIdmap, then reads the live value throughSignalAccess::read— the exact same primitive every other STATE consumer (the accessor ABI,driver::resolve_net_step) reads through (ST-152’s “no second, independently-populated store” discipline applied to introspection too). ReturnsNone, never a fabricated/zero value or a panic, for a pathnetlistcannot resolve, or (structurally impossible in practice onceallocate_instanceis the only producer ofInstantiatedSignalIds this map ever sees, but checked anyway rather than.unwrap()ed) for onenetlistresolves to a signal thisStateEnginenever allocated storage for. - read_
inline_ 2s - Task 13 — 2-state build-mode arena and read/write family (ledger ST-100, ST-101, ST-102, ST-139).
- read_
slot - Reads the current word(s) stored at
loc, without any diffing —commit_write_at’s ownoldread (Task 9 retrofit: a free function over&Arena, not aStateEnginemethod, so it is callable from the accessor ABI’sInstanceHandle-only call sites too — see this module’s top doc comment). - read_
wide_ 2s - Reads
elem_word_countwords starting atword_offsetfrom the wide 2-state plane, no diffing. - real_
sv_ get_ mem_ word - The production binding of
sv_get_mem_word(seereal_sv_get_scalar). - real_
sv_ get_ scalar - The production binding of the
sv_get_scalarABI symbol:sv_get_scalarafterresolve_foreign_slot. - real_
sv_ get_ wide - The production binding of
sv_get_wide(seereal_sv_get_scalar). - real_
sv_ rt_ inline_ ptrs const u128 *const *sv_rt_inline_ptrs(SimHandle): for each slot number ofhandle’s instance, the addresssv_get_scalarwould read (null where the slot needs the accessor: notInline, or a windowed alias). JIT code calls it once per segment and loads anInlinesignal directly, so a process activation costs one call rather than one per signal. Valid for the rest of the kernel call (InstanceHandle::inline_ptr_table). Lives here, not inaccessor_impl.rs, whose source-scan test forbids raw pointer returns (this is a read-only table, never base+offset arithmetic).- real_
sv_ rt_ slot_ owner SimHandle sv_rt_slot_owner(SimHandle, SlotId): the instance whose storageslotofhandleis –handleitself for one of its own slots, the instance a foreign slot names otherwise (seeset_foreign_slots). A hierarchical call into another instance (u1.f(), LRM 23.6) passes this as the callee’s instance handle, so the callee’s memories and block events areu1’s own.- release_
driver - The other half of
force_driver: removesforced’s oneDriverEntryfromset.driversand re-runsresolve_net_step, unwrapping itsOk—force/releaseare only ever exercised on ordinary, non-UserDefinednets in v1 (this module’s top doc comment, Scope note), so theErrarm is unreachable from this function and it never wraps it further. - resolve_
foreign_ slot (handle, slot)itself for one of the instance’s own slots; for a foreign slot (seeset_foreign_slots), the instance and slot it names. Every production entry point that reads or writes a slot’s storage for a compiled kernel resolves through this first (real_sv_get_*,real_sv_set_mem_word, force); a cell lookup needs no resolving (a foreign slot’s cell is in the instance’s own cell table).- resolve_
mem_ row - Task 11 (ST-138): state.md §3’s pinned formula, verbatim:
word_offset' = word_offset + row_stride_words * row_index,row_indexa runtime value. Panics (never a silent OOB read/write) ifloc.class != SlotClass::Memoryorrow_index >= loc.num_rows as u64— ARCHITECTURE §7 item 9’s “loud, never silent” discipline. The returnedSlotLocationstill hasclass: SlotClass::Memoryand the SAMEelem_word_count(the layout builder already setselem_word_count == row_stride_wordsfor every realMemoryslot — one row’s own word count — so the resolved location slots directly into the existingread_slot/write_slot/commit_write_atprimitives with zero further change). - resolve_
net_ step - Reads all
Kcontribution cells viaSignalAccess::read, folds them bit-by-bit through [combine_bit] (propagating the firstErrout via?, never partially committing some bits and rejecting others), andcommit_writes the result intoset.resolvedonly on a fully-resolvedOk— schedulable exactly like any other write (ARCHITECTURE §6.2: this function is the pure function ENGINE later wraps as a synthetic sensitivity-driven process, not the scheduling itself). - resolve_
strengths - Per-bit resolution of
valueslikeresolve_values, keeping each bit’s strength (LRM 28.12;Noneforz) for%v(LRM 21.2.1.5). Index 0 is bit 0.supply0/supply1nets areSupply. - resolve_
values - Resolves one
width-bit net ofnet_kindfrom its drivers’ current values and strengths (each full-width; a bit a driver does not drive isz), per bit through [combine_bit]. Asupply0/supply1net is its constant unless a supply-strength driver disagrees (x). The result is shaped Narrow (up to 64 bits) or Wide. - set_
foreign_ slots - Task F3 (
docs/superpowers/plans/2026-09-27-wave-A2-slice-finish.md, CG-125/NL-035): resolvesslot(the sameSlotIdsv_get_scalar/sv_set_scalaralready address by) to the absoluteStateCellIda synthetic inter-instance port-connection process needs forcrate::sched::SchedulerOps::commit_blocking_write/crate::sched::StaticSensitivity(registering a wake on the source side, writing through the canonical commit path on the destination side). Every otherStateCellIdin this crate is minted directly byStateEngine::alloc_cell/allocate_instance’s own per-slot loop (InstanceHandle::cell_for_slot,pub(crate)); this is the one place a caller outside this crate (vj’s hierarchy pipeline, which holds aSimHandle+SlotIdpair from its own signal-slot bookkeeping but never runsallocate_instance’s loop itself) needs to look one back up. Giveshandle’s instance its foreign slots: slotown + k(whereownis the instance’s own slot count, returned) namestargets[k], another instance’s own slot. A target that is itself a foreign slot is followed to its owner. - set_
foreign_ slots_ windowed set_foreign_slotswhere a target may be a window of its slot – a ref port bound to a select (IEEE 1800-2023 23.3.3.2, 13.5.2): such a foreign slot is a view of the target (state::alias) with its own cell, so a wait on it wakes only when the window changes.- set_
mem_ word_ reporting_ change sv_set_mem_word’s body, returning the memory’s whole-array cell and whether the row’s stored value actually changed – what a scheduler-aware caller (sched::kernel_adapter::real_sv_set_mem_word) needs to wake processes sensitive to the memory.- splice_
window rootwithwindowreplaced bynew(inroot’s own representation).- sv_
get_ mem_ word - Task 12 (ST-024, ST-025, ST-114): memory-word accessors.
slotaddresses the wholeSlotClass::Memoryarray the same waysv_get_wide/sv_set_wideaddress a wholeSlotClass::Widesignal ([slot_location_for] is shared, unchanged); the one extra step isresolve_mem_row, applied to that base location with the caller’s runtimerow_index, per state.md §3’s pinnedword_offset' = word_offset + row_stride_words * row_indexformula. Both fns panic (never silently read/write past the array) ifrow_indexis out of bounds orslotdoes not resolve to aSlotClass::Memorylocation — seeresolve_mem_row’s own doc comment for the exact panic conditions. - sv_
get_ mem_ word_ inline - The
sv_get_mem_wordtwin ofsv_get_scalar_inline(ST-026, Task 12). - sv_
get_ scalar - Narrow (
SlotClass::Inline) scalar read (ST-020):vj_abi::accessor’s FIXEDvallow 64 bits /unkhigh 64 bits layout, read straight out of the arena’s inline plane athandle’s own base-applied word offset. - sv_
get_ scalar_ inline - Task 10 (ST-026): the concrete artifact ARCHITECTURE §7 item 1’s
“accessor-ABI as the contract with
alwaysinlinewrappers” resolves to on STATE’s side — a thin,#[inline(always)]Rust-level wrapper around theextern "C"fn above, a pure pass-through never a second, divergent implementation. CODEGEN is expected to call these (or emit its ownalwaysinline-attributed LLVM declaration of theextern "C"symbol directly — either way, STATE’s obligation is only that an inlinable entry point exists and is documented as the one sanctioned call shape). - sv_
get_ wide - Wide (
SlotClass::Wide) non-memory read (ST-022): a non-owningWideViewoverhandle’s ownaval/bvalplane words atslot’s base-applied offset —word_countwords starting at that offset in each plane, pervj_abi::accessor’s documented shape. - sv_
get_ wide_ inline - The
sv_get_widetwin ofsv_get_scalar_inline(ST-026). - sv_
set_ mem_ word - ST-025: the
sv_set_wide-shaped write counterpart, through the sameresolve_mem_rowstep and the samecommit_write_atprimitive every other write in this crate goes through — never a second, ad hoc write path.cellis this slot’s one whole-memoryStateCellId(the samehandle.cell_for_slot(slot.0)sv_set_wideuses; aSlotClass::Memoryslot mints exactly one cell for the whole array, not one per row — seeStateEngine::allocate_instance’s own per-slot loop), so a VC record from this fn reports “this memory changed”, identifying the row viaat/the caller’s ownrow_index, exactly assv_set_widealready does for a whole non-memory wide signal. - sv_
set_ mem_ word_ inline - The
sv_set_mem_wordtwin ofsv_get_scalar_inline(ST-026, Task 12). - sv_
set_ scalar - Narrow scalar write (ST-021): writes
valueand reports whether it changed by routing through [commit_write_at] — the same VC-detection primitiveStateEngine::commit_writeuses — never a second, parallel write path. Theextern "C"signature itself returns()(the frozen ABI type alias,vj_abi::accessor::SvSetScalarFn); the change report lands in the same speculative VC buffer every othercommit_write_atcaller’s changes do, observable viawrite::last_vc_record_forin tests. - sv_
set_ scalar_ inline - The
sv_set_scalartwin ofsv_get_scalar_inline(ST-026). - sv_
set_ wide - Wide non-memory write (ST-023): copies
value’selem_word_countwords out of the caller-suppliedWideViewinto an ownedFourStateValue::Wideand routes through [commit_write_at] — the wide-tier sibling ofsv_set_scalar, through the identical shared primitive. - sv_
set_ wide_ inline - The
sv_set_widetwin ofsv_get_scalar_inline(ST-026). - svint_
bits v’s bits, LSB first, at its full width (sv-lang 0.1.17 expands every width; before it, values past 1024 bits came back empty).Noneif the slice ever disagrees withbit_width()– never a fabricated value.- synthetic_
z_ layout - A layout of one slot per entry of
widthsholding no declared signal – the contribution cells of resolved nets’ drivers (vj’snets): each Inline or Wide by width, starting all-z(not driving). - synthetic_
z_ layout_ rows synthetic_z_layoutwhere cellkwithrows[k] > 0is aMemoryslot of that many rows ofwidths[k]bits, every row all-z: the contribution cell of a driver of an unpacked array of nets, whose elements are resolved one by one (vj’snets). A row starts atfills[k](LSB first) when that is non-empty, else all-z: a user nettype’s driver has noz(its data type’s default value instead); a non-memory cell with a non-emptyfills[k]starts at it too (a specify path’s staging cell startsx, LRM 30.5.1).- window_
value - The value of
windowwithinroot:Narrowup to 64 bits,Widebeyond, as the storage class of a slot of that width is. - write_
inline_ 2s - Writes
valueatword_offsetiff it differs from the currently-stored value (plainu64equality – ST-102’s “without any mask comparison”: there is no mask half in this family to compare). Returns whether a real change occurred. - write_
slot - Stores
newatloc. Onlycommit_write_at(below) calls this in the ordinary write path, and only afterfour_state_changedhas already confirmed a real change — see this function’s own SAFETY comments for the single-logical-writer argument that makes the twounsafeArenaaccessor calls sound. - write_
wide_ 2s - Writes
valuesstarting atword_offsetin the wide 2-state plane iff they differ from what’s currently stored (element-wiseu64equality, no mask half). Returns whether a real change occurred.