Skip to main content

Module process

Module process 

Source
Expand description

A2-PROCESS (sv-sim-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. SignalEventControl with posedge/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. See docs/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 the ProcessInstanceId registration-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 segmented super::cfg::ProcessCfg computes which compiler-generated temporaries (if any) also need one (PR-021, PR-016, PR-019). Ledger PR-015..PR-027, CG-100. See docs/design/process.md §3.

Structs§

ActivationRecord
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).
ArenaRange
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-owning Vec.
ForkFrame
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). children is a fixed ArenaRange into the engine’s dynamic fork-child table — never an owned Vec, the same memcpy-safety reason as ActivationRecord::frame. Its elements are crate::sched::ProcessId, not ProcessInstanceId: scheduler.md is explicit that “fork children are dynamically created ProcessIds not present in static elaboration,” so ProcessInstanceId (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 concrete ProcessIds are assigned dynamically at fork time and live in that out-of-line table, never inline here.
PredicateFn
The settled CondThunk shape for a SignalEventControl’s iff re-check AND wait(expr)’s own re-check (PR-106, A2-part2 Task 3): a plain extern "C" function pointer over the shared SimHandle, produced by exactly one compiler entry point, sv-sim-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.
ProcessInstanceId
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.
ProcessResult
ResumeInfo
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).
SubscriptionSetId
A precomputed, static subscription-set id for always_comb/always_latch’s implicit sensitivity (scheduler.md §4/§5) — O(1) resubscribe, computed once ever from AnalyzedProcedure::read_set().

Enums§

Effect
Rollback-safety classification per LoweredStmt/Segment (process.md §6), consumed by the engine’s Time-Warp commit policy.
FrameSlot
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, not Vec<u64> data (see ActivationRecord’s doc comment for why that distinction is load-bearing).
ProcessStatus
ResumeReason
WaitSpec
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 through ProcessStatus::Suspended.
WaitSpecStorage
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 is WaitSpecStorage, distinct from the richer WaitSpec the 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 already Copy (PredicateFn is a bare extern "C" fn pointer) so it is inlined directly; EdgeList’s term count is unbounded (an arbitrary-length @(a or b or c or ...)), so like ActivationRecord::frame it is instead an ArenaRange into a static, elaboration-time-built edge-term table (the concrete StateCellIds 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::slot arena-slot integer operand before it reaches accessor::build_get_scalar/build_set_scalar, so two processes in different WOCB partitions (region_ids) address disjoint arena-base bands: partition region_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) yields 0, 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 synthetic region_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 (sv-sim-codegen::process_lower’s prime_external_signals/flush_external_signals) and this task’s own unit test – never reimplemented a second time.

Type Aliases§

ProcessKernelFn
The compiled-kernel calling convention every process TEMPLATE compiles to (process.md §4). Not the literal ABI-crossing symbol — that is sv_sim_abi::ProcessFn (extern "C", using the frozen SimHandle/ EvalResult/RescheduleReq shapes 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 Rust fn pointer, deliberately not extern "C", since ProcessResult owns a heap-allocated field (WaitSpec::EdgeList’s Vec<..>, via ProcessStatus::Suspended) that is not FFI-safe by value. ActivationRecord itself is #[repr(C)]/POD (see its own doc comment) — it is the return type, not the activation pointer, that blocks extern "C" here.