Signals and the Dut¶
The operations available on a generated Dut’s members — ports, unpacked
arrays, inouts, and the inferred internal hierarchy — and the wide-value
type behind them. Hierarchy and
Interfaces teach the concepts; this page is the
surface.
A generated Dut is a plain aggregate of typed, stateless proxy members —
cheap to copy, safe to pass by value. Widths, directions, and array bounds
are compile-time properties, so a misspelled signal, a write to an output,
or force() on a port is a compile error.
Ports¶
get¶
set¶
set_now¶
value_type get() const;
void set(value_type value); // writable ports only; queues (write model)
void set_now(value_type value); // writable ports only; immediate
The value_type follows the width: uint32_t through 32 bits, uint64_t
through 64, Bits<W> above. Values are masked to the declared width on
both read and write. Under the default write model, set() queues and
flushes at the timestep’s ReadWrite point — a write after an awaited edge
lands on the next edge — while set_now() deposits immediately
(cocotb’s setimmediatevalue()). A get() between a set() and its
flush returns the simulator’s value, not the queued one, and writing from
ReadOnly fails at the offending call site.
One-bit ports convert implicitly to the Signal that edge triggers take:
co_await RisingEdge{dut.clk} just works.
force()/release() on any port is a compile error by design — force is
for inferred hierarchical objects only.
at¶
auto at(int32_t index) const; // unpacked arrays; also operator[]
Unpacked-array ports index by their declared SystemVerilog bounds — a
[1:3] array indexes 1..3 — one at() per dimension, with the final
dimension yielding an element carrying the scalar port surface
(get/set/set_now). Out-of-range indices are a runtime error naming
the array and its declared range.
drive¶
high_z¶
value_type get() const; // inout ports
void drive(value_type value) const; // enable the testbench driver
void high_z() const; // disable it
inout ports replace set() with explicit drive intent; both operations
are immediate. See Interfaces and inouts.
Wide values¶
Bits¶
template <std::size_t W> class Bits; // canonical, zero-extended
static Bits from_uint(uint64_t value);
static Bits from_uint128(uint128_t value);
static Bits from_hex(std::string_view text); // "0x" and "_" tolerated
static Bits from_words(word_array words);
uint32_t word(size_t index) const; void set_word(size_t index, uint32_t v);
bool bit(size_t index) const; void set_bit(size_t index, bool value);
Bits<K> slice(size_t lsb) const; void set_slice(size_t lsb, const Bits<K>&);
unsigned to_uint() const; // W ≤ 32
uint64_t to_uint64() const; // W ≤ 64
uint128_t to_uint128() const; // W ≤ 128
The value type of everything wider than 64 bits. Comparison is ==/!=
only — there are no arithmetic, bitwise, or shift operators; manipulate
through words, bits, and slices. Out-of-range access is a runtime error,
not undefined behavior. Random::randbits<W>() produces one directly:
dut.payload_i.set(test.random().randbits<256>()).
Internal hierarchy¶
deposit¶
force¶
release¶
value_type get() const; // dut.block.sub.name.get()
void deposit(value_type value) const; // one blocking assignment, immediate
void force(value_type value) const; // override drivers; persists
void release() const; // variable keeps last forced value;
// net returns to its drivers
Hierarchy operations are all immediate — none queues under the write
model and none advances time; a get() in the same instant observes a
preceding deposit()/force(). deposit() exists only on assignable
objects (variables, not resolved nets); force()/release() exist on
both. One-bit hierarchy signals convert to Signal for edge waits.
Four-state variants (get_logic, deposit_logic, force_logic) and
typed views (get_as<View>(), deposit_as(view)) carry the same timing.
Memory¶
Element at(int32_t index) const; // declared bounds; also operator[]
void get_into(int32_t first_index, std::span<value_type> values) const;
void deposit(int32_t first_index, std::span<const value_type> values) const;
Inferred memories index by declared bounds, one at() per dimension; each
element carries the hierarchy-signal surface. The span forms move whole
regions in one call — the backdoor path
memory models build on.
Timing summary¶
Operation |
Timing |
|---|---|
|
Deferred — flushes at the timestep’s ReadWrite point |
|
Immediate |
|
Immediate; never sees your own queued write |
|
Immediate |
Hierarchy |
Immediate |
See also¶
Hierarchy — what is inferred, what can be forced, and the usage-pruned transport contract.
Four-state values — the
_logicvariants and their current limits.