verilator/test_regress/t/t_covergroup_default_bins.v

215 lines
6.8 KiB
Systemverilog

// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain
// SPDX-FileCopyrightText: 2026 Matthew Ballance
// SPDX-License-Identifier: CC0-1.0
// Test default bins - catch-all for values not in other bins
// 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
// Non-covergroup class in the same module - must not interfere with covergroup processing
class DataHelper;
bit [7:0] val;
function new(bit [7:0] v); val = v; endfunction
endclass
module t;
bit [7:0] data;
logic [1:0] idx;
logic [63:0] data64;
logic [64:0] data65;
DataHelper helper;
// Signals for the unlabeled-coverpoint covergroups below
logic [1:0] a;
logic [1:0] b;
typedef struct packed {
logic [1:0] hi;
logic [1:0] lo;
} pair_t;
pair_t p;
covergroup cg;
coverpoint data {
bins low = {[0:3]};
bins high = {[12:15]};
bins other = default; // Catches everything else (4-11, 16+)
}
endgroup
// Covergroup with default as the only bin - catches all sampled values
covergroup cg2;
cp_only_default: coverpoint data {
bins all = default;
}
endgroup
// Covergroup with default + ignore + illegal bins - excluded values must not count toward coverage
covergroup cg3;
coverpoint data {
ignore_bins bad = {255}; // excluded from coverage
illegal_bins err = {254}; // illegal value, excluded from coverage
bins normal = {[1:10]};
bins other = default;
}
endgroup
// Auto-bins on a small range with one value excluded by ignore_bins -
// when the range is small enough, one auto-bin per valid value is created; the excluded value is skipped.
covergroup cg4;
cp_idx: coverpoint idx {
ignore_bins skip = {2}; // value 2 excluded; auto-bins created for 0,1,3
}
endgroup
// 64-bit signal with auto_bin_max=4
covergroup cg5;
cp_data64: coverpoint data64 { bins auto[4]; }
endgroup
// 65-bit signal with explicit range bins
covergroup cg6;
cp_data65: coverpoint data65 { bins lo = {[0:15]}; bins hi = {[100:200]}; }
endgroup
// Unlabeled coverpoint - the signal name is used as the coverpoint name
covergroup cg7;
coverpoint data { bins lo = {[0:7]}; bins hi = {[8:15]}; }
endgroup
// Multiple unlabeled coverpoints: each gets a unique deterministic name (the variable
// name for a single identifier). Previously two unlabeled coverpoints in one covergroup
// collided on the generated bin-variable name (e.g. duplicate '__Vcov__auto_0').
covergroup cg_plain;
option.auto_bin_max = 2;
coverpoint a;
coverpoint b;
endgroup
// Unlabeled coverpoints with compound (member-select) expressions get synthesized names.
covergroup cg_member;
option.auto_bin_max = 2;
coverpoint p.lo;
coverpoint p.hi;
endgroup
// A cross referencing unlabeled coverpoints by their derived names.
covergroup cg_cross;
option.auto_bin_max = 2;
coverpoint a;
coverpoint b;
ab: cross a, b;
endgroup
initial begin
cg cg_inst;
cg2 cg2_inst;
cg3 cg3_inst;
cg4 cg4_inst;
cg5 cg5_inst;
cg6 cg6_inst;
cg7 cg7_inst;
cg_plain cg_plain_inst;
cg_member cg_member_inst;
cg_cross cg_cross_inst;
cg_inst = new();
cg2_inst = new();
cg3_inst = new();
cg4_inst = new();
cg5_inst = new();
cg6_inst = new();
cg7_inst = new();
cg_plain_inst = new();
cg_member_inst = new();
cg_cross_inst = new();
helper = new(8'h42);
data = helper.val; // Use helper to avoid optimization
// Hit low bin
data = 2;
cg_inst.sample();
cg2_inst.sample();
`checkr(cg2_inst.get_inst_coverage(), 100.0); // cg2 has 1 bin (default) -> 100% after first sample
// Hit high bin
data = 14;
cg_inst.sample();
cg2_inst.sample();
// Hit default bin with value 7 (not in low or high)
data = 7;
cg_inst.sample();
cg2_inst.sample();
`checkr(cg_inst.get_inst_coverage(), 100.0); // all 3 bins (low, high, other) hit
// Hit another default value (should not increase coverage)
data = 20;
cg_inst.sample();
cg2_inst.sample();
`checkr(cg_inst.get_inst_coverage(), 100.0);
`checkr(cg2_inst.get_inst_coverage(), 100.0);
// Sample cg3: verify ignore/illegal bins do not contribute to coverage
data = 2;
cg3_inst.sample(); // hits normal bin
`checkr(cg3_inst.get_inst_coverage(), 100.0); // 1/1: only 'normal' counts (default/ignore/illegal excluded, LRM 19.5)
data = 7;
cg3_inst.sample(); // hits normal bin again
`checkr(cg3_inst.get_inst_coverage(), 100.0); // no new normal bins
data = 255;
cg3_inst.sample(); // ignore_bins value; recorded but excluded from coverage
`checkr(cg3_inst.get_inst_coverage(), 100.0);
// note: do not sample 254 (illegal_bins would cause runtime assertion)
data = 100;
cg3_inst.sample(); // hits default (other) bin; recorded but excluded from coverage
`checkr(cg3_inst.get_inst_coverage(), 100.0);
// Sample cg4: auto-bins with one excluded value
// idx=2 is in ignore_bins, so auto-bins cover 0, 1, 3 only (3 bins total)
idx = 0; cg4_inst.sample();
idx = 1; cg4_inst.sample();
idx = 3; cg4_inst.sample();
`checkr(cg4_inst.get_inst_coverage(), 100.0);
// Sample cg5: 64-bit signal, 4 auto bins; values 0 and 5 both fall in first bin
data64 = 0; cg5_inst.sample();
`checkr(cg5_inst.get_inst_coverage(), 25.0); // 1/4 bins hit
data64 = 5; cg5_inst.sample();
`checkr(cg5_inst.get_inst_coverage(), 25.0); // same bin, no increase
// Sample cg6: 65-bit signal with range bins
data65 = 5;
cg6_inst.sample(); // hits bin lo=[0:15]
`checkr(cg6_inst.get_inst_coverage(), 50.0);
data65 = 150;
cg6_inst.sample(); // hits bin hi=[100:200]
`checkr(cg6_inst.get_inst_coverage(), 100.0);
// Sample cg7: unlabeled coverpoint
data = 3;
cg7_inst.sample(); // hits bin lo
`checkr(cg7_inst.get_inst_coverage(), 50.0);
data = 10;
cg7_inst.sample(); // hits bin hi
`checkr(cg7_inst.get_inst_coverage(), 100.0);
// cg_plain: two unlabeled coverpoints (a, b), 2 auto bins each -> distinct names
a = 0; b = 3; cg_plain_inst.sample();
`checkr(cg_plain_inst.get_inst_coverage(), 50.0);
// cg_member: unlabeled member-select coverpoints (synthesized names)
p.lo = 0; p.hi = 3; cg_member_inst.sample();
`checkr(cg_member_inst.get_inst_coverage(), 50.0);
// cg_cross: cross of unlabeled coverpoints referenced by derived name
a = 0; b = 0; cg_cross_inst.sample();
a = 3; b = 3; cg_cross_inst.sample();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule