Skip to main content

vj_sim/covergroup/
decl.rs

1//! The declaration side of the model: what the SystemVerilog source says,
2//! before any instance exists (IEEE 1800-2023 19.3, 19.5).
3//!
4//! A [`CoverpointDecl`] is produced once per `covergroup` and instantiated once
5//! per `new`, with that instance's constructor arguments (see
6//! [`super::coverpoint::Coverpoint::new`]).
7
8use super::value::{Expr, TypeInfo};
9
10/// `bins`, `ignore_bins` or `illegal_bins` (19.5, 19.5.5, 19.5.6).
11#[derive(Clone, Copy, Debug, PartialEq, Eq)]
12pub enum BinKind {
13    Normal,
14    Ignore,
15    Illegal,
16}
17
18/// The bracket after the bin name.
19#[derive(Clone, Debug, PartialEq)]
20pub enum ArrayKind {
21    /// `bins b`: one bin.
22    None,
23    /// `bins b[]`: one bin per value (per interval for reals).
24    Open,
25    /// `bins b[N]`: `N` bins, `N` evaluated at construction.
26    Fixed(Expr),
27}
28
29/// One end of a `[lo:hi]` range; `$` is the type minimum/maximum.
30#[derive(Clone, Debug, PartialEq)]
31pub enum Bound {
32    Expr(Expr),
33    Dollar,
34}
35
36/// One element of a `covergroup_range_list` (Syntax 19-2).
37#[derive(Clone, Debug, PartialEq)]
38pub enum RangeItem {
39    /// A single value (or, for a set expression's elements, one element).
40    Single(Expr),
41    /// `[lo:hi]`, `[$:hi]`, `[lo:$]`.
42    Range(Bound, Bound),
43    /// `[center +/- tol]` (`relative = false`) or `[center +%- tol]`
44    /// (`relative = true`), 11.4.13.
45    Tolerance {
46        center: Expr,
47        tol: Expr,
48        relative: bool,
49    },
50}
51
52/// `repeat_range`: `n` or `lo : hi` (Syntax 19-3).
53#[derive(Clone, Debug, PartialEq)]
54pub struct RepeatRange {
55    pub lo: Expr,
56    pub hi: Option<Expr>,
57}
58
59impl RepeatRange {
60    pub fn exactly(n: i128) -> RepeatRange {
61        RepeatRange {
62            lo: Expr::int(n),
63            hi: None,
64        }
65    }
66
67    pub fn between(lo: i128, hi: i128) -> RepeatRange {
68        RepeatRange {
69            lo: Expr::int(lo),
70            hi: Some(Expr::int(hi)),
71        }
72    }
73}
74
75/// The repetition suffix of a `trans_item`.
76#[derive(Clone, Debug, PartialEq)]
77pub enum TransRep {
78    Once,
79    /// `[* repeat_range ]`
80    Consecutive(RepeatRange),
81    /// `[-> repeat_range ]`
82    Goto(RepeatRange),
83    /// `[= repeat_range ]`
84    NonConsecutive(RepeatRange),
85}
86
87/// A `trans_range_list`: a value range list with its repetition.
88#[derive(Clone, Debug, PartialEq)]
89pub struct TransItem {
90    pub values: Vec<RangeItem>,
91    pub rep: TransRep,
92}
93
94impl TransItem {
95    pub fn new(values: Vec<RangeItem>) -> TransItem {
96        TransItem {
97            values,
98            rep: TransRep::Once,
99        }
100    }
101
102    pub fn rep(mut self, rep: TransRep) -> TransItem {
103        self.rep = rep;
104        self
105    }
106}
107
108/// A `trans_set`: items joined by `=>`.
109pub type TransSet = Vec<TransItem>;
110
111/// What a bin matches.
112#[derive(Clone, Debug, PartialEq)]
113pub enum BinBody {
114    /// `( trans_set ) { , ( trans_set ) }` (19.5.2).
115    Trans(Vec<TransSet>),
116    /// `default sequence` (19.5.2).
117    DefaultSeq,
118    /// `{ range list } [with (expr)]`. A `with` kernel receives the
119    /// constructor arguments followed by `item`. The coverpoint-name form
120    /// `cp with (expr)` is `[$:$]` plus the clause.
121    Ranges {
122        items: Vec<RangeItem>,
123        with: Option<Expr>,
124    },
125    /// A `set_covergroup_expression`: evaluates to a [`super::value::Val::List`].
126    Set(Expr),
127    /// `default` (19.5): the values of no other bin.
128    Default,
129}
130
131#[derive(Clone, Debug, PartialEq)]
132pub struct BinDecl {
133    pub name: String,
134    pub kind: BinKind,
135    pub array: ArrayKind,
136    pub wildcard: bool,
137    /// Per-bin `iff` (sample-time kernel).
138    pub iff: Option<Expr>,
139    pub body: BinBody,
140}
141
142impl BinDecl {
143    /// A plain `bins <name> = { items }`.
144    pub fn ranges(name: &str, items: Vec<RangeItem>) -> BinDecl {
145        BinDecl {
146            name: name.to_string(),
147            kind: BinKind::Normal,
148            array: ArrayKind::None,
149            wildcard: false,
150            iff: None,
151            body: BinBody::Ranges { items, with: None },
152        }
153    }
154
155    pub fn kind(mut self, kind: BinKind) -> BinDecl {
156        self.kind = kind;
157        self
158    }
159
160    pub fn array(mut self, array: ArrayKind) -> BinDecl {
161        self.array = array;
162        self
163    }
164
165    pub fn wildcard(mut self) -> BinDecl {
166        self.wildcard = true;
167        self
168    }
169
170    pub fn iff(mut self, iff: Expr) -> BinDecl {
171        self.iff = Some(iff);
172        self
173    }
174
175    pub fn with(mut self, with: Expr) -> BinDecl {
176        if let BinBody::Ranges { with: w, .. } = &mut self.body {
177            *w = Some(with);
178        }
179        self
180    }
181
182    /// A transition bin `bins <name> = (set) , (set) ...`.
183    pub fn trans(name: &str, sets: Vec<TransSet>) -> BinDecl {
184        BinDecl {
185            name: name.to_string(),
186            kind: BinKind::Normal,
187            array: ArrayKind::None,
188            wildcard: false,
189            iff: None,
190            body: BinBody::Trans(sets),
191        }
192    }
193
194    /// `bins <name> = default sequence`.
195    pub fn default_seq(name: &str) -> BinDecl {
196        BinDecl {
197            name: name.to_string(),
198            kind: BinKind::Normal,
199            array: ArrayKind::None,
200            wildcard: false,
201            iff: None,
202            body: BinBody::DefaultSeq,
203        }
204    }
205
206    pub fn default_bin(name: &str) -> BinDecl {
207        BinDecl {
208            name: name.to_string(),
209            kind: BinKind::Normal,
210            array: ArrayKind::None,
211            wildcard: false,
212            iff: None,
213            body: BinBody::Default,
214        }
215    }
216}
217
218/// The `matches` clause of a `with` select or a set select (19.6.1.2).
219#[derive(Clone, Debug, PartialEq)]
220pub enum Matches {
221    /// `matches n`: at least `n` satisfying value tuples (a positive integer,
222    /// evaluated at construction). Omitted means `Count(1)`.
223    Count(Expr),
224    /// `matches $`: every value tuple must satisfy.
225    All,
226}
227
228impl Matches {
229    /// The default policy of 19.6.1.2: a single value tuple selects.
230    pub fn one() -> Matches {
231        Matches::Count(Expr::int(1))
232    }
233}
234
235/// A `select_expression` (Syntax 19-4).
236#[derive(Clone, Debug, PartialEq)]
237pub enum SelectExpr {
238    /// `binsof(cp)` / `binsof(cp.bin)`, optionally `intersect { ranges }`.
239    /// `bin` names one bin, or a whole `b[]` / `b[N]` array by its base name.
240    Binsof {
241        cp: String,
242        bin: Option<String>,
243        intersect: Option<Vec<RangeItem>>,
244    },
245    Not(Box<SelectExpr>),
246    And(Box<SelectExpr>, Box<SelectExpr>),
247    Or(Box<SelectExpr>, Box<SelectExpr>),
248    /// `sel with (expr) [matches ...]`. The kernel receives the constructor
249    /// arguments followed by one value per cross item, in item order.
250    With {
251        sel: Box<SelectExpr>,
252        expr: Expr,
253        matches: Matches,
254    },
255    /// The enclosing cross's own identifier: every bin tuple.
256    All,
257    /// `cross_set_expression [matches ...]`: evaluates to a
258    /// [`super::value::Val::List`] of tuples (each a `Val::List` with one value
259    /// per cross item), 19.6.1.4.
260    Set {
261        expr: Expr,
262        matches: Matches,
263    },
264}
265
266/// A `bins`, `ignore_bins` or `illegal_bins` selection of a cross (19.6.1,
267/// 19.6.2, 19.6.3).
268#[derive(Clone, Debug, PartialEq)]
269pub struct CrossBinDecl {
270    pub name: String,
271    pub kind: BinKind,
272    pub select: SelectExpr,
273    /// Per-bin `iff` (sample-time kernel).
274    pub iff: Option<Expr>,
275}
276
277impl CrossBinDecl {
278    pub fn new(name: &str, kind: BinKind, select: SelectExpr) -> CrossBinDecl {
279        CrossBinDecl {
280            name: name.to_string(),
281            kind,
282            select,
283            iff: None,
284        }
285    }
286
287    pub fn iff(mut self, iff: Expr) -> CrossBinDecl {
288        self.iff = Some(iff);
289        self
290    }
291}
292
293/// A `cross` (19.6).
294#[derive(Clone, Debug, PartialEq)]
295pub struct CrossDecl {
296    pub name: String,
297    /// The crossed coverpoints, by name, in declaration order. A variable
298    /// operand is represented by the implicit coverpoint the frontend adds.
299    pub items: Vec<String>,
300    /// Cross-level `iff` (sample-time kernel).
301    pub iff: Option<Expr>,
302    pub bins: Vec<CrossBinDecl>,
303    pub options: Vec<(String, Expr)>,
304    pub type_options: Vec<(String, Expr)>,
305}
306
307impl CrossDecl {
308    pub fn new(name: &str, items: &[&str]) -> CrossDecl {
309        CrossDecl {
310            name: name.to_string(),
311            items: items.iter().map(|s| s.to_string()).collect(),
312            iff: None,
313            bins: Vec::new(),
314            options: Vec::new(),
315            type_options: Vec::new(),
316        }
317    }
318
319    pub fn bin(mut self, bin: CrossBinDecl) -> CrossDecl {
320        self.bins.push(bin);
321        self
322    }
323}
324
325/// A `coverpoint` (explicit, or the implicit one of a cross operand).
326#[derive(Clone, Debug, PartialEq)]
327pub struct CoverpointDecl {
328    pub name: String,
329    pub ty: TypeInfo,
330    /// Sample-time kernel yielding the coverpoint value.
331    pub expr: Expr,
332    /// Coverpoint-level `iff` (sample-time kernel).
333    pub iff: Option<Expr>,
334    pub bins: Vec<BinDecl>,
335    /// For an enum-typed coverpoint: every enumerator `(name, value)` in
336    /// declaration order (auto bins are named after them, 19.5.3).
337    pub enum_values: Option<Vec<(String, i128)>>,
338    /// `option.<name> = <expr>` assignments inside the coverpoint, in order.
339    pub options: Vec<(String, Expr)>,
340    /// `type_option.<name> = <expr>` assignments inside the coverpoint.
341    pub type_options: Vec<(String, Expr)>,
342}
343
344/// A `covergroup` declaration (19.3): its options and its coverage items.
345#[derive(Clone, Debug, PartialEq)]
346pub struct CovGroupDecl {
347    pub name: String,
348    /// `option.<name> = <expr>` assignments of the covergroup, in order.
349    /// Evaluated per instance with the constructor arguments (19.7).
350    pub options: Vec<(String, Expr)>,
351    /// `type_option.<name> = <expr>` assignments; constant expressions
352    /// (19.7.1), evaluated once when the type is defined.
353    pub type_options: Vec<(String, Expr)>,
354    pub coverpoints: Vec<CoverpointDecl>,
355    pub crosses: Vec<CrossDecl>,
356}
357
358impl CovGroupDecl {
359    pub fn new(name: &str) -> CovGroupDecl {
360        CovGroupDecl {
361            name: name.to_string(),
362            options: Vec::new(),
363            type_options: Vec::new(),
364            coverpoints: Vec::new(),
365            crosses: Vec::new(),
366        }
367    }
368
369    pub fn coverpoint(mut self, cp: CoverpointDecl) -> CovGroupDecl {
370        self.coverpoints.push(cp);
371        self
372    }
373
374    pub fn cross(mut self, x: CrossDecl) -> CovGroupDecl {
375        self.crosses.push(x);
376        self
377    }
378
379    pub fn option(mut self, name: &str, v: Expr) -> CovGroupDecl {
380        self.options.push((name.to_string(), v));
381        self
382    }
383
384    pub fn type_option(mut self, name: &str, v: Expr) -> CovGroupDecl {
385        self.type_options.push((name.to_string(), v));
386        self
387    }
388}
389
390impl CoverpointDecl {
391    pub fn new(name: &str, ty: TypeInfo, expr: Expr) -> CoverpointDecl {
392        CoverpointDecl {
393            name: name.to_string(),
394            ty,
395            expr,
396            iff: None,
397            bins: Vec::new(),
398            enum_values: None,
399            options: Vec::new(),
400            type_options: Vec::new(),
401        }
402    }
403
404    pub fn bin(mut self, bin: BinDecl) -> CoverpointDecl {
405        self.bins.push(bin);
406        self
407    }
408}