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}