Skip to content

API reference

Waveform

Waveform(value, clock, time, width=None, signed=False, signal=None)

A clock-synchronised, numpy-backed time series of a hardware signal.

Every Waveform is a triple of parallel numpy arrays of equal length:

  • value — signal values sampled on every clock edge.
  • clock — absolute sampling-edge number counted from the first selected edge in the waveform file (which is cycle 0).
  • time — simulation timestamp (in the file's native time unit) of each sample.

These three arrays are always kept in sync; any operation that filters or transforms values also transforms the corresponding clock and time entries so positional alignment is preserved.

The convenience property data returns them as a single numpy record array with fields ("time", "clock", "value") for easy pandas / numpy interop.

width and signed are direct fields on Waveform. signal is an optional Signal that is set only when the waveform was loaded directly from a reader.

Bit-width rules
  • Widths ≤ 64 bits are stored as np.int64 (signed) or np.uint64 (unsigned).
  • Widths > 64 bits are stored as Python object arrays (arbitrary precision integers).
  • Arithmetic operators automatically infer a result width (e.g. addition widens by 1 bit; multiplication sums both widths). Width inference is capped at 64 bits for integer types.
  • Two Waveform operands must have the same signedness; mixing signed and unsigned raises ValueError.
Typical usage

Waveforms are normally created by a Reader, not constructed directly.

with VcdReader("sim.vcd") as r:
    data = r.load_waveform("tb.dut.data[7:0]", clock="tb.clk")
    valid = r.load_waveform("tb.dut.valid", clock="tb.clk")

valid_data = data.mask(valid == 1)
print(valid_data.value)

data property

Return value/clock/time as a single numpy record array.

Fields: "time" (simulation timestamp), "clock" (edge counter), "value" (signal value). Useful for pandas conversion or bulk numpy operations that need all three columns together.

ahead(n=1, pad='repeat', pad_value=None)

Return a new Waveform looking n cycles into the future.

Convenience wrapper around relative() for positive offsets.

Parameters:

Name Type Description Default
n int

Number of cycles to look ahead. Default is 1.

1
pad Literal['repeat', 'value']

See relative() for the padding options.

'repeat'
pad_value Any

See relative() for an example.

None

Returns:

Type Description
Waveform

A new waveform shifted forward by n cycles.

Example
# Rising edge detection
rising = (wave == 0) & wave.ahead()

any_edge()

Detect either edge in a 1-bit waveform.

Returns a new unsigned 1-bit Waveform that is true for both 0 -> 1 and 1 -> 0 transitions. The first sample is always false.

Raises:

Type Description
ValueError

If the source waveform is not one bit wide.

as_signed()

Reinterpret the unsigned bit pattern as a two's-complement signed integer.

Raises ValueError if width is unknown (None). Returns a copy if the waveform is already signed.

as_unsigned()

Reinterpret the signed value as an unsigned bit pattern.

Raises ValueError if width is unknown (None). Returns a copy if the waveform is already unsigned.

back(n=1, pad='repeat', pad_value=None)

Return a new Waveform looking n cycles into the past.

Convenience wrapper around relative() for negative offsets.

Parameters:

Name Type Description Default
n int

Number of cycles to look back. Default is 1.

1
pad Literal['repeat', 'value']

See relative() for the padding options.

'repeat'
pad_value Any

See relative() for an example.

None

Returns:

Type Description
Waveform

A new waveform shifted backward by n cycles.

Example
# Check if current value equals previous
same = wave == wave.back()

bit_count()

Count the number of set bits (population count) in each sample value.

Returns a new unsigned Waveform with width=64 where each value is the popcount of the corresponding source sample. Supports arbitrarily wide signals (> 64 bits) by chunking.

Raises:

Type Description
ValueError:

If self.width is None.

changed()

Detect changes between adjacent samples.

Returns a new unsigned 1-bit Waveform where value[i] is true when the current sample differs from the previous sample. The first sample is always false.

compress()

Compact a waveform while preserving value changes and the final sample.

This removes redundant samples inside each stable run, but keeps the first sample of each value run and always keeps the final sample. The result still records both where values change and where the original sampled window ends.

Use this when reducing waveform size for display, export, or quick inspection without losing the final sample.

Returns:

Type Description
Waveform

A compacted waveform. It may still contain one repeated final value when the last stable run has more than one sample, because the final sample is preserved intentionally.

concatenate(waves) staticmethod

Concatenate multiple waveforms into a single wider waveform.

Bits are joined so that the last element in waves becomes the MSB group and the first becomes the LSB group — this is the inverse of split_bits().

All waveforms in waves must be unsigned and have the same length. The result width is the sum of all input widths.

Parameters:

Name Type Description Default
waves list[Waveform]

List of waveforms to concatenate; at least one element required.

required

Raises:

Type Description
Exception:

If any waveform is signed.

ValueError:

If any waveform has width=None.

Example
# Recombine four 8-bit bytes into one 32-bit value (byte3 = MSB)
bus32 = Waveform.concatenate([byte0, byte1, byte2, byte3])

copy()

Return a deep copy of this waveform.

Returns:

Type Description
Waveform

New waveform with copied value, clock, and time arrays and the same width / signed metadata.

cycle_slice(begin_cycle=None, end_cycle=None, include_end=False)

Return a new Waveform trimmed to the given absolute clock cycle range.

Uses binary search on the sorted clock array so the operation is O(log n) regardless of waveform length. The clock values are absolute cycle numbers from the start of simulation (not relative to this waveform's window), so the same cycle number means the same simulation instant across different waveforms.

Parameters:

Name Type Description Default
begin_cycle int | None

First clock cycle to include (inclusive). Defaults to the first sample's cycle number.

None
end_cycle int | None

Last clock cycle. Exclusive by default; set include_end=True to make it inclusive.

None
include_end bool

If True, samples exactly at end_cycle are included.

False
See Also

time_slice : slice by simulation timestamp instead of cycle number.

Example
# Analyse cycles 100 to 199 (exclusive end)
window = wave.cycle_slice(100, 200)

downsample(chunk_size, func=np.mean)

Reduce the sample rate by aggregating consecutive chunks.

Splits value, clock, and time into non-overlapping windows of chunk_size and applies func to each window. The result length is ceil(len / chunk_size).

Parameters:

Name Type Description Default
chunk_size int

Number of consecutive samples to aggregate into one.

required
func Callable[[NDArray[Any]], float]

Aggregation function applied to each value chunk. Defaults to np.mean. clock and time chunks are always averaged.

mean
Example
# Average occupancy in 100-cycle windows
avg = occupancy.downsample(100, np.mean)

falling_edge()

Detect 1→0 transitions in a 1-bit waveform.

Returns a new 1-bit Waveform where value[i] == True if and only if self.value[i-1] == 1 and self.value[i] == 0. The first sample is always False.

Raises:

Type Description
ValueError

If the source waveform is not one bit wide.

See Also

rising_edge : detect 0→1 transitions. any_edge : detect either transition.

filter(condition)

Return a new Waveform keeping only the samples that satisfy condition.

condition is called once per sample value (scalar, not vectorized). For large waveforms prefer vectorized_filter().

Parameters:

Name Type Description Default
condition Callable[[Any], bool]

A callable that accepts a single value and returns bool.

required
Example
non_zero = wave.filter(lambda v: v != 0)

map(func, width=None, signed=None)

Apply a scalar function element-wise and return a new Waveform.

Internally wraps func with np.vectorize. For large waveforms prefer vectorized_map() with a native numpy operation.

Parameters:

Name Type Description Default
func Callable[[Any], Any]

Callable applied to each value element individually.

required
width int | None

Bit-width of the result. None if not known (default).

None
signed bool | None

Signedness of the result. Defaults to False.

None
Example
upper_nibble = wave.map(lambda v: (v >> 4) & 0xF, width=4, signed=False)

mask(mask)

Return a new Waveform keeping only the samples where mask is True.

Parameters:

Name Type Description Default
mask NDArray[bool_] | Waveform

Either a boolean np.ndarray or a 1-bit Waveform (width == 1 or dtype == bool). Must have the same length as self.

required

Raises:

Type Description
TypeError:

If mask is a Waveform with width != 1, or is not a boolean array.

Example
valid_data = data.mask(valid == 1)   # keep only cycles where valid is high

merge(waves, func, width, signed) staticmethod

Combine multiple same-length waveforms into one using a custom function.

At each sample index i, func is called with [w.value[i] for w in waves] and the returned value becomes the result sample. clock and time are taken from waves[0].

All waveforms must have the same number of samples.

Parameters:

Name Type Description Default
waves list[Waveform]

Input waveforms; must be non-empty and all equal in length.

required
func Callable[[list[Any]], Any]

Callable (list[scalar]) -> scalar applied per sample.

required
width int

Bit-width to assign to the result.

required
signed bool

Signedness of the result.

required
Example
# Compute bitwise majority across three 1-bit signals
majority = Waveform.merge(
    [a, b, c], lambda vs: int(sum(vs) >= 2), width=1, signed=False
)

relative(offset, pad='repeat', pad_value=None)

Return a new Waveform shifted by offset cycles.

This is the core method for relative time access. Use ahead() and back() for more readable positive/negative offsets.

Parameters:

Name Type Description Default
offset int

Number of cycles to shift. Positive looks forward (future), negative looks backward (past).

required
pad Literal['repeat', 'value']

Boundary handling strategy:

  • 'repeat' (default): pad with boundary value (first/last element).
  • 'value': pad with pad_value (must be provided).
'repeat'
pad_value Any

Value to use when pad='value'. Ignored otherwise.

None

Returns:

Type Description
Waveform

A new waveform shifted by offset cycles. clock and time arrays are always preserved unchanged.

Raises:

Type Description
ValueError:

If pad='value' but pad_value is not provided.

ValueError:

If pad is not one of 'repeat', 'value'.

Example
# Rising edge detection
rising = (wave == 0) & wave.ahead()

# Look back 3 cycles
past = wave.relative(-3)
See Also

ahead : Shift forward (positive offset). back : Shift backward (negative offset).

rising_edge()

Detect 0→1 transitions in a 1-bit waveform.

Returns a new 1-bit Waveform where value[i] == True if and only if self.value[i-1] == 0 and self.value[i] == 1. The first sample is always False.

Raises:

Type Description
ValueError

If the source waveform is not one bit wide.

See Also

falling_edge : detect 1→0 transitions. any_edge : detect either transition.

slice(begin_idx, end_idx, include_end=False)

Return a new Waveform trimmed to the given sample index range.

Parameters:

Name Type Description Default
begin_idx int

First sample index to include (inclusive).

required
end_idx int

Last sample index. Exclusive by default; set include_end=True to make it inclusive.

required
include_end bool

If True, the sample at end_idx is included.

False
See Also

time_slice : slice by simulation timestamp instead of array index.

split_bits(bit_group_size, padding=False)

Split the waveform into multiple narrower waveforms by bit groups.

Parameters:

Name Type Description Default
bit_group_size int | list[int]
  • int — split into equal-sized groups of this many bits, starting from bit 0 (LSB). width must be a multiple of bit_group_size unless padding=True.
  • list[int] — explicit widths for each group (LSB-first). The values must sum to self.width; padding is ignored.
required
padding bool

If True and an integer bit_group_size is given, the last group may be narrower than bit_group_size.

False

Returns:

Type Description
list[Waveform]:

Waveforms ordered from LSB group to MSB group, each unsigned.

Raises:

Type Description
ValueError:

If self.width is None.

Exception:

If width is not divisible by bit_group_size when padding=False, or if list sizes do not sum to self.width.

Example
# Split a 32-bit bus into four 8-bit bytes (byte0 = bits[7:0])
bytes_ = bus32.split_bits(8)

take(indices)

Return a new Waveform selecting samples at the given integer positions.

Parameters:

Name Type Description Default
indices NDArray[integer] | list[int] | Waveform

Integer index array, list of ints, or a Waveform whose value array contains integer indices (e.g. the result of np.where). Boolean arrays are not accepted; use mask() instead.

required

Raises:

Type Description
TypeError:

If indices contains booleans or non-integer values.

Example
# Keep every other sample
even = wave.take(list(range(0, len(wave.value), 2)))

time_slice(begin_time=None, end_time=None, include_end=False)

Return a new Waveform trimmed to the given simulation time range.

Uses binary search on the sorted time array so the operation is O(log n) regardless of waveform length.

Parameters:

Name Type Description Default
begin_time int | None

Start of the time window (inclusive). Defaults to the first sample's timestamp.

None
end_time int | None

End of the time window. Exclusive by default; set include_end=True to make it inclusive.

None
include_end bool

If True, samples exactly at end_time are included.

False
Example
# Analyse only the first 1000 simulation time units
early = wave.time_slice(0, 1000)

unique_consecutive()

Remove consecutive duplicate values.

Equivalent to run-length deduplication: each run of equal consecutive values is represented by its first sample. This matches the usual unique_consecutive semantics and is useful when only the sequence of observed values matters.

Returns:

Type Description
Waveform

A new waveform with consecutive duplicate values removed. The final timestamp may be dropped when the last value spans multiple samples.

vectorized_filter(func)

Return a new Waveform keeping only the samples where func returns True.

func receives the entire value array at once and must return a boolean array of the same length. Prefer this over filter() for performance-critical paths.

Parameters:

Name Type Description Default
func Callable[[NDArray[Any]], NDArray[bool_]]

Vectorized callable: (NDArray) -> NDArray[bool].

required

vectorized_map(func, width=None, signed=None)

Apply a vectorized function to the value array and return a new Waveform.

func receives the entire value ndarray and must return an ndarray of the same length. clock and time are deep-copied unchanged.

Parameters:

Name Type Description Default
func Callable[[NDArray[Any]], NDArray[Any]]

Vectorized callable: (NDArray) -> NDArray.

required
width int | None

Bit-width of the result. None if not known (default).

None
signed bool | None

Signedness of the result. Defaults to False.

None

Readers

Format-specific readers share the common loading, query, and expression APIs.

VcdReader(file)

Bases: Reader

Read VCD waveform files via vcdvcd.

Supports the common Reader APIs, including hierarchy traversal, expression evaluation, and clock-synchronised waveform loading.

begin_time property

Return the first timestamp stored in the VCD file.

end_time property

Return the last timestamp stored in the VCD file.

top_scopes cached property

Return immutable top-level scopes in the VCD hierarchy.

close()

Close this VCD reader.

The underlying vcdvcd reader keeps data in memory and does not expose an explicit close operation, so this method is a no-op.

eval(expr, clock, xz_value=0, signed=False, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None, mode='single', root_scope=None)

Evaluate a waveform expression containing physical signal paths.

Parameters:

Name Type Description Default
expr str

Expression string. Signal paths may be used as operands or as arguments to registered expression functions.

required
clock str

Clock signal used for all waveform loads.

required
xz_value int
0
signed int
0
sample_on_posedge int
0
begin_time int
0
end_time int
0
begin_cycle int
0
end_cycle int | None

Forwarded to load_matched_waveforms for every path.

None
mode Literal['single', 'zip']

'single' requires every path to match one signal. 'zip' evaluates once per shared multi-match key and broadcasts singleton paths.

'single'
root_scope Scope | None

If provided, resolve paths within this scope.

None

Returns:

Type Description
Waveform or dict[tuple[Capture, ...], Waveform]

The evaluated waveform, or one waveform per zip key.

get_matched_scopes(path, root_scope=None)

Return all scopes whose paths match path, keyed by captures.

Similar to get_matched_signals but stops at the scope level — the last component of path must match a scope name, not a signal. Useful for enumerating module instances before loading their signals.

Parameters:

Name Type Description Default
path str

Scope query path using the same syntax as signal paths. The last component must match a scope (module) name, e.g. "tb.dut.fifo_{0..3}" or r"tb./([a-z]+)_core/".

required
root_scope Scope | None

If provided, search only within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Scope]:

Maps each capture key to the matched Scope. Ordinary exact-name matches are omitted from the key, so a query without binding matchers uses ().

Raises:

Type Description
ValueError:

If two different scopes resolve to the same key, or if using module matchers on a backend without definition support (VCD/FST), or if the path contains a terminal signal bit-range suffix.

get_matched_signals(path, root_scope=None)

Return all signals whose paths match path, keyed by captures.

Traverses the scope tree starting from root_scope (or the file's top-level scopes if root_scope is None) and applies the query path to each level. See the class docstring for query path syntax.

Parameters:

Name Type Description Default
path str

Signal query path, e.g. "tb.dut.fifo_{0..3}.w_ptr[2:0]" or r"tb.dut./([a-z]+)_valid/".

required
root_scope Scope | None

If provided, search only within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Signal]:

Maps each capture key to the matched Signal object (carrying name, width, range, signed). Ordinary exact-name matches are omitted from the key, so a query without binding matchers uses ().

Raises:

Type Description
ValueError:

If two different signals resolve to the same key, or if using module matchers on a backend without definition support (VCD/FST).

get_scope(path, root_scope=None)

Return the scope at an exact hierarchy path.

Parameters:

Name Type Description Default
path str

Exact dotted scope path. Matcher expressions and terminal signal ranges are not accepted.

required
root_scope Scope | None

If provided, resolve path within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
Scope

The exact matched scope.

Raises:

Type Description
ValueError

If path contains matcher syntax, contains a terminal range, or the scope does not exist.

get_signal(path, root_scope=None)

Return the signal at an exact hierarchy path.

Parameters:

Name Type Description Default
path str

Exact dotted signal path, with an optional terminal bit selection or range. Matcher expressions are not accepted.

required
root_scope Scope | None

If provided, resolve path within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
Signal

The exact matched signal, including any requested range view.

Raises:

Type Description
ValueError

If path contains matcher syntax or the signal does not exist.

load_matched_unknown_masks(signal_path, clock_path, include_x=True, include_z=True, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None, root_scope=None)

Batch-load X/Z mask waveforms for all signals matching signal_path.

Clock assignment follows load_matched_waveforms: a single matched clock is broadcast to all signals; otherwise the longest-prefix clock key is selected for each signal key.

Parameters:

Name Type Description Default
signal_path str

Signal query path. See class docstring.

required
clock_path str

Clock signal query path. Must match at least one signal.

required
include_x bool

If True (default), mark source X/x bits.

True
include_z bool

If True (default), mark source Z/z bits.

True
sample_on_posedge bool

Same sampling/windowing semantics as load_waveform.

False
begin_time bool

Same sampling/windowing semantics as load_waveform.

False
end_time bool

Same sampling/windowing semantics as load_waveform.

False
begin_cycle bool

Same sampling/windowing semantics as load_waveform.

False
end_cycle bool

Same sampling/windowing semantics as load_waveform.

False
root_scope Scope | None

If provided, both signal_path and clock_path are searched within this scope instead of the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Waveform]:

Same keys as get_matched_signals on signal_path.

load_matched_waveforms(signal_path, clock_path, xz_value=0, signed=False, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None, root_scope=None)

Batch-load all signals matching signal_path, each paired with its clock.

Internally calls get_matched_signals for both signal_path and clock_path, then dispatches load_waveform for every match.

Clock assignment rules:

  • Single clock — if clock_path matches exactly one signal, that clock is broadcast to all matched signals.
  • Multiple clocks — for each signal key, the clock whose key is the longest prefix of the signal key is selected. If no clock key is a prefix, raises ValueError.

Parameters:

Name Type Description Default
signal_path str

Signal query path. See class docstring.

required
clock_path str

Clock signal query path. Must match at least one signal.

required
xz_value int

Forwarded to load_waveform for every loaded signal.

0
signed int

Forwarded to load_waveform for every loaded signal.

0
sample_on_posedge int

Forwarded to load_waveform for every loaded signal.

0
begin_time int

Forwarded to load_waveform for every loaded signal.

0
end_time int

Forwarded to load_waveform for every loaded signal.

0
begin_cycle int

Forwarded to load_waveform for every loaded signal.

0
end_cycle int

Forwarded to load_waveform for every loaded signal.

0
root_scope Scope | None

If provided, both signal_path and clock_path are searched within this scope instead of the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Waveform]:

Same keys as get_matched_signals on signal_path.

Raises:

Type Description
ValueError:

If clock_path matches no signals, or if no clock key is a prefix of a signal key.

load_unknown_mask(signal, clock, include_x=True, include_z=True, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None)

Load source X/Z presence as an unsigned bitmask waveform.

The returned Waveform is sampled on the same clock edges and supports the same time/cycle windowing as load_waveform, but its values are masks instead of substituted two-state signal values. A mask bit is 1 when the corresponding source bit is selected by include_x and/or include_z.

Parameters:

Name Type Description Default
signal Signal | str

Full dotted signal path or Signal object.

required
clock Signal | str

Clock signal path or Signal object.

required
include_x bool

If True (default), mark source X/x bits.

True
include_z bool

If True (default), mark source Z/z bits.

True
sample_on_posedge bool

Same sampling/windowing semantics as load_waveform.

False
begin_time bool

Same sampling/windowing semantics as load_waveform.

False
end_time bool

Same sampling/windowing semantics as load_waveform.

False
begin_cycle bool

Same sampling/windowing semantics as load_waveform.

False
end_cycle bool

Same sampling/windowing semantics as load_waveform.

False

Returns:

Name Type Description
Waveform Waveform

Unsigned mask waveform.

load_waveform(signal, clock, xz_value=0, signed=False, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None)

Load a single signal as a clock-synchronised Waveform.

The signal is sampled on every negedge of clock by default (i.e. the value is captured at each falling edge of the clock, which reflects the value that was stable during the preceding high phase). Set sample_on_posedge=True to sample on rising edges instead.

Parameters:

Name Type Description Default
signal Signal | str

Full dotted path of the signal as a Signal object or a string. When a Signal is passed, signal.full_name is used as the path (which may include bit-range suffixes). When a string is passed, the value is used verbatim as the full hierarchical path, e.g. "tb.dut.data[7:0]" or "tb.dut.data".

required
clock Signal | str

Clock signal as a Signal or full dotted path string, e.g. "tb.clk".

required
xz_value int

Integer substituted for X and Z values in the file. Defaults to 0.

0
signed bool

If True, the loaded values are interpreted as two's-complement signed integers.

False
sample_on_posedge bool

If True, sample on rising clock edges; otherwise on falling edges (default).

False
begin_time int | None

Simulation time to start loading from (inclusive). None means start of simulation. Mutually exclusive with begin_cycle.

None
end_time int | None

Simulation time to stop loading at (exclusive). None means end of simulation. Mutually exclusive with end_cycle.

None
begin_cycle int | None

Absolute clock cycle number to start loading from (inclusive). None means start of simulation. Mutually exclusive with begin_time. The clock is always loaded from time 0 so cycle numbers are absolute and comparable across different waveforms.

None
end_cycle int | None

Absolute clock cycle number to stop loading at (exclusive). None means end of simulation. Mutually exclusive with end_time.

None

Returns:

Name Type Description
Waveform Waveform

One sample per clock edge within the requested window. The .clock array contains absolute cycle numbers from the start of simulation. waveform.signal.full_name records the resolved signal path when source metadata is available.

Raises:

Type Description
ValueError:

If both begin_time and begin_cycle (or both end_time and end_cycle) are provided simultaneously.

FstReader(file)

Bases: Reader

Read FST waveform files via pylibfst.

Supports the same high-level APIs as VcdReader, including context-manager usage, hierarchy traversal, pattern matching, expression evaluation, and clock-synchronised load_waveform sampling.

begin_time cached property

Return the first timestamp stored in the FST file.

end_time cached property

Return the last timestamp stored in the FST file.

top_scopes property

Return immutable top-level scopes in the FST hierarchy.

close()

Close the underlying FST reader handle.

eval(expr, clock, xz_value=0, signed=False, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None, mode='single', root_scope=None)

Evaluate a waveform expression containing physical signal paths.

Parameters:

Name Type Description Default
expr str

Expression string. Signal paths may be used as operands or as arguments to registered expression functions.

required
clock str

Clock signal used for all waveform loads.

required
xz_value int
0
signed int
0
sample_on_posedge int
0
begin_time int
0
end_time int
0
begin_cycle int
0
end_cycle int | None

Forwarded to load_matched_waveforms for every path.

None
mode Literal['single', 'zip']

'single' requires every path to match one signal. 'zip' evaluates once per shared multi-match key and broadcasts singleton paths.

'single'
root_scope Scope | None

If provided, resolve paths within this scope.

None

Returns:

Type Description
Waveform or dict[tuple[Capture, ...], Waveform]

The evaluated waveform, or one waveform per zip key.

get_matched_scopes(path, root_scope=None)

Return all scopes whose paths match path, keyed by captures.

Similar to get_matched_signals but stops at the scope level — the last component of path must match a scope name, not a signal. Useful for enumerating module instances before loading their signals.

Parameters:

Name Type Description Default
path str

Scope query path using the same syntax as signal paths. The last component must match a scope (module) name, e.g. "tb.dut.fifo_{0..3}" or r"tb./([a-z]+)_core/".

required
root_scope Scope | None

If provided, search only within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Scope]:

Maps each capture key to the matched Scope. Ordinary exact-name matches are omitted from the key, so a query without binding matchers uses ().

Raises:

Type Description
ValueError:

If two different scopes resolve to the same key, or if using module matchers on a backend without definition support (VCD/FST), or if the path contains a terminal signal bit-range suffix.

get_matched_signals(path, root_scope=None)

Return all signals whose paths match path, keyed by captures.

Traverses the scope tree starting from root_scope (or the file's top-level scopes if root_scope is None) and applies the query path to each level. See the class docstring for query path syntax.

Parameters:

Name Type Description Default
path str

Signal query path, e.g. "tb.dut.fifo_{0..3}.w_ptr[2:0]" or r"tb.dut./([a-z]+)_valid/".

required
root_scope Scope | None

If provided, search only within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Signal]:

Maps each capture key to the matched Signal object (carrying name, width, range, signed). Ordinary exact-name matches are omitted from the key, so a query without binding matchers uses ().

Raises:

Type Description
ValueError:

If two different signals resolve to the same key, or if using module matchers on a backend without definition support (VCD/FST).

get_scope(path, root_scope=None)

Return the scope at an exact hierarchy path.

Parameters:

Name Type Description Default
path str

Exact dotted scope path. Matcher expressions and terminal signal ranges are not accepted.

required
root_scope Scope | None

If provided, resolve path within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
Scope

The exact matched scope.

Raises:

Type Description
ValueError

If path contains matcher syntax, contains a terminal range, or the scope does not exist.

get_signal(path, root_scope=None)

Return the signal at an exact hierarchy path.

Parameters:

Name Type Description Default
path str

Exact dotted signal path, with an optional terminal bit selection or range. Matcher expressions are not accepted.

required
root_scope Scope | None

If provided, resolve path within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
Signal

The exact matched signal, including any requested range view.

Raises:

Type Description
ValueError

If path contains matcher syntax or the signal does not exist.

load_matched_unknown_masks(signal_path, clock_path, include_x=True, include_z=True, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None, root_scope=None)

Batch-load X/Z mask waveforms for all signals matching signal_path.

Clock assignment follows load_matched_waveforms: a single matched clock is broadcast to all signals; otherwise the longest-prefix clock key is selected for each signal key.

Parameters:

Name Type Description Default
signal_path str

Signal query path. See class docstring.

required
clock_path str

Clock signal query path. Must match at least one signal.

required
include_x bool

If True (default), mark source X/x bits.

True
include_z bool

If True (default), mark source Z/z bits.

True
sample_on_posedge bool

Same sampling/windowing semantics as load_waveform.

False
begin_time bool

Same sampling/windowing semantics as load_waveform.

False
end_time bool

Same sampling/windowing semantics as load_waveform.

False
begin_cycle bool

Same sampling/windowing semantics as load_waveform.

False
end_cycle bool

Same sampling/windowing semantics as load_waveform.

False
root_scope Scope | None

If provided, both signal_path and clock_path are searched within this scope instead of the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Waveform]:

Same keys as get_matched_signals on signal_path.

load_matched_waveforms(signal_path, clock_path, xz_value=0, signed=False, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None, root_scope=None)

Batch-load all signals matching signal_path, each paired with its clock.

Internally calls get_matched_signals for both signal_path and clock_path, then dispatches load_waveform for every match.

Clock assignment rules:

  • Single clock — if clock_path matches exactly one signal, that clock is broadcast to all matched signals.
  • Multiple clocks — for each signal key, the clock whose key is the longest prefix of the signal key is selected. If no clock key is a prefix, raises ValueError.

Parameters:

Name Type Description Default
signal_path str

Signal query path. See class docstring.

required
clock_path str

Clock signal query path. Must match at least one signal.

required
xz_value int

Forwarded to load_waveform for every loaded signal.

0
signed int

Forwarded to load_waveform for every loaded signal.

0
sample_on_posedge int

Forwarded to load_waveform for every loaded signal.

0
begin_time int

Forwarded to load_waveform for every loaded signal.

0
end_time int

Forwarded to load_waveform for every loaded signal.

0
begin_cycle int

Forwarded to load_waveform for every loaded signal.

0
end_cycle int

Forwarded to load_waveform for every loaded signal.

0
root_scope Scope | None

If provided, both signal_path and clock_path are searched within this scope instead of the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Waveform]:

Same keys as get_matched_signals on signal_path.

Raises:

Type Description
ValueError:

If clock_path matches no signals, or if no clock key is a prefix of a signal key.

load_unknown_mask(signal, clock, include_x=True, include_z=True, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None)

Load source X/Z presence as an unsigned bitmask waveform.

The returned Waveform is sampled on the same clock edges and supports the same time/cycle windowing as load_waveform, but its values are masks instead of substituted two-state signal values. A mask bit is 1 when the corresponding source bit is selected by include_x and/or include_z.

Parameters:

Name Type Description Default
signal Signal | str

Full dotted signal path or Signal object.

required
clock Signal | str

Clock signal path or Signal object.

required
include_x bool

If True (default), mark source X/x bits.

True
include_z bool

If True (default), mark source Z/z bits.

True
sample_on_posedge bool

Same sampling/windowing semantics as load_waveform.

False
begin_time bool

Same sampling/windowing semantics as load_waveform.

False
end_time bool

Same sampling/windowing semantics as load_waveform.

False
begin_cycle bool

Same sampling/windowing semantics as load_waveform.

False
end_cycle bool

Same sampling/windowing semantics as load_waveform.

False

Returns:

Name Type Description
Waveform Waveform

Unsigned mask waveform.

load_waveform(signal, clock, xz_value=0, signed=False, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None)

Load a single signal as a clock-synchronised Waveform.

The signal is sampled on every negedge of clock by default (i.e. the value is captured at each falling edge of the clock, which reflects the value that was stable during the preceding high phase). Set sample_on_posedge=True to sample on rising edges instead.

Parameters:

Name Type Description Default
signal Signal | str

Full dotted path of the signal as a Signal object or a string. When a Signal is passed, signal.full_name is used as the path (which may include bit-range suffixes). When a string is passed, the value is used verbatim as the full hierarchical path, e.g. "tb.dut.data[7:0]" or "tb.dut.data".

required
clock Signal | str

Clock signal as a Signal or full dotted path string, e.g. "tb.clk".

required
xz_value int

Integer substituted for X and Z values in the file. Defaults to 0.

0
signed bool

If True, the loaded values are interpreted as two's-complement signed integers.

False
sample_on_posedge bool

If True, sample on rising clock edges; otherwise on falling edges (default).

False
begin_time int | None

Simulation time to start loading from (inclusive). None means start of simulation. Mutually exclusive with begin_cycle.

None
end_time int | None

Simulation time to stop loading at (exclusive). None means end of simulation. Mutually exclusive with end_cycle.

None
begin_cycle int | None

Absolute clock cycle number to start loading from (inclusive). None means start of simulation. Mutually exclusive with begin_time. The clock is always loaded from time 0 so cycle numbers are absolute and comparable across different waveforms.

None
end_cycle int | None

Absolute clock cycle number to stop loading at (exclusive). None means end of simulation. Mutually exclusive with end_time.

None

Returns:

Name Type Description
Waveform Waveform

One sample per clock edge within the requested window. The .clock array contains absolute cycle numbers from the start of simulation. waveform.signal.full_name records the resolved signal path when source metadata is available.

Raises:

Type Description
ValueError:

If both begin_time and begin_cycle (or both end_time and end_cycle) are provided simultaneously.

FsdbReader(file, *, quiet=True)

Bases: Reader

Read FSDB waveform files through the Verdi NPI runtime.

FsdbReader requires the Verdi runtime library (libNPI.so). Configure it with WAVEKIT_NPI_LIB, VERDI_HOME, or LD_LIBRARY_PATH before opening FSDB files.

quiet (default True) suppresses the NPI console banner via the -quiet initialization argument. Pass quiet=False to keep the banner. NPI initialization is process-global, so quiet only takes effect on the first FsdbReader created in the process; later readers cannot reliably re-enable the banner.

begin_time property

Return the first timestamp stored in the FSDB file.

end_time property

Return the last timestamp stored in the FSDB file.

top_scopes cached property

Return immutable top-level scopes in the FSDB hierarchy.

close()

Close the underlying FSDB/NPI reader handle.

eval(expr, clock, xz_value=0, signed=False, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None, mode='single', root_scope=None)

Evaluate a waveform expression containing physical signal paths.

Parameters:

Name Type Description Default
expr str

Expression string. Signal paths may be used as operands or as arguments to registered expression functions.

required
clock str

Clock signal used for all waveform loads.

required
xz_value int
0
signed int
0
sample_on_posedge int
0
begin_time int
0
end_time int
0
begin_cycle int
0
end_cycle int | None

Forwarded to load_matched_waveforms for every path.

None
mode Literal['single', 'zip']

'single' requires every path to match one signal. 'zip' evaluates once per shared multi-match key and broadcasts singleton paths.

'single'
root_scope Scope | None

If provided, resolve paths within this scope.

None

Returns:

Type Description
Waveform or dict[tuple[Capture, ...], Waveform]

The evaluated waveform, or one waveform per zip key.

get_matched_scopes(path, root_scope=None)

Return all scopes whose paths match path, keyed by captures.

Similar to get_matched_signals but stops at the scope level — the last component of path must match a scope name, not a signal. Useful for enumerating module instances before loading their signals.

Parameters:

Name Type Description Default
path str

Scope query path using the same syntax as signal paths. The last component must match a scope (module) name, e.g. "tb.dut.fifo_{0..3}" or r"tb./([a-z]+)_core/".

required
root_scope Scope | None

If provided, search only within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Scope]:

Maps each capture key to the matched Scope. Ordinary exact-name matches are omitted from the key, so a query without binding matchers uses ().

Raises:

Type Description
ValueError:

If two different scopes resolve to the same key, or if using module matchers on a backend without definition support (VCD/FST), or if the path contains a terminal signal bit-range suffix.

get_matched_signals(path, root_scope=None)

Return all signals whose paths match path, keyed by captures.

Traverses the scope tree starting from root_scope (or the file's top-level scopes if root_scope is None) and applies the query path to each level. See the class docstring for query path syntax.

Parameters:

Name Type Description Default
path str

Signal query path, e.g. "tb.dut.fifo_{0..3}.w_ptr[2:0]" or r"tb.dut./([a-z]+)_valid/".

required
root_scope Scope | None

If provided, search only within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Signal]:

Maps each capture key to the matched Signal object (carrying name, width, range, signed). Ordinary exact-name matches are omitted from the key, so a query without binding matchers uses ().

Raises:

Type Description
ValueError:

If two different signals resolve to the same key, or if using module matchers on a backend without definition support (VCD/FST).

get_scope(path, root_scope=None)

Return the scope at an exact hierarchy path.

Parameters:

Name Type Description Default
path str

Exact dotted scope path. Matcher expressions and terminal signal ranges are not accepted.

required
root_scope Scope | None

If provided, resolve path within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
Scope

The exact matched scope.

Raises:

Type Description
ValueError

If path contains matcher syntax, contains a terminal range, or the scope does not exist.

get_signal(path, root_scope=None)

Return the signal at an exact hierarchy path.

Parameters:

Name Type Description Default
path str

Exact dotted signal path, with an optional terminal bit selection or range. Matcher expressions are not accepted.

required
root_scope Scope | None

If provided, resolve path within this scope instead of starting from the file's top-level scopes.

None

Returns:

Type Description
Signal

The exact matched signal, including any requested range view.

Raises:

Type Description
ValueError

If path contains matcher syntax or the signal does not exist.

load_matched_unknown_masks(signal_path, clock_path, include_x=True, include_z=True, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None, root_scope=None)

Batch-load X/Z mask waveforms for all signals matching signal_path.

Clock assignment follows load_matched_waveforms: a single matched clock is broadcast to all signals; otherwise the longest-prefix clock key is selected for each signal key.

Parameters:

Name Type Description Default
signal_path str

Signal query path. See class docstring.

required
clock_path str

Clock signal query path. Must match at least one signal.

required
include_x bool

If True (default), mark source X/x bits.

True
include_z bool

If True (default), mark source Z/z bits.

True
sample_on_posedge bool

Same sampling/windowing semantics as load_waveform.

False
begin_time bool

Same sampling/windowing semantics as load_waveform.

False
end_time bool

Same sampling/windowing semantics as load_waveform.

False
begin_cycle bool

Same sampling/windowing semantics as load_waveform.

False
end_cycle bool

Same sampling/windowing semantics as load_waveform.

False
root_scope Scope | None

If provided, both signal_path and clock_path are searched within this scope instead of the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Waveform]:

Same keys as get_matched_signals on signal_path.

load_matched_waveforms(signal_path, clock_path, xz_value=0, signed=False, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None, root_scope=None)

Batch-load all signals matching signal_path, each paired with its clock.

Internally calls get_matched_signals for both signal_path and clock_path, then dispatches load_waveform for every match.

Clock assignment rules:

  • Single clock — if clock_path matches exactly one signal, that clock is broadcast to all matched signals.
  • Multiple clocks — for each signal key, the clock whose key is the longest prefix of the signal key is selected. If no clock key is a prefix, raises ValueError.

Parameters:

Name Type Description Default
signal_path str

Signal query path. See class docstring.

required
clock_path str

Clock signal query path. Must match at least one signal.

required
xz_value int

Forwarded to load_waveform for every loaded signal.

0
signed int

Forwarded to load_waveform for every loaded signal.

0
sample_on_posedge int

Forwarded to load_waveform for every loaded signal.

0
begin_time int

Forwarded to load_waveform for every loaded signal.

0
end_time int

Forwarded to load_waveform for every loaded signal.

0
begin_cycle int

Forwarded to load_waveform for every loaded signal.

0
end_cycle int

Forwarded to load_waveform for every loaded signal.

0
root_scope Scope | None

If provided, both signal_path and clock_path are searched within this scope instead of the file's top-level scopes.

None

Returns:

Type Description
dict[tuple[Capture, ...], Waveform]:

Same keys as get_matched_signals on signal_path.

Raises:

Type Description
ValueError:

If clock_path matches no signals, or if no clock key is a prefix of a signal key.

load_unknown_mask(signal, clock, include_x=True, include_z=True, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None)

Load source X/Z presence as an unsigned bitmask waveform.

The returned Waveform is sampled on the same clock edges and supports the same time/cycle windowing as load_waveform, but its values are masks instead of substituted two-state signal values. A mask bit is 1 when the corresponding source bit is selected by include_x and/or include_z.

Parameters:

Name Type Description Default
signal Signal | str

Full dotted signal path or Signal object.

required
clock Signal | str

Clock signal path or Signal object.

required
include_x bool

If True (default), mark source X/x bits.

True
include_z bool

If True (default), mark source Z/z bits.

True
sample_on_posedge bool

Same sampling/windowing semantics as load_waveform.

False
begin_time bool

Same sampling/windowing semantics as load_waveform.

False
end_time bool

Same sampling/windowing semantics as load_waveform.

False
begin_cycle bool

Same sampling/windowing semantics as load_waveform.

False
end_cycle bool

Same sampling/windowing semantics as load_waveform.

False

Returns:

Name Type Description
Waveform Waveform

Unsigned mask waveform.

load_waveform(signal, clock, xz_value=0, signed=False, sample_on_posedge=False, begin_time=None, end_time=None, begin_cycle=None, end_cycle=None)

Load a single signal as a clock-synchronised Waveform.

The signal is sampled on every negedge of clock by default (i.e. the value is captured at each falling edge of the clock, which reflects the value that was stable during the preceding high phase). Set sample_on_posedge=True to sample on rising edges instead.

Parameters:

Name Type Description Default
signal Signal | str

Full dotted path of the signal as a Signal object or a string. When a Signal is passed, signal.full_name is used as the path (which may include bit-range suffixes). When a string is passed, the value is used verbatim as the full hierarchical path, e.g. "tb.dut.data[7:0]" or "tb.dut.data".

required
clock Signal | str

Clock signal as a Signal or full dotted path string, e.g. "tb.clk".

required
xz_value int

Integer substituted for X and Z values in the file. Defaults to 0.

0
signed bool

If True, the loaded values are interpreted as two's-complement signed integers.

False
sample_on_posedge bool

If True, sample on rising clock edges; otherwise on falling edges (default).

False
begin_time int | None

Simulation time to start loading from (inclusive). None means start of simulation. Mutually exclusive with begin_cycle.

None
end_time int | None

Simulation time to stop loading at (exclusive). None means end of simulation. Mutually exclusive with end_cycle.

None
begin_cycle int | None

Absolute clock cycle number to start loading from (inclusive). None means start of simulation. Mutually exclusive with begin_time. The clock is always loaded from time 0 so cycle numbers are absolute and comparable across different waveforms.

None
end_cycle int | None

Absolute clock cycle number to stop loading at (exclusive). None means end of simulation. Mutually exclusive with end_time.

None

Returns:

Name Type Description
Waveform Waveform

One sample per clock edge within the requested window. The .clock array contains absolute cycle numbers from the start of simulation. waveform.signal.full_name records the resolved signal path when source metadata is available.

Raises:

Type Description
ValueError:

If both begin_time and begin_cycle (or both end_time and end_cycle) are provided simultaneously.

has_fsdb_support()

Check whether the Verdi FSDB runtime library is installed.

Pattern matching

Pattern()

Declarative temporal pattern builder over waveform signals.

Build steps with Pattern().wait(...).capture(...) and execute with module-level match. Pattern stores only the declarative step AST; programmable checking/extraction uses match(body) or collect(body).

The first blocking step selects candidate start cycles. Later blocking steps wait within a matched transaction.

Declarative callbacks receive (index, captures). index is the current sample index into waveform arrays, not a cycle number and not rebased by start_cycle. captures is the current match's capture dict.

branch(cond, true_body=None, false_body=None)

Run one of two epsilon bodies based on cond at the current cycle.

Parameters:

Name Type Description Default
cond Waveform | Callable[[int, dict[str, Any]], bool] | bool

Waveform, bool, or callable(index, captures) -> bool. Callback index is the current waveform-array sample index, not a cycle number. captures is the current match's capture dict.

required
true_body Pattern | None

Optional body run when cond is true.

None
false_body Pattern | None

Optional body run when cond is false.

None

Returns:

Type Description
Pattern

This pattern, for chaining.

capture(name, signal, *, mode='last')

Record a value into captures[name] at the current cycle.

Parameters:

Name Type Description Default
name str

Capture key.

required
signal Waveform | Callable[[int, dict[str, Any]], Any]

Waveform or callable(index, captures) -> Any. Waveforms are read as waveform.value[index] at the current cycle. Callback index is the current waveform-array sample index, not a cycle number. captures is the current match's capture dict.

required
mode CaptureMode

'last' overwrites existing values, 'first' keeps the first value, and 'list' appends each captured value to a list.

'last'

Returns:

Type Description
Pattern

This pattern, for chaining.

consume(cond, channel=None, *, require=None, require_message=None)

Wait for cond and exclusively claim (channel, cycle).

Parameters:

Name Type Description Default
cond Waveform | Callable[[int, dict[str, Any]], bool] | bool

Waveform, bool, or callable(index, captures) -> bool. When true, this step tries to consume the current event cycle. Callback index is the current waveform-array sample index, not a cycle number. captures is the current match's capture dict.

required
channel Channel | Hashable | Callable[[int, dict[str, Any]], Channel | Hashable] | None

Channel, hashable key, or callable(index, captures) -> Channel | Hashable. If omitted, this consume step receives a private channel created when the step is declared. Channel callbacks use the same (index, captures) arguments. The resolved (channel, cycle) can be claimed by at most one match; earlier start cycles win. This does not reserve the channel while cond is false.

None
require Waveform | Callable[[int, dict[str, Any]], bool] | bool | None

Optional condition checked while cond is false, or while cond is true but the current (channel, cycle) was already claimed. It is not checked on the successful consume cycle.

None
require_message str | Callable[[int, dict[str, Any]], str] | None

Optional message for MatchStatus.RequireViolated. A callable uses the same (index, captures) arguments and is evaluated only on failure.

None

Returns:

Type Description
Pattern

This pattern, for chaining.

delay(n, *, require=None, require_message=None)

Wait exactly n cycles; delay(0) is an epsilon no-op.

Parameters:

Name Type Description Default
n int | Callable[[int, dict[str, Any]], int]

Non-negative int or callable(index, captures) -> int. Callback index is the current waveform-array sample index, not a cycle number. captures is the current match's capture dict.

required
require Waveform | Callable[[int, dict[str, Any]], bool] | bool | None

Optional condition checked before each cycle advance during the delay. Failure records MatchStatus.RequireViolated(require_message).

None
require_message str | Callable[[int, dict[str, Any]], str] | None

Optional message for MatchStatus.RequireViolated. A callable uses the same (index, captures) arguments and is evaluated only on failure.

None

Returns:

Type Description
Pattern

This pattern, for chaining.

loop(body, *, until=None, when=None)

Run body as a do-while (until) or while (when) loop.

Parameters:

Name Type Description Default
body Pattern

Nested declarative pattern body.

required
until Waveform | Callable[[int, dict[str, Any]], bool] | bool | None

Optional do-while exit condition. The body runs first; the loop exits when until becomes true. Callable conditions use (index, captures).

None
when Waveform | Callable[[int, dict[str, Any]], bool] | bool | None

Optional while condition. The condition is checked before each iteration; the loop exits when when becomes false. Callable conditions use (index, captures).

None

Returns:

Type Description
Pattern

This pattern, for chaining.

Notes

Exactly one of until and when is required. Conditions use the same Waveform / bool / callable forms as wait.

repeat(body, n)

Run body exactly n times.

Parameters:

Name Type Description Default
body Pattern

Nested declarative pattern body.

required
n int | Callable[[int, dict[str, Any]], int]

Non-negative int or callable(index, captures) -> int. Callback index is the current waveform-array sample index, not a cycle number. captures is the current match's capture dict.

required

Returns:

Type Description
Pattern

This pattern, for chaining.

require(cond, *, message=None)

Assert cond at the current cycle, else record RequireViolated.

Parameters:

Name Type Description Default
cond Waveform | Callable[[int, dict[str, Any]], bool] | bool

Waveform, bool, or callable(index, captures) -> bool. Callback index is the current waveform-array sample index, not a cycle number. captures is the current match's capture dict.

required
message str | Callable[[int, dict[str, Any]], str] | None

Optional failure message. A callable uses the same (index, captures) arguments and is evaluated only on failure.

None

Returns:

Type Description
Pattern

This pattern, for chaining.

wait(cond, *, require=None, require_message=None)

Observe cycles until cond becomes true, without consuming the event.

Parameters:

Name Type Description Default
cond Waveform | Callable[[int, dict[str, Any]], bool] | bool

Waveform, bool, or callable(index, captures) -> bool. When true at the current cycle, the step completes at that cycle. Callback index is the current waveform-array sample index, not a cycle number. captures is the current match's capture dict.

required
require Waveform | Callable[[int, dict[str, Any]], bool] | bool | None

Optional condition checked only while cond is false. It is not checked on the cycle where cond becomes true. Failure records MatchStatus.RequireViolated(require_message).

None
require_message str | Callable[[int, dict[str, Any]], str] | None

Optional message for MatchStatus.RequireViolated. A callable uses the same (index, captures) arguments and is evaluated only on failure.

None

Returns:

Type Description
Pattern

This pattern, for chaining.

match(body, *, axis=None, timeout=None, timeout_message=None, start_cycle=None, end_cycle=None)

Run a declarative pattern or programmable check body.

Parameters:

Name Type Description Default
body Pattern | Callable[[PatternContext], Any]

Declarative Pattern or normal callable body(ctx). Check bodies run once per scanned start cycle and must return ctx.OK to emit an OK row, or None to skip that start. Other non-None values are errors.

required
axis Waveform | None

Optional waveform that defines the scan axis, cycle numbers, and result timestamps. Declarative patterns usually infer it from observed waveforms. Pass axis when the body may not observe a waveform before blocking, or when using start_cycle / end_cycle without an inferable waveform.

None
timeout int | None

Optional positive integer per-start maximum duration in cycles. Exceeding it records MatchStatus.Timeout(timeout_message).

None
timeout_message str | None

Optional human-readable message stored in timeout statuses.

None
start_cycle int | None

Optional absolute cycle scan window. start_cycle is inclusive and end_cycle is exclusive.

None
end_cycle int | None

Optional absolute cycle scan window. start_cycle is inclusive and end_cycle is exclusive.

None

Returns:

Type Description
MatchRecords

Ordered batch of match records and captured columns.

Raises:

Type Description
PatternError

If the body is invalid, waveform axes are incompatible, or execution cannot infer a scan axis.

collect(body, *, axis=None, timeout=None, timeout_message=None, start_cycle=None, end_cycle=None)

Run a programmable extraction body and collect returned items.

Parameters:

Name Type Description Default
body Callable[[PatternContext], Any]

Normal callable body(ctx). It runs once per scanned start cycle; each non-None return value is appended to the output list. Declarative Pattern objects are intentionally unsupported.

required
axis Waveform | None

Optional waveform that defines the scan axis. Pass it when the body may not observe a waveform before blocking, or when using a scan window.

None
timeout int | None

Optional positive integer per-start maximum duration in cycles. Timeout raises PatternError instead of returning a status row.

None
timeout_message str | None

Optional human-readable timeout message.

None
start_cycle int | None

Optional absolute cycle scan window. start_cycle is inclusive and end_cycle is exclusive.

None
end_cycle int | None

Optional absolute cycle scan window. start_cycle is inclusive and end_cycle is exclusive.

None

Returns:

Type Description
list[Any]

Non-None values returned by the extraction body.

Raises:

Type Description
PatternError

If body is not a normal callable, if a timeout/require failure occurs, or if execution cannot infer a scan axis.

MatchRecords(start, end, duration, status, captures)

Bases: Sequence[MatchRecord]

Columnar batch of pattern match records.

start and end are point waveforms: .value stores waveform-array sample indices, .clock stores absolute cycle numbers, and .time stores simulation timestamps. duration.value is end.value - start.value + 1.

failed property

Return a boolean result-row mask for failed matches.

Returns:

Type Description
Waveform

One-bit waveform aligned to result rows. value is true where status is not MatchStatus.OK.

ok property

Return a boolean result-row mask for successful matches.

Returns:

Type Description
Waveform

One-bit waveform aligned to result rows. value is true where status is MatchStatus.OK.

filter_failed()

Return records whose status is not MatchStatus.OK.

Returns:

Type Description
MatchRecords

A row-masked batch with all fields and captures filtered together.

filter_ok()

Return records whose status is MatchStatus.OK.

Returns:

Type Description
MatchRecords

A row-masked batch with all fields and captures filtered together.

filter_status(status)

Return records matching a status class.

Parameters:

Name Type Description Default
status type[MatchStatusValue]

Status class such as MatchStatus.Timeout.

required

Returns:

Type Description
MatchRecords

A row-masked batch with all fields and captures filtered together.

MatchRecord(start, end, status, captures) dataclass

One pattern match record.

Attributes:

Name Type Description
start, end

Inclusive match boundary points. MatchPoint.index is the waveform-array sample index, MatchPoint.cycle is the absolute clock cycle, and MatchPoint.time is the simulation timestamp.

status MatchStatusValue

Terminal status object: MatchStatus.OK(), MatchStatus.Timeout(...), or MatchStatus.RequireViolated(...).

captures dict[str, Any]

Per-record captured Python values.

duration property

Return the inclusive duration in sampled cycles.

Returns:

Type Description
int

end.index - start.index + 1.

MatchPoint(index, cycle, time) dataclass

One match boundary point.

index is the waveform-array sample index; cycle and time are the corresponding absolute cycle number and simulation timestamp.

MatchStatus

Terminal status namespace for pattern match records.

OK() dataclass

Bases: MatchStatusValue

Successful completion of a pattern candidate.

RequireViolated(message=None) dataclass

Bases: MatchStatusValue

A non-blocking require check failed.

Timeout(message=None) dataclass

Bases: MatchStatusValue

A pattern candidate did not complete within its allowed duration.

Channel

Identity object for explicit consume ownership.

A Channel represents a logical event stream from which at most one pattern instance may consume per cycle. Plain wait steps are observational and do not consume channels.

PatternError

Bases: Exception

Raised for pattern definition or runtime errors.

Signal hierarchy and queries

Node(base_name, parent) dataclass

Bases: ABC

An immutable node in a waveform-file hierarchy.

children abstractmethod property

Return this node's direct children.

full_name cached property

Return this node's fully-qualified real hierarchy name.

is_range_selectable property

Return whether this node supports a trailing bit-range selection.

name property

Return this node's local name, including a signal range when present.

get_matched_nodes(path)

Return matching descendant nodes keyed by binding captures.

get_matched_scopes(path)

Return matching descendant scopes keyed by binding captures.

get_matched_signals(path)

Return matching descendant signals keyed by binding captures.

Scope(base_name, parent) dataclass

Bases: Node

A real hierarchy scope.

children abstractmethod property

Return this node's direct children.

full_name cached property

Return this node's fully-qualified real hierarchy name.

is_range_selectable property

Return whether this node supports a trailing bit-range selection.

name property

Return this node's local name, including a signal range when present.

get_matched_nodes(path)

Return matching descendant nodes keyed by binding captures.

get_matched_scopes(path)

Return matching descendant scopes keyed by binding captures.

get_matched_signals(path)

Return matching descendant signals keyed by binding captures.

Signal(base_name, parent, range, composite_type=None, native_range=None) dataclass

Bases: Node

An immutable signal view, optionally narrowed by a selection range.

children abstractmethod property

Return this node's direct children.

full_name cached property

Return this node's fully-qualified real hierarchy name.

is_leaf property

Return whether this signal has no composite children.

is_range_selectable property

Return whether this signal supports a trailing bit-range selection.

name property

Return this node's local name, including a signal range when present.

native_width cached property

Return the width of the complete signal before range selection.

width cached property

Return the width of the current selected signal view.

get_matched_nodes(path)

Return matching descendant nodes keyed by binding captures.

get_matched_scopes(path)

Return matching descendant scopes keyed by binding captures.

get_matched_signals(path)

Return matching descendant signals keyed by binding captures.

with_range(selected_range)

Return a view with selected_range, or restore the native range for None.

Range(start, end) dataclass

An HDL index range whose direction is preserved as start:end.

SignalCompositeType

Bases: Enum

Composite signal type as reported by a waveform backend.

Capture(anchor_node=None, node=None, definition=None) dataclass

Base class for typed bindings returned in a capture tuple.

Matcher-specific code may create a partial Capture with no node context. Matcher.match() completes it before it can escape the matcher layer.

finalize(*, anchor_node, node, definition=None)

Complete a partial Capture with its matched node context.

with_anchor_node(anchor_node)

Return a complete Capture rebased to anchor_node.

ExactCapture(anchor_node=None, node=None, definition=None) dataclass

Bases: Capture

Exact-name binding; only module-definition matches are public.

finalize(*, anchor_node, node, definition=None)

Complete a partial Capture with its matched node context.

with_anchor_node(anchor_node)

Return a complete Capture rebased to anchor_node.

BraceCapture(anchor_node=None, node=None, definition=None, groups=()) dataclass

Bases: Capture

Binding produced by brace expansion; groups stores brace values.

finalize(*, anchor_node, node, definition=None)

Complete a partial Capture with its matched node context.

with_anchor_node(anchor_node)

Return a complete Capture rebased to anchor_node.

RegexCapture(anchor_node=None, node=None, definition=None, groups=()) dataclass

Bases: Capture

Binding produced by regex matching; groups stores regex groups.

finalize(*, anchor_node, node, definition=None)

Complete a partial Capture with its matched node context.

with_anchor_node(anchor_node)

Return a complete Capture rebased to anchor_node.

WildcardCapture(anchor_node=None, node=None, definition=None) dataclass

Bases: Capture

Binding produced by * or ** wildcard matching.

finalize(*, anchor_node, node, definition=None)

Complete a partial Capture with its matched node context.

with_anchor_node(anchor_node)

Return a complete Capture rebased to anchor_node.