pub enum ResolvedSuspend {
Delay(u64),
DynamicDelay,
Edge {
cell: StateCellId,
edge: EdgeKind,
},
Done,
RepeatEdge {
count: u64,
cell: StateCellId,
edge: EdgeKind,
},
EdgeWithGuard {
cell: StateCellId,
edge: EdgeKind,
guard_fn: extern "C" fn(SimHandle) -> bool,
},
ForkJoin {
join_kind: JoinKind,
base: u32,
count: u32,
},
WaitFork,
ByRequest,
EventList {
base: u32,
count: u32,
},
}Expand description
The compile-time-resolved suspend shape build_eval_result encodes.
Deliberately not vj_sim::process::cfg::SuspendPoint (an
sv_lang-carrying, frontend-gated type): this module – and the whole
sched module tree – must build with --no-default-features (D4), so
every type crossing this boundary is sv_lang-free. vj-codegen
resolves its own SuspendPoint (a constant delay tick count, or an edge
signal’s already-assigned SlotId) down to this shape before calling in.
Variants§
Delay(u64)
DynamicDelay
A delay computed at run time (#d, #(expr)): the kernel stores
the tick count with real_sv_rt_set_delay just before it returns.
Edge
Done
RepeatEdge
Task 6 (CG-081/CG-171): a single-cell, single-edge REPEAT wait –
count occurrences of edge on cell must fire before the process
resumes. Closes SuspendPoint::CycleDelay (##N, always reachable
via a Timed statement – FULLY resolved by this task) and would
close RepeatedEventControl (repeat(n) @(...), CG-081’s own name
for this kind) too, were that AST shape ever reachable from a Timed
statement at all – see vj-codegen::process_lower:: resolve_suspend_point’s CycleDelay arm and vj-sim::process:: cfg::SuspendPoint’s own doc comment for the full reasoning on both.
count is the RAW, un-multiplied cycle count – edges of cell
are counted LIVE at scheduler runtime (EventTerm::Repeat,
SC-052/SC-053, already built and tested), never pre-multiplied
against any period at codegen time (ARCHITECTURE §6.5).
EdgeWithGuard
Task 7 (AB-096/CG-082): a single-cell, single-edge wait carrying a
compiled re-check guard – the wait(expr)/iff-qualified shape.
See [RescheduleReqLayoutProposal::from_single_edge_with_guard]’s
own doc comment for the full ABI-budget reasoning behind reusing
a/b instead of a ninth struct field, and for why this is NOT
extended to RepeatEdge in this pass.
ForkJoin
R-run Task 17 (PR-047/PR-061/PR-085): a fork ... join
(JoinKind::All only – this task’s own scope) suspend. Unlike
every other variant above, a fork/join site’s real payload (one
super::SpawnSpec per branch) is NOT self-contained here – it is
compile-time-known (branches are static source, not a per-instance
runtime count) but too large to fit RescheduleReqLayoutProposal’s
frozen 24-byte budget for more than ~2 branches, so vj-codegen
instead materializes a real, compile-time-constant
Vec<SpawnSpec> fork table (one per compiled program, growing as
each fork/join site is lowered) and this variant carries only
base/count, an crate::process::ArenaRange-shaped reference
into it – exactly [RescheduleReqLayoutProposal::from_fork_join]’s
own, already-specified KIND_FORK_JOIN wire shape (docs/CONTRACTS.md
open question 8 / D1a’s own “no allocator, no STATE-owned storage”
concern does not apply here: this table is compiled INTO the
program as an ordinary Rust Vec a CompiledKernelProcess is handed
at construction time – see decode_reschedule_with_fork_table).
WaitFork
wait fork; (SC-125) – see reschedule_req_proposal::KIND_WAIT_FORK.
ByRequest
p.await() / p.suspend() (classes plan Task 13) – see
reschedule_req_proposal::KIND_BY_REQUEST.
EventList
A wait on several terms (@*, @(a or posedge b), wait(expr) on a
wide or multi-signal condition, @(a) any-change): the terms live in
the program’s wait table ([base, base+count), see WaitTableEntry),
encoded as KIND_EDGE_LIST.