Skip to main content

Crate rustdv

Crate rustdv 

Source
Expand description

§rustdv

A hardware verification framework in Rust: cocotb-style simulator coroutines plus a UVM-analog testbench library, rethought for Rust’s ownership model.

This is the facade crate (design-doc D2.5): it re-exports the public API so a testbench needs one dependency and one import:

use rustdv::prelude::*;

rustdv::vpi_bootstrap!();

#[rustdv::test]
async fn my_test(ctx: RustdvCtx) -> Result<(), TestError> {
    let dut = ctx.dut();
    // ...
    Ok(())
}

Re-exports§

pub use rustdv_gpi as gpi;
pub use rustdv_runner as runner;
pub use rustdv_sim as sim;

Modules§

channel
Channels: the TLM-1 replacement (design-doc §5.6, review-memo R6). Twelve pyuvm port classes become six methods on two types; direction lives in the type name; a mismatch is a compile error.
log
Sim-time-stamped logging in the book’s format: 2.00ns INFO ... (design-doc OQ-8: the tracing mapping is deferred; this minimal zero-dependency logger reproduces the output format the book teaches).
prelude
One-line import for testbenches (the from pyuvm import * analog).

Macros§

first
first!(a, b, ...) — first completed future wins; losers are dropped.
join
join!(a, b, ...) — wait for all.
vpi_bootstrap
Export the VPI entry points from the testbench cdylib. The simulator (vvp) dlopens the library and calls each routine in vlog_startup_routines; ours registers the start-of-simulation callback that launches the regression (design-doc §3.2, as deviated — see rustdv-runner docs and STATUS.md).

Structs§

AnalysisBus
A broadcast hub: one publisher in, every subscriber out.
CheckSink
Collector for check-phase failures (design-doc §5.3 signature).
Clock
Clock::new(&dut_clk, SimDuration::ns(10)).start().
ComponentReg
One registered component: its name and its maker. Emitted by #[derive(Component)] for every component, universally (D73).
ConfigDb
The configuration database. All methods are associated functions over an ambient per-test store (D11, D16).
Event
Manual-reset event; wait() completes immediately if already set.
Executor
The executor (design-doc §4.3). !Send — it never leaves the sim thread.
Factory
The factory. Ambient, like the ConfigDb it is built on; every method is an associated function.
GetExport
The FIFO’s get side.
HierarchyHandle
A module/scope handle: dut.child("name")? (OQ-6 dynamic-first lean).
Lock
LockGuard
RAII lock guard; drop releases (fair handoff to the next waiter).
LogicArray
A fixed-width vector of 4-state bits, MSB first (binstr order).
LogicHandle
A value-bearing signal. Explicit get()/set() (mapping row 20 — cocotb 2.x itself moved off the .value property).
NullTrigger
Yield once to the scheduler. Kept for parity but documented as a smell — prefer Event (cocotb NullTrigger docstring; book: Coroutines chapter).
ObjectionGuard
RAII objection. Drop = drop_objection (mapping row 32).
ObjectionRegistry
PeekExport
The FIFO’s peek side.
Port
A port: a component’s request for an interface it does not own.
PortInfo
One declared port, for the elaboration report.
PortName
The name a port is declared under, carrying the interface it demands.
PublishExport
The publish side of a hub: connect it to a source’s PublishPort.
PutExport
The FIFO’s put side, handed to a component that needs to put.
Queue
FIFO queue with optional bound; cloning shares the queue.
Receiver
The get/peek families (pyuvm: _s12, 12.2.5).
ResponseQueue
Responses, retrievable in order or by ticket (pyuvm’s ResponseQueue).
Rng
RustdvComp
A slot that holds any component. It says nothing about position in the tree and nothing about overridability; the build line decides that (new_comp() fixed, create_comp() overridable). Every child field a block may want to override is an RustdvComp.
RustdvCtx
The one context every testbench is handed (D47: TestCtx and RunCtx merged). Named for the framework, not for a phase, because Part II teaches testbenches that have no phases. Everything a running testbench is handed: the DUT, randomization, the objection registry, and the component’s path.
RustdvPath
RustdvSeq
A slot holding any sequence with these request/response types — what create_seq() returns, and what a component declares when the factory chooses the type. The parallel of RustdvComp.
RustdvShared
A handle to state shared between a component and its analysis port.
Sender
The put family (pyuvm: _s12, 12.2.5).
SeqCtx
What a running sequence is handed. Its equivalent of a component’s crate::RustdvCtx: it can log, it has a seeded RNG, and it knows its sequencer — if it has one.
SeqError
SeqItem
What a driver receives: the framework’s id plus the user’s plain payload.
SeqItemExport
The sequencer’s side, handed to connect.
Sequencer
The sequencer: a queue of items feeding one driver.
SimDuration
A span of simulation time in simulator precision steps. Unit-safe constructors (mapping row 13): SimDuration::ns(2).
SubscribeExport
The subscribe side of a hub. Connect as many subscribers to it as you like — that is what makes the write a broadcast.
TapExport
One of a FIFO’s analysis taps (D23): connect a subscriber to watch the traffic without joining the data path.
TaskHandle
Public task control surface; also a Future (handle.await == awaiting completion, as in cocotb 2.x). Port of cocotb Task (design-doc §4.3).
TestError
TestRegistration
One registered test (design-doc §6.1: the cocotb Test option set).
TimeoutError
Timer
One-shot timed trigger (port of cocotb Timer, mapping row 13). Construction rejects zero durations, as cocotb’s does.
TlmEmpty
TlmFifo
A bounded (or unbounded) FIFO that is also a component in the hierarchy.
TlmFull
try_send failure: returns the item (pyuvm try_put returning False).
TxnId
A transaction’s ticket. Assigned by the sequencer, carried in the envelope, and echoed on the response so a sequence gets the answer to the question it asked.

Enums§

Active
Agent activity (pyuvm’s ConfigDB is_active int becomes an enum — mapping row 42; illegal values are unrepresentable).
AnyHandle
ConfigError
Why a get failed. SystemVerilog collapses all of these into return 0 and leaves your variable untouched; naming them is the point.
ConnectError
Errors from wiring. Every one is a testbench bug found during elaboration, so the exports panic on them — but the message says exactly which port, on which component, and why.
Either
HandleError
Logic
One 4-state bit.
TaskError
TaskState
The seven task states, per cocotb (mapping row 5).
TlmError
ValueError

Traits§

Component
The UVM phase lifecycle (design-doc §5.3, D51), restored in full. Nine phases, each a method with a default no-op body — override only what you use, exactly as pyuvm’s uvm_component does. build and connect are real phases again, not the “constructor conventions” R3 collapsed them into; restoring them is the point of this chapter.
ComponentNode
Structural traversal over the ownership tree (design-doc D5.2). Generated by #[derive(Component)] for structs whose children are fields marked #[component]; hand-implementable by design (OQ-15: the derive is convenience, not requirement).
ComponentTrait
The UVM phase lifecycle (design-doc §5.3, D51), restored in full. Nine phases, each a method with a default no-op body — override only what you use, exactly as pyuvm’s uvm_component does. build and connect are real phases again, not the “constructor conventions” R3 collapsed them into; restoring them is the point of this chapter.
DynPhases
Dyn-safe mirror of Component’s non-async phases (D48).
GetIf
What a get export offers: take the item out.
PeekIf
What a peek export offers: copy the item and leave it there, so whoever gets it next still finds it. That is why peek needs T: Clone where get does not.
PortField
The bridge between a port field and the generated ComponentNode methods.
PortOwner
Whatever connect is pointed at: a child slot, or a component itself.
PublishIf
What a publish export offers: hand an item to everyone, immediately.
PutIf
What a put export offers. Implemented by the FIFO’s put side; a PutPort holds one of these once connected.
SeqItemIf
What a sequencer’s export offers a driver. Behind dyn, so the port can hold it without knowing which sequencer it came from.
Sequence
A sequence: a program that produces stimulus.
SinkHandle
The erased handle a subscribe port hands to the hub.
Subscriber
What a component does with an item it was handed by an analysis broadcast — the port of uvm_subscriber’s write.

Functions§

build_all
Top-down: build a node, then build the children it just created (D6). Reading children_mut after build is what lets a parent construct them in its own build phase and have the walk descend into them.
channel
Create a bounded channel (design-doc §5.6 signature). The UVM TLM FIFO default depth is 1; capacity = 0 is coerced to 1.
check_all
Top-down.
check_connections
Run the connection sweep and turn any misses into one error listing them all. Called by the runner between connect and end_of_elaboration.
connect_all
Bottom-up: children connect before parents.
create_seq
Build a sequence of this type, honouring any override installed for it.
end_of_elaboration_all
Top-down.
extract_all
Top-down.
final_all
Top-down.
first2
join2
next_time_step
Await the next simulator time step (port of NextTimeStep()).
print_hierarchy
Debug printer: the child walker serving pyuvm’s hierarchy print (design-doc §5.2).
read_only
Await the next ReadOnly phase (port of ReadOnly()).
read_write
Await the next ReadWrite phase (port of ReadWrite()).
report_all
Top-down.
run_all
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.
run_component_test
The full phaser: drive every UVM phase over a component tree, in order (D51) — the analog of pyuvm handing the test class to its phaser. The runner calls this for a #[rustdv::test] struct, so the test body is just the phase methods; no hand-rolled start_all.
run_extract_check_report
The standard post-run tail: extract → check → report → final, returning Err if any check failed (an Err fails the test, design-doc §0.6).
set_seq_override
Install a sequence override: wherever From::create_seq() is called, build a To instead.
sim_time_ns
Current simulation time in nanoseconds (for log formatting).
sim_time_steps
Current simulation time in precision steps.
spawn
Port of cocotb.start_soon (mapping row 4).
spawn_named
start_all
Bottom-up: children start before parents (transitional spawn hook).
start_of_simulation_all
Top-down.
top_module
The first top-level module (the DUT in single-top designs).
unconnected_ports
Every required port in the tree that nobody connected, as path.name (kind).
with_timeout
Run fut with a simulation-time timeout.

Type Aliases§

GetPort
A port that takes items out of something it does not own.
Maker
A maker: builds a component with no arguments (its name and parent come from the tree, D7). Non-capturing, so it is an ordinary fn pointer.
PeekPort
A port that copies items without removing them.
PublishPort
A port that broadcasts items to whoever is listening — or to nobody.
PutPort
A port that puts items into something it does not own.
SeqItemPort
A driver’s request for items. Declared #[port(seq_item)].
SubscribePort
A port that receives broadcast items. It is the odd one out: instead of the export writing an interface into it, the component fills it with its subscriber (subscribe) and the hub reads it out at connect time. Broadcast runs the other way, so the wiring does too.

Attribute Macros§

test
#[rustdv::test] — port of @cocotb.test() (design-doc §6.1). Both front doors (design-doc §6.1, D46). Registers at link time either

Derive Macros§

Component
#[derive(Component)] — ComponentNode traversal (design-doc §6.3). Generates the ComponentNode impl (design-doc §6.3, revised per R2): traversal of #[component] fields, including Option<T> and Vec<T>; names synthesized from field names. Emits no factory registration (R5) — but R5 is reversed: the factory returns in ch29, and this derive is where its registration will land. The impl is hand-writable; the derive is convenience.