Expand description
A2-PROCESS (vj-sim::process) — cross-track contract only: the process
template lowering shape shared between the A2-process track and CODEGEN
(process.md). Real liveness analysis / CFG construction belongs to the
A2-process track, not this wave.
Re-exports§
pub use cfg::SuspendPointKind;pub use cfg::suspending_statement_kinds;
Modules§
- cfg
- Task S3a (
docs/superpowers/plans/2026-09-26-wave-A2-slice.md): the CPS control-flow-graph builder and its Segment IR lowering, restricted to exactly the A2-slice’s two suspend kinds (Delay,Edge– i.e.SignalEventControlwithposedge/negedge). Ledger PR-004, PR-005, PR-006 (Delay/SignalEvent half only), PR-007, PR-008, PR-041, PR-042, PR-043, PR-044, PR-048, PR-069, PR-074, PR-114, CG-098, CG-099. Seedocs/design/process.md§§1-6. - dedup
- Task S5 (
docs/superpowers/plans/2026-09-26-wave-A2-slice.md): the process TEMPLATE dedup key (PR-028, PR-029, PR-030) and theProcessInstanceIdregistration-order tie-break (PR-075, PR-076, PR-077). - liveness
- Task S3b (
docs/superpowers/plans/2026-09-26-wave-A2-slice.md): the Activation Record frame layout – declared SV locals get a permanent slot unconditionally (PR-017, PR-018), and a backward liveness fixpoint over the segmentedsuper::cfg::ProcessCfgcomputes which compiler-generated temporaries (if any) also need one (PR-021, PR-016, PR-019). Ledger PR-015..PR-027, CG-100. Seedocs/design/process.md§3.
Structs§
- Activation
Record - POD, pointer-free, memcpy-checkpointable — the only per-instance execution state that must survive a suspend or a Time-Warp rollback (process.md §3; ledger CG-164, CG-176, ST-005).
- Arena
Range - A fixed, pointer-free reference to a contiguous range of STATE-owned arena
storage (word- or element-addressed, per the referencing field’s own unit).
Never an owning buffer — the one shape every
ActivationRecord-embedded field below uses in place of a heap-owningVec. - Fork
Frame - Fork/join bookkeeping (process.md §7: “construction only, no scheduling
semantics in v1”; ledger PR-086, fork/join family PR-001, PR-047, PR-061).
childrenis a fixedArenaRangeinto the engine’s dynamic fork-child table — never an ownedVec, the same memcpy-safety reason asActivationRecord::frame. Its elements arecrate::sched::ProcessId, notProcessInstanceId: scheduler.md is explicit that “fork children are dynamically created ProcessIds not present in static elaboration,” soProcessInstanceId(elaboration-derived, static-only per this file’s own doc comment above) structurally cannot name them. The branch count for a given fork site is statically known at lowering time; the concreteProcessIds are assigned dynamically at fork time and live in that out-of-line table, never inline here. - Predicate
Fn - The settled
CondThunkshape for aSignalEventControl’siffre-check ANDwait(expr)’s own re-check (PR-106, A2-part2 Task 3): a plainextern "C"function pointer over the sharedSimHandle, produced by exactly one compiler entry point,vj-codegen::process_lower:: compile_iff_guard– see that function’s own doc comment. Through Task 1 this shape was left an open question (process.md: “needs to be settled jointly with codegen’s dispatcher shape… not decided unilaterally here”); Task 3 settles it: a raw function pointer into a standalone, independently-compiled guard function, never a re-entry into a dedicated micro-segment. - Process
Instance Id - Stable, elaboration-order-derived tie-break key (process.md §6: “derived from a deterministic pre-order walk of the frozen Design’s instance hierarchy, never from allocation order or thread arrival”; ledger PR-075..PR-077, PR-118, DT-011, DT-031). The scheduler consumes this as its canonical cross-thread tie-break.
- Process
Result - Resume
Info - What woke a process (process.md §4
ResumeInfo/ResumeReason). - StmtId
- Opaque, minted 1:1 by CODEGEN per trap-eligible statement at lowering time (debugger.md; ledger CG-142, CG-149, CG-154, SC-104, SC-126, DB-034): stable only within one compile, never across recompiles (no hot-reload of source into a live debug session).
- Subscription
SetId - A precomputed, static subscription-set id for
always_comb/always_latch’s implicit sensitivity (scheduler.md §4/§5) — O(1) resubscribe, computed once ever fromAnalyzedProcedure::read_set().
Enums§
- Effect
- Rollback-safety classification per
LoweredStmt/Segment(process.md §6), consumed by the engine’s Time-Warp commit policy. - Frame
Slot - One frame slot’s compile-time SHAPE only (process.md §3
FrameSlot/FourStateI2N/WideFourState; ledger ST-103..ST-105): the number of u64 words the slot’s payload occupies. This is layout metadata CODEGEN consumes when computing a TEMPLATE’s fixed frame offsets (“Frame slot layout is decided once per process TEMPLATE… handed to codegen as a fixed struct layout”) — never the runtime payload itself, which is why it carries counts, notVec<u64>data (seeActivationRecord’s doc comment for why that distinction is load-bearing). - Process
Status - Resume
Reason - Wait
Spec - The ABI-facing resume contract (process.md §4
WaitSpec; ledger CG-169, CG-170, SC-085, SC-119, PR-012, PR-037) a compiled process kernel reports back throughProcessStatus::Suspended. - Wait
Spec Storage - The POD cache of the last-returned suspend reason, embedded directly in
ActivationRecord.docs/design/process.md§3/§4 names this exact split: the persisted field isWaitSpecStorage, distinct from the richerWaitSpecthe suspend/resume ABI exchanges with the scheduler on every call (“last-returned WaitSpec, re-derivable but cached for O(1) resume dispatch and for the debugger inspector”).Edge’s single term is alreadyCopy(PredicateFnis a bareextern "C"fn pointer) so it is inlined directly;EdgeList’s term count is unbounded (an arbitrary-length@(a or b or c or ...)), so likeActivationRecord::frameit is instead anArenaRangeinto a static, elaboration-time-built edge-term table (the concreteStateCellIds for a given suspend point are fixed once elaboration resolves the instance’s signals and never change for the life of the run, so this table is a read-only lookup, never a rollback hazard).
Functions§
- arena_
base_ offset_ for_ region - Task 10 (A2-part2, PR-122): the per-partition additive bias CODEGEN adds
to a
SignalSlot::slotarena-slot integer operand before it reachesaccessor::build_get_scalar/build_set_scalar, so two processes in different WOCB partitions (region_ids) address disjoint arena-base bands: partitionregion_id’s slots occupy[region_id * slots_per_region, (region_id + 1) * slots_per_region). A plain multiply, not a hardcoded zero –region_id == 0(v1’s only real value) yields0, leaving every real accessor call’s slot operand byte-identical to today’s unbiased value (this task changes zero observable behavior for any real v1 design); a caller that hand-sets a syntheticregion_id >= 1(no such partition exists yet – the WOCB analysis pass that would assign one is unbuilt) gets a real, disjoint, nonzero band, which is exactly what the codegen-side IR-inspection test proves. One definition, reused by both the real biasing call site (vj-codegen::process_lower’sprime_external_signals/flush_external_signals) and this task’s own unit test – never reimplemented a second time.
Type Aliases§
- Process
Kernel Fn - The compiled-kernel calling convention every process TEMPLATE compiles to
(process.md §4). Not the literal ABI-crossing symbol — that is
vj_abi::ProcessFn(extern "C", using the frozenSimHandle/EvalResult/RescheduleReqshapes so every field stays FFI-safe). This is the richer, process-track-internal Rust-level decoding of that call, matching process.md’s own explicitly-flagged scope (“proposed here at the logical (Suspend/ResumeArg) level only; the physical ABI needs to be pinned jointly with CODEGEN”) — an ordinary Rustfnpointer, deliberately notextern "C", sinceProcessResultowns a heap-allocated field (WaitSpec::EdgeList’sVec<..>, viaProcessStatus::Suspended) that is not FFI-safe by value.ActivationRecorditself is#[repr(C)]/POD (see its own doc comment) — it is the return type, not the activation pointer, that blocksextern "C"here.