Skip to main content

vj_sim/image/
verif.rs

1//! The verification half of a [`DesignImage`](super::DesignImage): what the
2//! assertion engines, the sampled-value bookkeeping, the clocking-block
3//! samplers and the covergroup runtime need beyond the kernels' machine code.
4//!
5//! Every function an entry refers to is a [`DesignImage::symbols`](super::DesignImage::symbols)
6//! index, resolved by the same `KernelResolver` the kernels are (the signature
7//! behind a symbol is fixed by what `vj-codegen` emits, see
8//! `vj_exec::verif`). Nothing here names an `sv-lang` type, so a `.so`
9//! carries it and a slang-free runner reads it: a design symbol is its
10//! `SymbolId::key_string` text.
11
12use crate::netlist::InstanceId;
13use crate::sched::assert_control::SiteDesc;
14use crate::state::EdgeKind;
15use crate::sva::engine::AssertKind;
16use crate::sva::ir::{LeafId, LocalVarId};
17use crate::sva::property::PropertyIr;
18
19/// One `(selector leaf, label leaf)` comparison of a property `case`, and the
20/// compiled function that evaluates it.
21#[derive(Clone, Debug, PartialEq, Eq)]
22pub struct CasePairImage {
23    pub selector: LeafId,
24    pub label: LeafId,
25    pub symbol: u32,
26}
27
28/// One concurrent assertion, procedural assertion, `expect`, sequence end-point
29/// watcher or checker assertion: everything `vj_codegen::sva::emit::AssertionSpec`
30/// carries, plus the symbols of the functions it compiled.
31#[derive(Clone, Debug, PartialEq)]
32pub struct AssertionImage {
33    /// The plan index of the assertion's kernel: the key of its queued
34    /// procedural instances and of its assertion-control site.
35    pub plan_index: u32,
36    pub instance: InstanceId,
37    /// The kernel the assertion's action blocks run in (resumed with the
38    /// pass/fail term; never registered as a process of its own).
39    pub kernel: u32,
40    pub frame_words: u32,
41    pub label: String,
42    pub kind: AssertKind,
43    pub ir: PropertyIr,
44    pub n_clocks: u32,
45    /// Sampled value functions' own history clocks (16.12), beyond the
46    /// assertion's own `n_clocks`: `ticks` has `n_clocks + hist_clocks`
47    /// entries (`vj_sim::sva::engine::EngineConfig::hist_clocks`).
48    pub hist_clocks: u32,
49    pub leaf_reads: Vec<Vec<LocalVarId>>,
50    pub leaf_writes: Vec<Option<LocalVarId>>,
51    pub activated: bool,
52    pub captured: Vec<LocalVarId>,
53    /// See `EngineConfig::disable_mixed`.
54    pub disable_mixed: bool,
55    /// See `EngineConfig::tick_history`.
56    pub tick_history: bool,
57    pub history_depth: u32,
58    pub future: bool,
59    /// The clock (an index into all `n_clocks + hist_clocks`) whose next tick
60    /// a `future`-sampled call's row holds, or `0` for a design with none.
61    pub future_clock: u32,
62    /// The byte offset of the assertion statement's own source range, for
63    /// VPI assertion control (36.9, `None`: not an assertion statement).
64    pub src_offset: Option<u64>,
65    /// Per leaf, its expression's source range: what VPI reports a step's or
66    /// a failure's leaves as (39.4.2).
67    pub leaf_src: Vec<(u32, u64, u64)>,
68    /// Entries in a sampled row.
69    pub row_len: u32,
70    /// `{name}_snap`.
71    pub snap: u32,
72    /// `{name}_t{c}` per clock (`n_clocks + hist_clocks` of them).
73    pub ticks: Vec<u32>,
74    /// `{name}_l{i}` per leaf; `None` for a leaf the engine never evaluates.
75    pub leaves: Vec<Option<u32>>,
76    /// `{name}_lv{i}`, parallel to `leaves`: the live-state form of a leaf
77    /// that holds a sampled value function (16.12), evaluated on a position
78    /// row instead of a plain signal row. `None` where `leaves[i]` is also
79    /// `None`, or the leaf has no such function.
80    pub live_leaves: Vec<Option<u32>>,
81    /// `{name}_c{k}` per `case` comparison.
82    pub cases: Vec<CasePairImage>,
83    /// The assertion-control registry entry (20.11); `None` for a directive no
84    /// control task reaches.
85    pub site: Option<SiteDesc>,
86    /// A sequence end-point watcher's cell (`AssertionSpec::end_cell`).
87    pub end_cell: Option<u32>,
88    /// `(design symbol key, first word, word count)`: the sampled-row words a
89    /// checker free variable occupies (`AssertionSpec::current_words`).
90    pub current_words: Vec<(String, u32, u32)>,
91    /// `(first word, word count)` of the row words refreshed from the live
92    /// cells at the Observed region (`AssertionSpec::observed_words`).
93    pub observed_words: Vec<(u32, u32)>,
94    /// The row words holding a collection handle (`AssertionSpec::coll_words`).
95    pub coll_words: Vec<u32>,
96    /// Per `coll_words` entry, where the collections inside its elements sit
97    /// (`AssertionSpec::coll_nests`); no slots for a flat collection.
98    pub coll_nests: Vec<crate::collections::Nest>,
99    /// The match-item calls that run as processes of their own
100    /// (`AssertionSpec::spawn_calls`).
101    pub spawn_calls: Vec<SpawnCallImage>,
102}
103
104/// A sequence match-item call of a task that can suspend (16.11): the runner
105/// spawns the kernel at each end point.
106#[derive(Clone, Debug, PartialEq, Eq)]
107pub struct SpawnCallImage {
108    /// The call's index: its fired term is `2 + call`.
109    pub call: u32,
110    /// The kernel's symbol, a `ProcessFn`.
111    pub kernel: u32,
112    pub frame_words: u32,
113    pub entry_pc: u32,
114}
115
116/// One active free variable of a checker instance (17.7.2).
117#[derive(Clone, Debug, PartialEq, Eq)]
118pub struct FreeVarImage {
119    /// The design symbol's key, matched against `AssertionImage::current_words`.
120    pub id: String,
121    pub slot: u32,
122    pub width: u32,
123    pub wide: bool,
124}
125
126/// The active free variables of one checker instance.
127#[derive(Clone, Debug, PartialEq, Eq)]
128pub struct FreeGroupImage {
129    pub instance: InstanceId,
130    pub vars: Vec<FreeVarImage>,
131    /// The generator the values are drawn from.
132    pub rng: u64,
133}
134
135/// One clocked sampled-value call site: when its compiled guard reports the
136/// clocking event occurred, the value history shifts.
137#[derive(Clone, Debug, PartialEq, Eq)]
138pub struct SampledSiteImage {
139    /// The `vj_sva_guard_*` function (`extern "C" fn(SimHandle) -> u8`).
140    pub guard: u32,
141    /// `(from, to)` slots, in the order they must run.
142    pub shifts: Vec<(u32, u32)>,
143}
144
145/// One instance's sampled-value state (`vj_sim::sva::sampled::hidden_slots`).
146#[derive(Clone, Debug, PartialEq, Eq)]
147pub struct SampledImage {
148    pub instance: InstanceId,
149    pub sites: Vec<SampledSiteImage>,
150    /// `(signal, its P cell)`.
151    pub p_copies: Vec<(u32, u32)>,
152}
153
154/// [`ClockingImage::skews`] code for `#1step`.
155pub const SKEW_STEP: u64 = u64::MAX;
156
157/// [`ClockingImage::skews`] code for an edge skew naming the edge OPPOSITE the
158/// clocking event's (LRM 14.4): the value at the end of the step of the clock
159/// signal's latest such edge. The event's own edge is `0`.
160pub const SKEW_EDGE_OPP: u64 = u64::MAX - 1;
161
162/// One clocking block's sampler (14.13): woken by the clocking event, it copies
163/// each input clock variable's signal into its sample cell, then bumps the
164/// event counter that `@(cb)` and `##N` wait on.
165#[derive(Clone, Debug, PartialEq, Eq)]
166pub struct ClockingImage {
167    pub instance: InstanceId,
168    /// The clocking event's terms: `(signal slot, edge)`; `None` is any change.
169    pub terms: Vec<(u32, Option<EdgeKind>)>,
170    /// `iff` guards (9.4.2.3, 14.12) as `(term index, gate function symbol)`
171    /// (`u64 gate(handle)`, 1 = condition known true): a term that fired counts
172    /// only while all of its gates hold, and the event is a clocking event if any
173    /// fired term counts. Empty = ungated.
174    pub gates: Vec<(u32, u32)>,
175    /// `(signal slot, sample slot, width)` per input clock variable.
176    pub samples: Vec<(u32, u32, u32)>,
177    /// The input skew of each of `samples` (14.4), in scheduler ticks:
178    /// [`SKEW_STEP`] is `#1step` (the Preponed value), `0` an explicit `#0`
179    /// (sampled in the Observed region), `N` the value at the end of the time
180    /// step `N` ticks before the event.
181    pub skews: Vec<u64>,
182    /// Per sample, the parts of a derived input clock variable source (14.5:
183    /// `input x = a[3:0]`, `input y = {a, b[2:1]}`): `(signal slot, signal
184    /// width, lsb, len)`, most significant first. An empty list (or a
185    /// missing entry) is the plain signal of `samples`.
186    pub parts: Vec<Vec<(u32, u32, u32, u32)>>,
187    /// The block's event counter slot.
188    pub counter: u32,
189    /// The instance that owns each of `terms`' signal slots, parallel to it.
190    /// A block clocked by an input port's wire is woken by the PARENT's signal
191    /// the port connects to (14.13: the clocking event and the parent's
192    /// `@(posedge clk)` are one event), not by the port's continuous-assignment
193    /// copy, which updates a delta later.
194    pub term_owners: Vec<InstanceId>,
195}
196
197/// The sampler of a covergroup with a clocking event (19.3: `covergroup cg
198/// @(posedge clk)` samples every instance of itself on each event).
199#[derive(Clone, Debug, PartialEq, Eq)]
200pub struct CovSamplerImage {
201    /// The event's terms: `(signal slot, edge)`; `None` is any change.
202    pub terms: Vec<(u32, Option<EdgeKind>)>,
203    /// `iff` gates (9.4.2.3) as `(term index, gate function symbol)`, the symbol
204    /// as `ClockingImage::gates`: a term that fired counts only while all of its
205    /// gates hold, and the event samples if any fired term counts.
206    pub gates: Vec<(u32, u32)>,
207    /// The terms that are an edge or a change of an EXPRESSION or select
208    /// (`@(posedge a[3])`, `@(posedge (a & b))`), not of a whole signal.
209    pub exprs: Vec<CovExprTermImage>,
210    /// `type_option.strobe` (19.7.1): sample at the end of the time slot.
211    pub strobe: bool,
212}
213
214/// A sampling-event term on an expression (19.3, 9.4.2): the sampler wakes on
215/// a change of any signal the expression reads (the `wake` terms of
216/// [`CovSamplerImage::terms`], each `(slot, any change)`), re-evaluates it
217/// with `func` and compares with the value of the previous wake.
218#[derive(Clone, Debug, PartialEq, Eq)]
219pub struct CovExprTermImage {
220    /// The value function symbol, `u64 f(handle)`: with an `edge`, bit 0 is the
221    /// expression's least significant bit and bit 1 whether it is `x`/`z`;
222    /// without one, the value in bits 0..32 and its unknown bits in 32..64.
223    pub func: u32,
224    /// `None` is any change of the value.
225    pub edge: Option<EdgeKind>,
226    /// Indices into the sampler's `terms` of the signals the expression reads.
227    pub wake: Vec<u32>,
228    /// `iff` gate function symbols (9.4.2.3) of this term.
229    pub gates: Vec<u32>,
230}
231
232/// The clocking event of a class-embedded covergroup whose event reads a
233/// property of each object (19.4: `covergroup cg @(posedge clk)` with `clk` a
234/// class property): one watcher for the type polls every object's event
235/// expressions whenever object state changes.
236#[derive(Clone, Debug, PartialEq, Eq)]
237pub struct CovClassClockImage {
238    /// The event's terms: `(kernel id of the term's expression, edge)`; `None`
239    /// is any change.
240    pub terms: Vec<(u32, Option<EdgeKind>)>,
241    /// `iff` gates (9.4.2.3) as `(term index, kernel id)`.
242    pub gates: Vec<(u32, u32)>,
243    /// `type_option.strobe` (19.7.1): sample at the end of the time slot.
244    pub strobe: bool,
245}
246
247/// One covergroup of the design as compiled for one module instance (19.3).
248#[derive(Clone, Debug, PartialEq)]
249pub struct CovGroupImage {
250    /// The design-wide type index `new` finds the table by.
251    pub type_index: u32,
252    /// The checker site the table belongs to (`0` outside a checker).
253    pub site: u32,
254    pub instance: InstanceId,
255    pub decl: crate::covergroup::decl::CovGroupDecl,
256    /// The `vj_cov_*` kernels (`CovKernelFn`), by id.
257    pub kernels: Vec<u32>,
258    pub sampler: Option<CovSamplerImage>,
259    /// The per-object clocking event of a class-embedded covergroup.
260    pub class_clock: Option<CovClassClockImage>,
261    /// The block events (19.3 `@@(begin f)` / `@@(end f)`) that sample this
262    /// covergroup, as the keys the subroutine's code passes to the runtime.
263    pub blocks: Vec<u64>,
264}
265
266/// Everything verification-related a design image carries.
267#[derive(Clone, Debug, Default, PartialEq)]
268pub struct VerifImage {
269    pub assertions: Vec<AssertionImage>,
270    pub free_groups: Vec<FreeGroupImage>,
271    pub sampled: Vec<SampledImage>,
272    /// In registration order: instance by instance, each instance's blocks in
273    /// declaration order.
274    pub clocking: Vec<ClockingImage>,
275    /// In table order: the index the runtime assigns a table is its position.
276    pub covergroups: Vec<CovGroupImage>,
277}
278
279impl VerifImage {
280    /// Whether the design has nothing to verify at run time.
281    pub fn is_empty(&self) -> bool {
282        let VerifImage {
283            assertions,
284            free_groups,
285            sampled,
286            clocking,
287            covergroups,
288        } = self;
289        assertions.is_empty()
290            && free_groups.is_empty()
291            && sampled.is_empty()
292            && clocking.is_empty()
293            && covergroups.is_empty()
294    }
295}