verilator/test_regress/t/t_covergroup_iff.v

242 lines
6.7 KiB
Systemverilog
Raw Permalink Normal View History

// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2026 by Wilson Snyder.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// Test iff (enable) guard: sampling is gated by the enable condition.
// Covers iff on explicit value bins, default bin, array bins,
// simple 2-step transition, and 3-step transition.
//
// Also covers compound iff expressions (&&, ||, unary !, bit/part-select,
// relational compare, parenthesized bitwise, and a concatenation-valued
// coverpoint with a compound iff). Previously any iff that was not a bare
// reference or a unary ! tripped an internal error ("Unexpected '...'
// expression under 'COVERPOINT'") because the iff child was widthed with no
// context.
// verilog_format: off
`define stop $stop
`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
// verilog_format: on
module t;
logic enable;
int value;
// Signals for the compound-iff covergroups below
logic m_is_read;
logic [3:0] m_be;
logic [1:0] m_a;
logic [1:0] m_b;
int count;
// iff on explicit value bins
covergroup cg_iff;
cp_value: coverpoint value iff (enable) {
2026-06-06 00:36:55 +02:00
bins disabled_lo = {1}; bins disabled_hi = {2}; bins enabled_lo = {3}; bins enabled_hi = {4};
}
endgroup
// iff on default bin
covergroup cg_default_iff;
cp: coverpoint value iff (enable) {
bins known = {10};
bins def = default; // default bin with coverpoint-level iff
}
endgroup
// iff on array bins
covergroup cg_array_iff;
cp: coverpoint value iff (enable) {
bins arr[] = {5, 6, 7}; // array bins, all gated by iff
}
endgroup
// iff on 2-step transition
covergroup cg_trans2_iff;
2026-06-06 00:36:55 +02:00
cp: coverpoint value iff (enable) {bins t2 = (1 => 2);}
endgroup
// iff on 3-step transition
covergroup cg_trans3_iff;
2026-06-06 00:36:55 +02:00
cp: coverpoint value iff (enable) {bins t3 = (1 => 2 => 3);}
endgroup
// --- compound iff expressions ---
// unary ! combined with && and a bit-select, on a concatenation-valued
// coverpoint expression -- the exact reported shape.
covergroup cg_and;
2026-06-06 00:36:55 +02:00
cp_concat: coverpoint {
m_a[0], m_b[0]
} iff (!m_is_read && m_be[0]) {
bins b00 = {2'b00}; bins b01 = {2'b01}; bins b10 = {2'b10}; bins b11 = {2'b11};
}
endgroup
// logical || guard
covergroup cg_or;
2026-06-06 00:36:55 +02:00
cp: coverpoint count iff (m_be[0] || m_be[1]) {bins lo = {1}; bins hi = {2};}
endgroup
// part-select compare guard
covergroup cg_part;
2026-06-06 00:36:55 +02:00
cp: coverpoint count iff (m_be[3:0] != 0) {bins one = {1};}
endgroup
// relational compare guard
covergroup cg_rel;
2026-06-06 00:36:55 +02:00
cp: coverpoint count iff (count > 3) {bins five = {5}; bins two = {2};}
endgroup
// parenthesized bitwise guard
covergroup cg_bitw;
2026-06-06 00:36:55 +02:00
cp: coverpoint count iff ((m_a & m_b) == 2'b10) {bins seven = {7};}
endgroup
2026-06-06 00:36:55 +02:00
cg_iff cg1 = new;
cg_default_iff cg2 = new;
cg_array_iff cg3 = new;
cg_trans2_iff cg4 = new;
cg_trans3_iff cg5 = new;
cg_and ca = new;
cg_or co = new;
cg_part cpp = new;
cg_rel cr = new;
cg_bitw cb = new;
initial begin
// Sample disabled_lo and disabled_hi with enable=0 -- must not be recorded
enable = 0;
2026-06-06 00:36:55 +02:00
value = 1;
cg1.sample();
value = 2;
cg1.sample();
`checkr(cg1.get_inst_coverage(), 0.0);
// Sample enabled_lo and enabled_hi with enable=1 -- must be recorded
enable = 1;
2026-06-06 00:36:55 +02:00
value = 3;
cg1.sample();
`checkr(cg1.get_inst_coverage(), 25.0);
2026-06-06 00:36:55 +02:00
value = 4;
cg1.sample();
`checkr(cg1.get_inst_coverage(), 50.0);
// cg2: default bin -- enable=1 lets known and default through
enable = 1;
2026-06-06 00:36:55 +02:00
value = 10;
cg2.sample(); // hits 'known'
`checkr(cg2.get_inst_coverage(), 100.0); // 1/1: only 'known' counts (default excluded, LRM 19.5)
2026-06-06 00:36:55 +02:00
value = 99;
cg2.sample(); // hits 'def' (default)
`checkr(cg2.get_inst_coverage(), 100.0);
enable = 0;
2026-06-06 00:36:55 +02:00
value = 99;
cg2.sample(); // gated by iff -- must NOT hit 'def'
`checkr(cg2.get_inst_coverage(), 100.0);
// cg3: array bins with iff (3 bins: arr[5], arr[6], arr[7])
// 1/3 hit -> 33.3% (not a clean binary fraction; no checkr)
enable = 1;
2026-06-06 00:36:55 +02:00
value = 5;
cg3.sample(); // arr[5] hit
enable = 0;
2026-06-06 00:36:55 +02:00
value = 6;
cg3.sample(); // gated
// cg4: 2-step transition with iff
enable = 1;
2026-06-06 00:36:55 +02:00
value = 1;
cg4.sample();
`checkr(cg4.get_inst_coverage(), 0.0);
2026-06-06 00:36:55 +02:00
value = 2;
cg4.sample(); // (1=>2) hit with enable=1
`checkr(cg4.get_inst_coverage(), 100.0);
enable = 0;
2026-06-06 00:36:55 +02:00
value = 1;
cg4.sample();
value = 2;
cg4.sample(); // (1=>2) gated by iff
`checkr(cg4.get_inst_coverage(), 100.0);
// cg5: 3-step transition with iff
enable = 1;
2026-06-06 00:36:55 +02:00
value = 1;
cg5.sample();
value = 2;
cg5.sample(); // mid-sequence, enable=1
enable = 0;
2026-06-06 00:36:55 +02:00
value = 3;
cg5.sample(); // iff is disabled at step 3 - incomplete sequence is discarded
`checkr(cg5.get_inst_coverage(), 0.0);
enable = 1;
2026-06-06 00:36:55 +02:00
value = 1;
cg5.sample();
value = 2;
cg5.sample();
value = 3;
cg5.sample(); // (1=>2=>3) fully hit with enable=1
`checkr(cg5.get_inst_coverage(), 100.0);
// --- compound iff expressions ---
// cg_and: guard true -> {0,1}=2'b01 sampled into b01
2026-06-06 00:36:55 +02:00
m_is_read = 0;
m_be = 4'b0001;
m_a = 2'b10;
m_b = 2'b11; // m_a[0]=0,m_b[0]=1 -> 2'b01
ca.sample(); // b01 hit
`checkr(ca.get_inst_coverage(), 25.0);
2026-06-06 00:36:55 +02:00
m_is_read = 1;
m_a = 2'b11;
m_b = 2'b11; // guard false -> gated
ca.sample();
`checkr(ca.get_inst_coverage(), 25.0);
// cg_or: guard true via bit1
2026-06-06 00:36:55 +02:00
m_be = 4'b0010;
count = 1;
co.sample(); // lo hit
`checkr(co.get_inst_coverage(), 50.0);
2026-06-06 00:36:55 +02:00
m_be = 4'b0000;
count = 2;
co.sample(); // gated
`checkr(co.get_inst_coverage(), 50.0);
// cg_part: part-select != 0
2026-06-06 00:36:55 +02:00
m_be = 4'b1000;
count = 1;
cpp.sample(); // one hit
`checkr(cpp.get_inst_coverage(), 100.0);
2026-06-06 00:36:55 +02:00
m_be = 4'b0000;
count = 1;
cpp.sample(); // gated
`checkr(cpp.get_inst_coverage(), 100.0);
// cg_rel: count > 3
2026-06-06 00:36:55 +02:00
count = 5;
cr.sample(); // five hit (5>3)
`checkr(cr.get_inst_coverage(), 50.0);
2026-06-06 00:36:55 +02:00
count = 2;
cr.sample(); // two gated (2>3 false)
`checkr(cr.get_inst_coverage(), 50.0);
// cg_bitw: (m_a & m_b) == 2'b10
2026-06-06 00:36:55 +02:00
m_a = 2'b10;
m_b = 2'b11;
count = 7;
cb.sample(); // seven hit
`checkr(cb.get_inst_coverage(), 100.0);
2026-06-06 00:36:55 +02:00
m_a = 2'b00;
m_b = 2'b11;
count = 7;
cb.sample(); // gated
`checkr(cb.get_inst_coverage(), 100.0);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule