Skip to main content

run_all

Function run_all 

Source
pub fn run_all<'a>(
    node: &'a mut dyn ComponentNode,
    ctx: &'a mut RustdvCtx,
) -> Pin<Box<dyn Future<Output = Result<(), TestError>> + 'a>>
Expand description

Bottom-up: every component’s run fires, children first (D48). The walk is boxed-recursive because dyn_run yields a boxed future we await, and the children’s borrows are held across those awaits.

Concurrent (D82). Every component’s run makes progress together — the analog of UVM forking each run_phase. The children’s runs are joined (SystemVerilog’s fork...join), and the node’s own run joins them, so a producer that blocks on a full FIFO and a consumer that drains it can both proceed. Sequential awaiting was the earlier behaviour and deadlocked on exactly that shape.

The futures borrow the tree rather than being spawned: spawn is 'static-bound and would force the component tree into Rc/RefCell, whereas this scope already owns it. spawn stays for work that must outlive the phase (BFM loops, monitor collectors — D59/D61).

Scope: siblings are concurrent; a node’s own run follows its subtree. All of a node’s children (and their subtrees) run joined together, then the node’s own run body executes. That is what Rust’s borrow rules allow: Component::run takes &mut self, which includes the child fields, so one &mut node cannot be split into “this node’s own state” and “its children” — a parent’s run future and its children’s run futures cannot coexist.

D82b lifts that limit for RustdvComp children. A RustdvComp slot holds a Box, so the box can be moved out of the parent for the duration of the run phase. Once out, it has no borrow relationship to the parent, and the two futures can be driven together. The boxes go back before the post-run phases walk the tree.

So a node’s run proceeds in two steps:

  1. In-place children firstOption<T>, Vec<T> and plain T fields cannot be moved out of their parent, so they keep the earlier behaviour: joined with each other, completing before the parent’s own run begins. Legacy chapters (ch24, ch25, tinyalu_tb) are all of this shape and hold parents with no run body, so nothing changes for them.
  2. Taken children joined with the parent’s own run — the shape D78 prescribes for all new code, and the one the sequence chapters need.