Remove low-value tests ; Rename tests to better-align with their purpose ; Move to using coverage.dat to assess correctness

Signed-off-by: Matthew Ballance <matt.ballance@gmail.com>
This commit is contained in:
Matthew Ballance 2026-03-14 16:59:55 +00:00
parent e5594e9c6c
commit 1ec09f9d2d
145 changed files with 577 additions and 2109 deletions

View File

@ -248,59 +248,6 @@ coverpoints with value and transition bins, and cross points.
endmodule
Supported Features
^^^^^^^^^^^^^^^^^^
* Coverpoints on integral expressions with value, range, wildcard, and transition bins
* Conditional coverpoint sampling (iff)
* Explicit and clocked sampling, with sample-function parameters
* at_least and auto_bin_max options on covergroups and coverpoints
* Cross points with auto-bins
Unsupported Features
^^^^^^^^^^^^^^^^^^^^
* Coverpoints on real (floating-point) expressions
* Coverpoint bin filtering (with)
* Coverpoint bin conditional sampling (iff)
* Transition bins with repetition operators ([\*N], [->N], [=N])
* Explicitly-typed coverpoints
* Block-event sampling
* Covergroup inheritance (extends)
* Cross points with user-defined bins
Functional Coverage Data Format
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Functional coverage data is stored in the coverage data file (typically
:file:`coverage.dat`) using the standard Verilator coverage format. Each
functional coverage bin is recorded as a coverage point with:
* **Type**: ``funccov`` - identifies the record as functional coverage
* **Page**: ``v_funccov/<covergroup_name>`` - groups bins by their covergroup
* **Hierarchy**: ``<covergroup>.<coverpoint>.<bin>`` for coverpoints, or
``<covergroup>.<cross>.<bin>`` for cross coverage
* **Count**: Number of times the bin was hit during simulation
Example coverage.dat entries:
.. code-block::
C 'tfunccovpagev_funccov/cgftest.vl28hcg.cp_a.low' 150
C 'tfunccovpagev_funccov/cgftest.vl29hcg.cp_a.high' 75
C 'tfunccovpagev_funccov/cgftest.vl35hcg.cross_ab.a0_b1' 25
To filter functional coverage data, use the :option:`--filter-type` option
with :command:`verilator_coverage`:
.. code-block:: bash
# Only process functional coverage
$ verilator_coverage --filter-type funccov --annotate report coverage.dat
# Exclude functional coverage
$ verilator_coverage --filter-type '!funccov' --annotate report coverage.dat
.. _line coverage:
Line Coverage

View File

@ -139,8 +139,8 @@ class FunctionalCoverageVisitor final : public VNVisitor {
}
const int numBins = constp->toSInt();
if (numBins <= 0 || numBins > 10000) {
cbinp->v3error("Automatic bins array size must be 1-10000, got "
if (numBins <= 0) {
cbinp->v3error("Automatic bins array size must be >= 1, got "
+ std::to_string(numBins));
binp = nextBinp;
continue;
@ -741,6 +741,17 @@ class FunctionalCoverageVisitor final : public VNVisitor {
if (caseItemp) { casep->addItemsp(caseItemp); }
}
// Add default case (reset to state 0) to prevent CASEINCOMPLETE warnings,
// since the state variable is wider than the number of valid states.
AstCaseItem* defaultItemp
= new AstCaseItem{binp->fileline(), nullptr,
new AstAssign{binp->fileline(),
new AstVarRef{binp->fileline(), stateVarp,
VAccess::WRITE},
new AstConst{binp->fileline(),
AstConst::WidthedValue{}, 8, 0}}};
casep->addItemsp(defaultItemp);
m_sampleFuncp->addStmtsp(casep);
UINFO(4, " Successfully added multi-value transition state machine" << endl);
}
@ -1716,12 +1727,6 @@ class FunctionalCoverageVisitor final : public VNVisitor {
AstCoverpoint* coverpointp = binInfo.coverpointp;
AstCoverCross* crossp = binInfo.crossp;
// Skip illegal and ignore bins - they don't count towards coverage
if (binp->binsType() == VCoverBinsType::BINS_IGNORE
|| binp->binsType() == VCoverBinsType::BINS_ILLEGAL) {
continue;
}
FileLine* fl = binp->fileline();
// Build hierarchical name: covergroup.coverpoint.bin or covergroup.cross.bin
@ -1765,7 +1770,13 @@ class FunctionalCoverageVisitor final : public VNVisitor {
insertCall += "\"filename\", \"" + fl->filename() + "\", ";
insertCall += "\"lineno\", \"" + std::to_string(fl->lineno()) + "\", ";
insertCall += "\"column\", \"" + std::to_string(fl->firstColumn()) + "\", ";
insertCall += "\"bin\", \"" + binName + "\");";
if (binp->binsType() == VCoverBinsType::BINS_IGNORE) {
insertCall += "\"bin\", \"" + binName + "\", \"bin_type\", \"ignore\");";
} else if (binp->binsType() == VCoverBinsType::BINS_ILLEGAL) {
insertCall += "\"bin\", \"" + binName + "\", \"bin_type\", \"illegal\");";
} else {
insertCall += "\"bin\", \"" + binName + "\");";
}
// Create a statement node with the coverage insert call
AstCStmt* cstmtp = new AstCStmt{fl, insertCall};

View File

@ -2802,6 +2802,35 @@ class VlTest:
self._file_contents_cache[filename] = str(fh.read())
return self._file_contents_cache[filename]
def covergroup_coverage_report(self, outfile: str = None) -> str:
"""Parse coverage.dat and write a sorted covergroup bin hit-count report.
Lines have the form: <hierarchy>[ [bin_type]]: <count>
ignore_bins and illegal_bins are annotated with [ignore] / [illegal].
Returns the path to the written report file.
"""
if outfile is None:
outfile = self.obj_dir + "/covergroup_report.txt"
contents = self.file_contents(self.coverage_filename)
entries = []
for m in re.finditer(r"C '([^']+)' (\d+)", contents):
entry, count = m.group(1), m.group(2)
if '\x01t\x02covergroup' not in entry:
continue
h_m = re.search(r'\x01h\x02([^\x01]+)', entry)
if not h_m:
continue
hier = h_m.group(1)
bt_m = re.search(r'\x01bin_type\x02([^\x01]+)', entry)
label = f"{hier} [{bt_m.group(1)}]" if bt_m else hier
entries.append((hier, label, int(count)))
entries.sort()
with open(outfile, 'w', encoding='utf-8') as fh:
for _hier, label, count in entries:
fh.write(f"{label}: {count}\n")
return outfile
@staticmethod
def _file_contents_static(filename: str) -> str:
if filename not in VlTest._file_contents_cache:

View File

@ -14,7 +14,6 @@ module t;
cg cov2 = new(69);
int i, j;
real r;
function void x();
cov1.set_inst_name("the_inst_name");
@ -23,16 +22,14 @@ module t;
cov1.stop();
void'(cov2.get_coverage());
r = cov2.get_coverage();
r = cov2.get_coverage(i, j);
void'(cov2.get_coverage(i, j));
// verilator lint_off IGNOREDRETURN
cov2.get_inst_coverage();
// verilator lint_on IGNOREDRETURN
r = cov2.get_inst_coverage(i, j);
void'(cov2.get_inst_coverage(i, j));
cg::get_coverage();
r = cg::get_coverage();
r = cg::get_coverage(i, j);
void'(cg::get_coverage());
void'(cg::get_coverage(i, j));
endfunction
endmodule

View File

@ -0,0 +1,2 @@
cg.data.grouped: 2
cg.data.values: 3

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -7,7 +7,6 @@
// Test array bins - separate bin per value
module t;
/* verilator lint_off UNSIGNED */
bit [7:0] data;
covergroup cg;
@ -22,65 +21,29 @@ module t;
initial begin
cg cg_inst;
real cov;
cg_inst = new();
// Initial coverage should be 0%
cov = cg_inst.get_inst_coverage();
if (cov != 0.0) begin
$error("Expected 0%% coverage, got %0.2f%%", cov);
end
// Hit first array bin value (1)
data = 1;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After hitting value 1: %0.2f%%", cov);
// 1 bin out of 4 total bins (3 array bins + 1 grouped bin)
if (cov < 23.0 || cov > 27.0) begin
$error("Expected ~25%% (1/4 bins), got %0.2f%%", cov);
end
// Hit second array bin value (5)
data = 5;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After hitting value 5: %0.2f%%", cov);
// 2 bins out of 4
if (cov < 48.0 || cov > 52.0) begin
$error("Expected ~50%% (2/4 bins), got %0.2f%%", cov);
end
// Hit the grouped bin (covers all of 2, 6, 10)
data = 6;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After hitting grouped bin: %0.2f%%", cov);
// 3 bins out of 4
if (cov < 73.0 || cov > 77.0) begin
$error("Expected ~75%% (3/4 bins), got %0.2f%%", cov);
end
// Hit third array bin value (9)
data = 9;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After hitting value 9: %0.2f%%", cov);
// All 4 bins covered
if (cov != 100.0) begin
$error("Expected 100%% (4/4 bins), got %0.2f%%", cov);
end
// Verify hitting other values in grouped bin doesn't increase coverage
data = 2;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
if (cov != 100.0) begin
$error("Coverage should stay 100%%, got %0.2f%%", cov);
end
$display("Array bins test PASSED");
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -0,0 +1,12 @@
cg1.cp_data3.auto_0: 1
cg1.cp_data3.auto_1: 0
cg1.cp_data3.auto_2: 0
cg1.cp_data3.auto_3: 1
cg1.cp_data3.auto_4: 0
cg1.cp_data3.auto_5: 0
cg1.cp_data3.auto_6: 0
cg1.cp_data3.auto_7: 0
cg2.cp_data3.auto_0: 1
cg2.cp_data3.auto_1: 0
cg2.cp_data3.auto_2: 1
cg2.cp_data3.auto_3: 0

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile(verilator_flags2=["-Wno-UNSIGNED -Wno-CMPCONST"])
test.compile(verilator_flags2=['--coverage', '-Wno-UNSIGNED', '-Wno-CMPCONST'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -0,0 +1,42 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Wilson Snyder.
// SPDX-FileCopyrightText: 2024 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// Test implicit auto-bin creation (no explicit bins) and option.auto_bin_max
module t;
logic [2:0] data3;
// Test 1: auto_bin_max default (64) - creates 8 bins for 3-bit signal
covergroup cg1;
cp_data3: coverpoint data3;
endgroup
// Test 2: auto_bin_max = 4 - creates 4 bins: [0:1],[2:3],[4:5],[6:7]
covergroup cg2;
option.auto_bin_max = 4;
cp_data3: coverpoint data3;
endgroup
initial begin
cg1 cg1_inst;
cg2 cg2_inst;
cg1_inst = new;
cg2_inst = new;
data3 = 0; cg1_inst.sample();
data3 = 3; cg1_inst.sample();
data3 = 0; cg2_inst.sample();
data3 = 4; cg2_inst.sample();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,4 @@
cg.data.auto[0]: 1
cg.data.auto[1]: 1
cg.data.auto[2]: 1
cg.data.auto[3]: 1

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -8,7 +8,6 @@
// SPDX-License-Identifier: CC0-1.0
module t;
/* verilator lint_off UNSIGNED */
/* verilator lint_off CMPCONST */
logic [2:0] data; // 3-bit: 0-7
@ -23,27 +22,22 @@ module t;
automatic cg cg_inst = new;
// Initial coverage should be 0%
$display("Coverage initial: %f%% (expected ~0.00%%)", cg_inst.get_inst_coverage());
// Sample first bin: 0 or 1
data = 0;
cg_inst.sample();
$display("Coverage after 0: %f%% (expected ~25.00%%)", cg_inst.get_inst_coverage());
// Sample second bin: 2 or 3
data = 2;
cg_inst.sample();
$display("Coverage after 2: %f%% (expected ~50.00%%)", cg_inst.get_inst_coverage());
// Sample third bin: 4 or 5
data = 5;
cg_inst.sample();
$display("Coverage after 5: %f%% (expected ~75.00%%)", cg_inst.get_inst_coverage());
// Sample fourth bin: 6 or 7
data = 7;
cg_inst.sample();
$display("Coverage complete: %f%% (expected ~100.00%%)", cg_inst.get_inst_coverage());
$write("*-* All Finished *-*\n");
$finish;

View File

@ -12,7 +12,7 @@ import vltest_bootstrap
test.scenarios('vlt')
# Use the same .v file as the non-timing test
test.top_filename = "t/t_covergroup_auto_sample.v"
test.top_filename = "t/t_covergroup_clocked_sample.v"
test.compile(v_flags2=["--timing"])

View File

@ -1,113 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Wilson Snyder.
// SPDX-FileCopyrightText: 2024 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// 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
// Test automatic bin creation when coverpoint has no explicit bins
module t(/*AUTOARG*/
// Inputs
clk
);
input clk;
logic [2:0] data3; // 3-bit: values 0-7
logic [1:0] data2; // 2-bit: values 0-3
// Test 1: auto_bin_max default (64) - should create 8 bins for 3-bit signal
// Each value should get its own bin since 2^3 = 8 < 64
covergroup cg1;
cp_data3: coverpoint data3; // No bins specified - autobins
endgroup
// Test 2: With option.auto_bin_max = 4
// Should create 4 bins: [0:1], [2:3], [4:5], [6:7]
covergroup cg2;
option.auto_bin_max = 4;
cp_data3: coverpoint data3; // No bins specified - autobins
endgroup
// Test 3: With ignore bins - should still auto-create for non-ignored values
// Autobins created, but value 7 is ignored
covergroup cg3;
cp_data3: coverpoint data3 {
ignore_bins reserved = {7};
}
endgroup
// Test 4: Smaller signal - 2-bit
// Should create 4 bins (one per value) since 2^2 = 4 < 64
covergroup cg4;
cp_data2: coverpoint data2; // No bins specified - autobins
endgroup
// Test 5: With auto_bin_max smaller than signal range
// 2-bit signal (0-3) with auto_bin_max=2 should create 2 bins: [0:1], [2:3]
covergroup cg5;
option.auto_bin_max = 2;
cp_data2: coverpoint data2; // No bins specified - autobins
endgroup
initial begin
cg1 cg1_inst;
cg2 cg2_inst;
cg3 cg3_inst;
cg4 cg4_inst;
cg5 cg5_inst;
cg1_inst = new;
cg2_inst = new;
cg3_inst = new;
cg4_inst = new;
cg5_inst = new;
// Test CG1: Hit values 0, 1, 2 (3 of 8 bins = 37.5%)
data3 = 0; cg1_inst.sample();
data3 = 1; cg1_inst.sample();
data3 = 2; cg1_inst.sample();
// Test CG2: Hit values 0, 1, 4 (bins [0:1] and [4:5], 2 of 4 bins = 50%)
data3 = 0; cg2_inst.sample();
data3 = 1; cg2_inst.sample();
data3 = 4; cg2_inst.sample();
// Test CG3: Hit values 0, 1, 7 (7 is ignored, so 2 of 7 valid bins = 28.6%)
data3 = 0; cg3_inst.sample();
data3 = 1; cg3_inst.sample();
data3 = 7; cg3_inst.sample(); // Ignored
// Test CG4: Hit all values 0-3 (4 of 4 bins = 100%)
data2 = 0; cg4_inst.sample();
data2 = 1; cg4_inst.sample();
data2 = 2; cg4_inst.sample();
data2 = 3; cg4_inst.sample();
// Test CG5: Hit values 0, 3 (bins [0:1] and [2:3], 2 of 2 bins = 100%)
data2 = 0; cg5_inst.sample();
data2 = 3; cg5_inst.sample();
$display("CG1 (8 autobins): %0.1f%%", cg1_inst.get_inst_coverage());
$display("CG2 (4 autobins w/ option): %0.1f%%", cg2_inst.get_inst_coverage());
$display("CG3 (7 autobins w/ ignore): %0.1f%%", cg3_inst.get_inst_coverage());
$display("CG4 (4 autobins): %0.1f%%", cg4_inst.get_inst_coverage());
$display("CG5 (2 autobins w/ option): %0.1f%%", cg5_inst.get_inst_coverage());
// Validate coverage results
`checkr(cg1_inst.get_inst_coverage(), 37.5);
`checkr(cg2_inst.get_inst_coverage(), 50.0);
`checkr(cg3_inst.get_inst_coverage(), 100.0 * (2.0/7.0));
`checkr(cg4_inst.get_inst_coverage(), 100.0);
`checkr(cg5_inst.get_inst_coverage(), 100.0);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -3,12 +3,8 @@
17 | bins auto[size_var];
| ^~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_covergroup_autobins_bad.v:24:12: Automatic bins array size must be 1-10000, got 0
%Error: t/t_covergroup_autobins_bad.v:24:12: Automatic bins array size must be >= 1, got 0
: ... note: In instance 't'
24 | bins auto[0];
| ^~~~
%Error: t/t_covergroup_autobins_bad.v:31:12: Automatic bins array size must be 1-10000, got 10001
: ... note: In instance 't'
31 | bins auto[10001];
| ^~~~
%Error: Exiting due to

View File

@ -18,23 +18,15 @@ module t;
}
endgroup
// Error: array size must be 1-10000 (zero)
// Error: array size must be >= 1 (zero)
covergroup cg2;
cp1: coverpoint cp_expr {
bins auto[0];
}
endgroup
// Error: array size must be 1-10000 (too large)
covergroup cg3;
cp1: coverpoint cp_expr {
bins auto[10001];
}
endgroup
cg1 cg1_inst = new;
cg2 cg2_inst = new;
cg3 cg3_inst = new;
initial $finish;
endmodule

View File

@ -0,0 +1,2 @@
cg.data.low: 3
cg.data.zero: 1

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -6,21 +6,13 @@
// Test viewing individual bin hit counts
// 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 (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [3:0] data;
covergroup cg;
coverpoint data {
bins zero = {0};
bins low = {[1:3]};
bins mid = {[4:7]};
bins high = {[8:15]};
bins zero = {0};
bins low = {[1:3]};
}
endgroup
@ -29,16 +21,10 @@ module t (/*AUTOARG*/);
initial begin
cg_inst = new;
// Sample various values with different frequencies
data = 0; cg_inst.sample(); // zero: 1
data = 1; cg_inst.sample(); // low: 1
data = 2; cg_inst.sample(); // low: 2
data = 2; cg_inst.sample(); // low: 3
data = 5; cg_inst.sample(); // mid: 1
data = 10; cg_inst.sample(); // high: 1
// Verify coverage is 100% (all 4 bins hit)
`checkr(cg_inst.get_inst_coverage(), 100.0);
data = 0; cg_inst.sample(); // zero: 1
data = 1; cg_inst.sample(); // low: 1
data = 2; cg_inst.sample(); // low: 2
data = 2; cg_inst.sample(); // low: 3
$write("*-* All Finished *-*\n");
$finish;

View File

@ -0,0 +1,4 @@
cg.cp_data.one: 1
cg.cp_data.three: 1
cg.cp_data.two: 1
cg.cp_data.zero: 2

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -1,4 +1,4 @@
// DESCRIPTION: Verilator: Test automatic sampling with clocking events
// DESCRIPTION: Verilator: Test covergroup clocked (automatic) sampling
// Tests --no-timing (default) mode; see t_covergroup_auto_sample_timing for --timing variant.
// This file ONLY is placed into the Public Domain, for any use, without warranty.
// SPDX-FileCopyrightText: 2025 Wilson Snyder
@ -30,28 +30,16 @@ module t (/*AUTOARG*/
cyc <= cyc + 1;
case (cyc)
0: data <= 2'b00; // Hit bin zero
1: data <= 2'b01; // Hit bin one
2: data <= 2'b10; // Hit bin two
3: data <= 2'b11; // Hit bin three
0: data <= 2'b00;
1: data <= 2'b01;
2: data <= 2'b10;
3: data <= 2'b11;
4: begin
$display("Coverage: %f%%", cg_inst.get_inst_coverage());
if (cg_inst.get_inst_coverage() >= 99.0) begin
$write("*-* All Finished *-*\n");
$finish;
end else begin
$display("ERROR: Expected 100%% coverage, got %f%%", cg_inst.get_inst_coverage());
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
endcase
// NOTE: NO manual .sample() call - relying on automatic sampling!
// Auto-stop after 10 cycles to prevent infinite loop
if (cyc > 10) begin
$display("ERROR: Test timed out");
$stop;
end
end
endmodule

View File

@ -1,18 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of either the GNU Lesser General Public License Version 3
# or the Perl Artistic License Version 2.0.
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt')
test.compile(verilator_flags2=["--timing"])
test.execute(fails=True, expect=r'%Error: .*Timeout')
test.passes()

View File

@ -1,83 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty.
// SPDX-FileCopyrightText: 2025 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// Test: Covergroup with INTERNAL clock using explicit sampling
// This demonstrates the workaround for internally generated clocks.
//
// Note: Auto-sampling with clocking events (@(posedge clk)) does NOT work
// for internal clocks due to Verilator timing scheduler limitations.
// The sample() call is generated but the NBA region isn't triggered.
//
// Root cause: Timing scheduler doesn't trigger NBA/active regions for
// internally generated clock edges. Even explicit .sample() calls in
// always @(posedge clk) blocks don't execute in --timing mode.
//
// Workaround: Use module input clocks (see t_covergroup_auto_sample.v)
//
// Solution: Call .sample() explicitly in an always block.
module t;
logic clk = 0;
always #5 clk = ~clk;
logic [1:0] data;
/* verilator lint_off UNSIGNED */
covergroup cg; // NOTE: No clocking event - we'll sample explicitly
cp: coverpoint data {
bins val0 = {2'b00};
bins val1 = {2'b01};
bins val2 = {2'b10};
bins val3 = {2'b11};
}
endgroup
/* verilator lint_on UNSIGNED */
cg cg_inst = new;
// Explicit sampling workaround for internal clocks
always @(posedge clk) begin
cg_inst.sample();
end
initial begin
// Cycle 0
data = 2'b00;
@(posedge clk);
// Cycle 1
data = 2'b01;
@(posedge clk);
// Cycle 2
data = 2'b10;
@(posedge clk);
// Cycle 3
data = 2'b11;
@(posedge clk);
// Check coverage
#1; // Small delay to ensure last sample completes
begin
automatic real cov = cg_inst.get_inst_coverage();
$display("Coverage: %0.1f%%", cov);
// Should have hit all 4 bins = 100%
if (cov >= 99.0) begin
$write("*-* All Finished *-*\n");
$finish;
end else begin
$display("ERROR: Expected 100%% coverage, got %f%%", cov);
$display("ERROR: This is a known limitation - auto-sampling doesn't work with internal clocks");
$stop;
end
end
end
endmodule

View File

@ -1,18 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of either the GNU Lesser General Public License Version 3
# or the Perl Artistic License Version 2.0.
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.execute()
test.passes()

View File

@ -1,60 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty.
// SPDX-FileCopyrightText: 2025 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// Test: Covergroup with clocking event using MODULE INPUT clock
// Status: WORKS - Verilator correctly auto-samples when clk is a module port
module t(/*AUTOARG*/
// Inputs
clk
);
input clk;
logic [1:0] data;
/* verilator lint_off UNSIGNED */
covergroup cg @(posedge clk);
cp: coverpoint data {
bins val0 = {2'b00};
bins val1 = {2'b01};
bins val2 = {2'b10};
bins val3 = {2'b11};
}
endgroup
/* verilator lint_on UNSIGNED */
cg cg_inst = new;
int cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
// Change data each cycle
data <= cyc[1:0];
if (cyc == 5) begin
automatic real cov = cg_inst.get_inst_coverage();
$display("Coverage: %0.1f%%", cov);
// Should have hit all 4 bins (cycles 0-3) = 100%
if (cov >= 99.0) begin
$write("*-* All Finished *-*\n");
$finish;
end else begin
$display("ERROR: Expected 100%% coverage, got %f%%", cov);
$stop;
end
end
if (cyc > 10) begin
$display("ERROR: Test timeout");
$stop;
end
end
endmodule

View File

@ -1,17 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-FileCopyrightText: 2024 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=['--timing'])
test.execute()
test.passes()

View File

@ -1,76 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Wilson Snyder.
// SPDX-FileCopyrightText: 2024 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// 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 (/*AUTOARG*/
// Inputs
clk
);
input clk;
logic [1:0] data;
// Covergroup with 4 bins
covergroup cg @(posedge clk);
cp: coverpoint data {
bins low = {2'b00};
bins mid1 = {2'b01};
bins mid2 = {2'b10};
bins high = {2'b11};
}
endgroup
cg cg_inst = new;
initial begin
// Initially no bins covered - should be 0%
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage after 0 samples: %f", cov);
`checkr(cov, 0.0);
// Cover 1 bin (low) - should be 25%
@(posedge clk);
data = 2'b00;
@(posedge clk);
cov = cg_inst.get_inst_coverage();
$display("Coverage after 1/4 bins: %f", cov);
`checkr(cov, 25.0);
// Cover 2nd bin (mid1) - should be 50%
@(posedge clk);
data = 2'b01;
@(posedge clk);
cov = cg_inst.get_inst_coverage();
$display("Coverage after 2/4 bins: %f", cov);
`checkr(cov, 50.0);
// Cover 3rd bin (mid2) - should be 75%
@(posedge clk);
data = 2'b10;
@(posedge clk);
cov = cg_inst.get_inst_coverage();
$display("Coverage after 3/4 bins: %f", cov);
`checkr(cov, 75.0);
// Cover 4th bin (high) - should be 100%
@(posedge clk);
data = 2'b11;
@(posedge clk);
cov = cg_inst.get_inst_coverage();
$display("Coverage after 4/4 bins: %f", cov);
`checkr(cov, 100.0);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,3 @@
cg.data.high: 1
cg.data.low: 1
cg.data.mid: 1

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -6,13 +6,7 @@
// Test querying coverage values via get_inst_coverage
// 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 (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [3:0] data;
covergroup cg;
@ -28,28 +22,20 @@ module t (/*AUTOARG*/);
initial begin
cg_inst = new;
// Initially no coverage
`checkr(cg_inst.get_inst_coverage(), 0.0);
// Sample low bin - should be 33.33% (1 of 3 bins)
// Sample low bin - should be 33.3% (1 of 3 bins)
data = 1;
cg_inst.sample();
`checkr(cg_inst.get_inst_coverage(), 100.0 * (1.0/3.0));
$display("After low: %0.1f%%", cg_inst.get_inst_coverage());
// Sample mid bin - should be 66.67% (2 of 3 bins)
// Sample mid bin - should be 66.7% (2 of 3 bins)
data = 5;
cg_inst.sample();
`checkr(cg_inst.get_inst_coverage(), 100.0 * (2.0/3.0));
$display("After mid: %0.1f%%", cg_inst.get_inst_coverage());
// Sample high bin - should be 100% (3 of 3 bins)
// Sample high bin - should be 100.0% (3 of 3 bins)
data = 10;
cg_inst.sample();
`checkr(cg_inst.get_inst_coverage(), 100.0);
// Sample again - coverage should still be 100%
data = 2;
cg_inst.sample();
`checkr(cg_inst.get_inst_coverage(), 100.0);
$display("After high: %0.1f%%", cg_inst.get_inst_coverage());
$write("*-* All Finished *-*\n");
$finish;

View File

@ -0,0 +1,35 @@
%Error: t/t_covergroup_coverpoint_method_unsup.v:31:42: Member 'a' not found in covergroup 'cg'
: ... note: In instance 't'
31 | $display("coverage a = %f", the_cg.a.get_inst_coverage());
| ^
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error-UNSUPPORTED: t/t_covergroup_coverpoint_method_unsup.v:31:44: Unsupported: Member call on object 'CONST '1'h0'' which is a 'BASICDTYPE 'logic''
: ... note: In instance 't'
31 | $display("coverage a = %f", the_cg.a.get_inst_coverage());
| ^~~~~~~~~~~~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: t/t_covergroup_coverpoint_method_unsup.v:32:42: Member 'b' not found in covergroup 'cg'
: ... note: In instance 't'
32 | $display("coverage b = %f", the_cg.b.get_inst_coverage());
| ^
%Error-UNSUPPORTED: t/t_covergroup_coverpoint_method_unsup.v:32:44: Unsupported: Member call on object 'CONST '1'h0'' which is a 'BASICDTYPE 'logic''
: ... note: In instance 't'
32 | $display("coverage b = %f", the_cg.b.get_inst_coverage());
| ^~~~~~~~~~~~~~~~~
%Error: t/t_covergroup_coverpoint_method_unsup.v:33:18: Member 'a' not found in covergroup 'cg'
: ... note: In instance 't'
33 | if (the_cg.a.get_inst_coverage() != 15 / 16.0) $stop();
| ^
%Error-UNSUPPORTED: t/t_covergroup_coverpoint_method_unsup.v:33:20: Unsupported: Member call on object 'CONST '1'h0'' which is a 'BASICDTYPE 'logic''
: ... note: In instance 't'
33 | if (the_cg.a.get_inst_coverage() != 15 / 16.0) $stop();
| ^~~~~~~~~~~~~~~~~
%Error: t/t_covergroup_coverpoint_method_unsup.v:34:18: Member 'b' not found in covergroup 'cg'
: ... note: In instance 't'
34 | if (the_cg.b.get_inst_coverage() != 4 / 5.0) $stop();
| ^
%Error-UNSUPPORTED: t/t_covergroup_coverpoint_method_unsup.v:34:20: Unsupported: Member call on object 'CONST '1'h0'' which is a 'BASICDTYPE 'logic''
: ... note: In instance 't'
34 | if (the_cg.b.get_inst_coverage() != 4 / 5.0) $stop();
| ^~~~~~~~~~~~~~~~~
%Error: Exiting due to

View File

@ -1,52 +0,0 @@
%Warning-COVERIGN: t/t_covergroup_coverpoints_unsup.v:19:17: Ignoring unsupported: coverage clocking event
19 | covergroup cg @(posedge clk);
| ^
... For warning description see https://verilator.org/warn/COVERIGN?v=latest
... Use "/* verilator lint_off COVERIGN */" and lint_on around source to disable this message.
%Warning-COVERIGN: t/t_covergroup_coverpoints_unsup.v:20:5: Ignoring unsupported: coverpoint
20 | coverpoint a;
| ^~~~~~~~~~
%Warning-COVERIGN: t/t_covergroup_coverpoints_unsup.v:21:36: Ignoring unsupported: cover bin specification
21 | coverpoint b {bins the_bins[5] = {[0 : 20]};}
| ^
%Warning-COVERIGN: t/t_covergroup_coverpoints_unsup.v:21:5: Ignoring unsupported: coverpoint
21 | coverpoint b {bins the_bins[5] = {[0 : 20]};}
| ^~~~~~~~~~
%Warning-COVERIGN: t/t_covergroup_coverpoints_unsup.v:19:3: Ignoring unsupported: covergroup
19 | covergroup cg @(posedge clk);
| ^~~~~~~~~~
%Error: t/t_covergroup_coverpoints_unsup.v:31:42: Member 'a' not found in covergroup 'cg'
: ... note: In instance 't'
31 | $display("coverage a = %f", the_cg.a.get_inst_coverage());
| ^
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error-UNSUPPORTED: t/t_covergroup_coverpoints_unsup.v:31:44: Unsupported: Member call on object 'CONST '1'h0'' which is a 'BASICDTYPE 'bit''
: ... note: In instance 't'
31 | $display("coverage a = %f", the_cg.a.get_inst_coverage());
| ^~~~~~~~~~~~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: t/t_covergroup_coverpoints_unsup.v:32:42: Member 'b' not found in covergroup 'cg'
: ... note: In instance 't'
32 | $display("coverage b = %f", the_cg.b.get_inst_coverage());
| ^
%Error-UNSUPPORTED: t/t_covergroup_coverpoints_unsup.v:32:44: Unsupported: Member call on object 'CONST '1'h0'' which is a 'BASICDTYPE 'bit''
: ... note: In instance 't'
32 | $display("coverage b = %f", the_cg.b.get_inst_coverage());
| ^~~~~~~~~~~~~~~~~
%Error: t/t_covergroup_coverpoints_unsup.v:33:18: Member 'a' not found in covergroup 'cg'
: ... note: In instance 't'
33 | if (the_cg.a.get_inst_coverage() != 15 / 16.0) $stop();
| ^
%Error-UNSUPPORTED: t/t_covergroup_coverpoints_unsup.v:33:20: Unsupported: Member call on object 'CONST '1'h0'' which is a 'BASICDTYPE 'bit''
: ... note: In instance 't'
33 | if (the_cg.a.get_inst_coverage() != 15 / 16.0) $stop();
| ^~~~~~~~~~~~~~~~~
%Error: t/t_covergroup_coverpoints_unsup.v:34:18: Member 'b' not found in covergroup 'cg'
: ... note: In instance 't'
34 | if (the_cg.b.get_inst_coverage() != 4 / 5.0) $stop();
| ^
%Error-UNSUPPORTED: t/t_covergroup_coverpoints_unsup.v:34:20: Unsupported: Member call on object 'CONST '1'h0'' which is a 'BASICDTYPE 'bit''
: ... note: In instance 't'
34 | if (the_cg.b.get_inst_coverage() != 4 / 5.0) $stop();
| ^~~~~~~~~~~~~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
cg.addr_cmd_mode.addr0_x_read_x_debug: 0
cg.addr_cmd_mode.addr0_x_read_x_normal: 1
cg.addr_cmd_mode.addr0_x_write_x_debug: 1
cg.addr_cmd_mode.addr0_x_write_x_normal: 0
cg.addr_cmd_mode.addr1_x_read_x_debug: 0
cg.addr_cmd_mode.addr1_x_read_x_normal: 0
cg.addr_cmd_mode.addr1_x_write_x_debug: 0
cg.addr_cmd_mode.addr1_x_write_x_normal: 1
cg.addr_cmd_mode.addr2_x_read_x_debug: 1
cg.addr_cmd_mode.addr2_x_read_x_normal: 0
cg.addr_cmd_mode.addr2_x_write_x_debug: 0
cg.addr_cmd_mode.addr2_x_write_x_normal: 0
cg.cp_addr.addr0: 2
cg.cp_addr.addr1: 1
cg.cp_addr.addr2: 1
cg.cp_cmd.read: 2
cg.cp_cmd.write: 2
cg.cp_mode.debug: 2
cg.cp_mode.normal: 2

View File

@ -10,8 +10,13 @@
import vltest_bootstrap
test.scenarios('simulator')
test.compile()
test.scenarios('vlt')
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -4,11 +4,6 @@
// SPDX-FileCopyrightText: 2026 Matthew Ballance
// SPDX-License-Identifier: CC0-1.0
// 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
// Test 3-way cross coverage
module t;
@ -38,34 +33,10 @@ module t;
cg cg_inst = new;
initial begin
// Hit different 3-way cross bins
addr = 0; cmd = 0; mode = 0; cg_inst.sample(); // addr0 x read x normal
$display("Sample 1: addr=%0d, cmd=%0d, mode=%0d", addr, cmd, mode);
addr = 1; cmd = 1; mode = 0; cg_inst.sample(); // addr1 x write x normal
$display("Sample 2: addr=%0d, cmd=%0d, mode=%0d", addr, cmd, mode);
addr = 2; cmd = 0; mode = 1; cg_inst.sample(); // addr2 x read x debug
$display("Sample 3: addr=%0d, cmd=%0d, mode=%0d", addr, cmd, mode);
addr = 0; cmd = 1; mode = 1; cg_inst.sample(); // addr0 x write x debug
$display("Sample 4: addr=%0d, cmd=%0d, mode=%0d", addr, cmd, mode);
addr = 1; cmd = 0; mode = 1; cg_inst.sample(); // addr1 x read x debug
$display("Sample 5: addr=%0d, cmd=%0d, mode=%0d", addr, cmd, mode);
// Check coverage
// Total bins:
// - 3 bins in cp_addr (addr0, addr1, addr2)
// - 2 bins in cp_cmd (read, write)
// - 2 bins in cp_mode (normal, debug)
// - 12 bins in 3-way cross (3 x 2 x 2)
// Total = 19 bins
// Hit: addr0, addr1, addr2 (3), read, write (2), normal, debug (2), 5 cross bins
// Total = 12 out of 19 = 63.2%
$display("Coverage: %0.1f%%", cg_inst.get_inst_coverage());
`checkr(cg_inst.get_inst_coverage(), 1200.0/19.0);
addr = 0; cmd = 0; mode = 0; cg_inst.sample(); // addr0 x read x normal
addr = 1; cmd = 1; mode = 0; cg_inst.sample(); // addr1 x write x normal
addr = 2; cmd = 0; mode = 1; cg_inst.sample(); // addr2 x read x debug
addr = 0; cmd = 1; mode = 1; cg_inst.sample(); // addr0 x write x debug
$write("*-* All Finished *-*\n");
$finish;

View File

@ -0,0 +1,24 @@
cg.addr_cmd_mode_parity.addr0_x_read_x_debug_x_even: 0
cg.addr_cmd_mode_parity.addr0_x_read_x_debug_x_odd: 0
cg.addr_cmd_mode_parity.addr0_x_read_x_normal_x_even: 1
cg.addr_cmd_mode_parity.addr0_x_read_x_normal_x_odd: 0
cg.addr_cmd_mode_parity.addr0_x_write_x_debug_x_even: 1
cg.addr_cmd_mode_parity.addr0_x_write_x_debug_x_odd: 0
cg.addr_cmd_mode_parity.addr0_x_write_x_normal_x_even: 0
cg.addr_cmd_mode_parity.addr0_x_write_x_normal_x_odd: 0
cg.addr_cmd_mode_parity.addr1_x_read_x_debug_x_even: 0
cg.addr_cmd_mode_parity.addr1_x_read_x_debug_x_odd: 1
cg.addr_cmd_mode_parity.addr1_x_read_x_normal_x_even: 0
cg.addr_cmd_mode_parity.addr1_x_read_x_normal_x_odd: 0
cg.addr_cmd_mode_parity.addr1_x_write_x_debug_x_even: 0
cg.addr_cmd_mode_parity.addr1_x_write_x_debug_x_odd: 0
cg.addr_cmd_mode_parity.addr1_x_write_x_normal_x_even: 0
cg.addr_cmd_mode_parity.addr1_x_write_x_normal_x_odd: 1
cg.cp_addr.addr0: 2
cg.cp_addr.addr1: 2
cg.cp_cmd.read: 2
cg.cp_cmd.write: 2
cg.cp_mode.debug: 2
cg.cp_mode.normal: 2
cg.cp_parity.even: 2
cg.cp_parity.odd: 2

View File

@ -10,8 +10,13 @@
import vltest_bootstrap
test.scenarios('simulator')
test.compile()
test.scenarios('vlt')
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -4,11 +4,6 @@
// SPDX-FileCopyrightText: 2026 Matthew Ballance
// SPDX-License-Identifier: CC0-1.0
// 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
// Test 4-way cross coverage
module t;
@ -42,31 +37,10 @@ module t;
cg cg_inst = new;
initial begin
// Hit different 4-way cross bins
addr = 0; cmd = 0; mode = 0; parity = 0; cg_inst.sample();
$display("Sample 1: addr=%0d, cmd=%0d, mode=%0d, parity=%0d", addr, cmd, mode, parity);
addr = 1; cmd = 1; mode = 0; parity = 1; cg_inst.sample();
$display("Sample 2: addr=%0d, cmd=%0d, mode=%0d, parity=%0d", addr, cmd, mode, parity);
addr = 0; cmd = 1; mode = 1; parity = 0; cg_inst.sample();
$display("Sample 3: addr=%0d, cmd=%0d, mode=%0d, parity=%0d", addr, cmd, mode, parity);
addr = 1; cmd = 0; mode = 1; parity = 1; cg_inst.sample();
$display("Sample 4: addr=%0d, cmd=%0d, mode=%0d, parity=%0d", addr, cmd, mode, parity);
// Check coverage
// Total bins:
// - 2 bins in cp_addr
// - 2 bins in cp_cmd
// - 2 bins in cp_mode
// - 2 bins in cp_parity
// - 16 bins in 4-way cross (2 x 2 x 2 x 2)
// Total = 24 bins
// Hit: 2+2+2+2+4 = 12 out of 24 = 50%
$display("Coverage: %0.1f%%", cg_inst.get_inst_coverage());
`checkr(cg_inst.get_inst_coverage(), 50.0);
$write("*-* All Finished *-*\n");
$finish;

View File

@ -1,18 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of either the GNU Lesser General Public License Version 3
# or the Perl Artistic License Version 2.0.
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.execute()
test.passes()

View File

@ -1,83 +0,0 @@
// 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 basic cross coverage functionality
module t;
/* verilator lint_off UNSIGNED */
bit [7:0] addr;
bit [7:0] cmd;
covergroup cg;
// Two coverpoints with 2 bins each
a: coverpoint addr {
bins low = {[0:3]};
bins high = {[4:7]};
}
b: coverpoint cmd {
bins read = {0};
bins write = {1};
}
// 2-way cross creates 4 bins: lowread, lowwrite, highread, highwrite
c: cross a, b;
endgroup
initial begin
cg cg_inst;
real cov;
cg_inst = new();
// Initially coverage should be 0%
cov = cg_inst.get_inst_coverage();
if (cov != 0.0) begin
$error("Initial coverage should be 0%%, got %0.2f%%", cov);
end
// Hit lowread
addr = 2; cmd = 0;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
// Should have: a.low(1), b.read(1), c.low_x__read(1) = 3/8 = 37.5%
if (cov < 35.0 || cov > 40.0) begin
$error("After 1 sample, expected ~37.5%%, got %0.2f%%", cov);
end
// Hit highwrite
addr = 5; cmd = 1;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
// Should have: a.low(1), a.high(1), b.read(1), b.write(1),
// c.low_x__read(1), c.high_x__write(1) = 6/8 = 75%
if (cov < 70.0 || cov > 80.0) begin
$error("After 2 samples, expected ~75%%, got %0.2f%%", cov);
end
// Hit lowwrite
addr = 1; cmd = 1;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
// Should have 7/8 = 87.5%
if (cov < 85.0 || cov > 90.0) begin
$error("After 3 samples, expected ~87.5%%, got %0.2f%%", cov);
end
// Hit highread for 100% coverage
addr = 7; cmd = 0;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
// Should have 8/8 = 100%
if (cov != 100.0) begin
$error("After all bins hit, expected 100%%, got %0.2f%%", cov);
end
$display("Cross coverage test PASSED - final coverage: %0.2f%%", cov);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,24 @@
cg.cp_a.a0: 9
cg.cp_a.a1: 4
cg.cp_a.a2: 4
cg.cp_a.a3: 4
cg.cp_b.b0: 21
cg.cp_b.b1: 0
cg.cp_b.b2: 0
cg.cp_b.b3: 0
cg.cross_ab.a0_x_b0: 9
cg.cross_ab.a0_x_b1: 0
cg.cross_ab.a0_x_b2: 0
cg.cross_ab.a0_x_b3: 0
cg.cross_ab.a1_x_b0: 4
cg.cross_ab.a1_x_b1: 0
cg.cross_ab.a1_x_b2: 0
cg.cross_ab.a1_x_b3: 0
cg.cross_ab.a2_x_b0: 4
cg.cross_ab.a2_x_b1: 0
cg.cross_ab.a2_x_b2: 0
cg.cross_ab.a2_x_b3: 0
cg.cross_ab.a3_x_b0: 4
cg.cross_ab.a3_x_b1: 0
cg.cross_ab.a3_x_b2: 0
cg.cross_ab.a3_x_b3: 0

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -48,9 +48,6 @@ module t(/*AUTOARG*/
b <= cyc[7:4];
if (cyc == 20) begin
automatic real inst_cov = cg_inst.get_inst_coverage();
$display("Coverage: %0.1f%%", inst_cov);
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -1,18 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-FileCopyrightText: 2024 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(make_main=False,
verilator_flags2=["--coverage-user", "--exe", "t/t_covergroup_cross_large_main.cpp"])
test.execute(check_finished=True)
test.passes()

View File

@ -0,0 +1,8 @@
cg.addr_cmd.addr0_x_read: 1
cg.addr_cmd.addr0_x_write: 1
cg.addr_cmd.addr1_x_read: 1
cg.addr_cmd.addr1_x_write: 1
cg.cp_addr.addr0: 2
cg.cp_addr.addr1: 2
cg.cp_cmd.read: 2
cg.cp_cmd.write: 2

View File

@ -10,8 +10,13 @@
import vltest_bootstrap
test.scenarios('simulator')
test.compile()
test.scenarios('vlt')
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -4,60 +4,31 @@
// SPDX-FileCopyrightText: 2026 Matthew Ballance
// SPDX-License-Identifier: CC0-1.0
// 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
// Test basic cross coverage with 2-way cross
module t;
logic [1:0] addr;
logic cmd;
logic clk;
// Covergroup with cross coverage
covergroup cg;
cp_addr: coverpoint addr {
bins addr0 = {0};
bins addr1 = {1};
bins addr2 = {2};
bins addr3 = {3};
}
cp_cmd: coverpoint cmd {
bins read = {0};
bins read = {0};
bins write = {1};
}
// Cross coverage: addr x cmd = 4 x 2 = 8 bins
addr_cmd: cross cp_addr, cp_cmd;
endgroup
cg cg_inst = new;
initial begin
// Hit different cross bins
addr = 0; cmd = 0; cg_inst.sample(); // addr0 x read
$display("After sample 1: addr=%0d, cmd=%0d", addr, cmd);
addr = 1; cmd = 1; cg_inst.sample(); // addr1 x write
$display("After sample 2: addr=%0d, cmd=%0d", addr, cmd);
addr = 2; cmd = 0; cg_inst.sample(); // addr2 x read
$display("After sample 3: addr=%0d, cmd=%0d", addr, cmd);
addr = 0; cmd = 1; cg_inst.sample(); // addr0 x write
$display("After sample 4: addr=%0d, cmd=%0d", addr, cmd);
// Check coverage - should be 50% (4 out of 8 bins hit)
// Actually, with cross bins, we have:
// - 4 bins in cp_addr: addr0, addr1, addr2, addr3
// - 2 bins in cp_cmd: read, write
// - 8 bins in cross (4 x 2)
// Hit: addr0, addr1, addr2 (3 bins), read, write (2 bins), 4 cross bins
// Total = 9 out of 14 = 64.3%
$display("Coverage: %0.1f%%", cg_inst.get_inst_coverage());
`checkr(cg_inst.get_inst_coverage(), 900.0/14.0);
addr = 0; cmd = 0; cg_inst.sample(); // addr0 x read
addr = 1; cmd = 1; cg_inst.sample(); // addr1 x write
addr = 0; cmd = 1; cg_inst.sample(); // addr0 x write
addr = 1; cmd = 0; cg_inst.sample(); // addr1 x read
$write("*-* All Finished *-*\n");
$finish;

View File

@ -1,18 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of either the GNU Lesser General Public License Version 3
# or the Perl Artistic License Version 2.0.
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile()
test.execute()
test.passes()

View File

@ -0,0 +1,93 @@
cg.cp_a.a0: 10
cg.cp_a.a1: 5
cg.cp_a.a2: 6
cg.cp_b.b0: 21
cg.cp_b.b1: 0
cg.cp_b.b2: 0
cg.cp_c.c0: 10
cg.cp_c.c1: 5
cg.cp_c.c2: 6
cg.cp_d.d0: 21
cg.cp_d.d1: 0
cg.cp_d.d2: 0
cg.cross_abcd.a0_x_b0_x_c0_x_d0: 10
cg.cross_abcd.a0_x_b0_x_c0_x_d1: 0
cg.cross_abcd.a0_x_b0_x_c0_x_d2: 0
cg.cross_abcd.a0_x_b0_x_c1_x_d0: 0
cg.cross_abcd.a0_x_b0_x_c1_x_d1: 0
cg.cross_abcd.a0_x_b0_x_c1_x_d2: 0
cg.cross_abcd.a0_x_b0_x_c2_x_d0: 0
cg.cross_abcd.a0_x_b0_x_c2_x_d1: 0
cg.cross_abcd.a0_x_b0_x_c2_x_d2: 0
cg.cross_abcd.a0_x_b1_x_c0_x_d0: 0
cg.cross_abcd.a0_x_b1_x_c0_x_d1: 0
cg.cross_abcd.a0_x_b1_x_c0_x_d2: 0
cg.cross_abcd.a0_x_b1_x_c1_x_d0: 0
cg.cross_abcd.a0_x_b1_x_c1_x_d1: 0
cg.cross_abcd.a0_x_b1_x_c1_x_d2: 0
cg.cross_abcd.a0_x_b1_x_c2_x_d0: 0
cg.cross_abcd.a0_x_b1_x_c2_x_d1: 0
cg.cross_abcd.a0_x_b1_x_c2_x_d2: 0
cg.cross_abcd.a0_x_b2_x_c0_x_d0: 0
cg.cross_abcd.a0_x_b2_x_c0_x_d1: 0
cg.cross_abcd.a0_x_b2_x_c0_x_d2: 0
cg.cross_abcd.a0_x_b2_x_c1_x_d0: 0
cg.cross_abcd.a0_x_b2_x_c1_x_d1: 0
cg.cross_abcd.a0_x_b2_x_c1_x_d2: 0
cg.cross_abcd.a0_x_b2_x_c2_x_d0: 0
cg.cross_abcd.a0_x_b2_x_c2_x_d1: 0
cg.cross_abcd.a0_x_b2_x_c2_x_d2: 0
cg.cross_abcd.a1_x_b0_x_c0_x_d0: 0
cg.cross_abcd.a1_x_b0_x_c0_x_d1: 0
cg.cross_abcd.a1_x_b0_x_c0_x_d2: 0
cg.cross_abcd.a1_x_b0_x_c1_x_d0: 5
cg.cross_abcd.a1_x_b0_x_c1_x_d1: 0
cg.cross_abcd.a1_x_b0_x_c1_x_d2: 0
cg.cross_abcd.a1_x_b0_x_c2_x_d0: 0
cg.cross_abcd.a1_x_b0_x_c2_x_d1: 0
cg.cross_abcd.a1_x_b0_x_c2_x_d2: 0
cg.cross_abcd.a1_x_b1_x_c0_x_d0: 0
cg.cross_abcd.a1_x_b1_x_c0_x_d1: 0
cg.cross_abcd.a1_x_b1_x_c0_x_d2: 0
cg.cross_abcd.a1_x_b1_x_c1_x_d0: 0
cg.cross_abcd.a1_x_b1_x_c1_x_d1: 0
cg.cross_abcd.a1_x_b1_x_c1_x_d2: 0
cg.cross_abcd.a1_x_b1_x_c2_x_d0: 0
cg.cross_abcd.a1_x_b1_x_c2_x_d1: 0
cg.cross_abcd.a1_x_b1_x_c2_x_d2: 0
cg.cross_abcd.a1_x_b2_x_c0_x_d0: 0
cg.cross_abcd.a1_x_b2_x_c0_x_d1: 0
cg.cross_abcd.a1_x_b2_x_c0_x_d2: 0
cg.cross_abcd.a1_x_b2_x_c1_x_d0: 0
cg.cross_abcd.a1_x_b2_x_c1_x_d1: 0
cg.cross_abcd.a1_x_b2_x_c1_x_d2: 0
cg.cross_abcd.a1_x_b2_x_c2_x_d0: 0
cg.cross_abcd.a1_x_b2_x_c2_x_d1: 0
cg.cross_abcd.a1_x_b2_x_c2_x_d2: 0
cg.cross_abcd.a2_x_b0_x_c0_x_d0: 0
cg.cross_abcd.a2_x_b0_x_c0_x_d1: 0
cg.cross_abcd.a2_x_b0_x_c0_x_d2: 0
cg.cross_abcd.a2_x_b0_x_c1_x_d0: 0
cg.cross_abcd.a2_x_b0_x_c1_x_d1: 0
cg.cross_abcd.a2_x_b0_x_c1_x_d2: 0
cg.cross_abcd.a2_x_b0_x_c2_x_d0: 6
cg.cross_abcd.a2_x_b0_x_c2_x_d1: 0
cg.cross_abcd.a2_x_b0_x_c2_x_d2: 0
cg.cross_abcd.a2_x_b1_x_c0_x_d0: 0
cg.cross_abcd.a2_x_b1_x_c0_x_d1: 0
cg.cross_abcd.a2_x_b1_x_c0_x_d2: 0
cg.cross_abcd.a2_x_b1_x_c1_x_d0: 0
cg.cross_abcd.a2_x_b1_x_c1_x_d1: 0
cg.cross_abcd.a2_x_b1_x_c1_x_d2: 0
cg.cross_abcd.a2_x_b1_x_c2_x_d0: 0
cg.cross_abcd.a2_x_b1_x_c2_x_d1: 0
cg.cross_abcd.a2_x_b1_x_c2_x_d2: 0
cg.cross_abcd.a2_x_b2_x_c0_x_d0: 0
cg.cross_abcd.a2_x_b2_x_c0_x_d1: 0
cg.cross_abcd.a2_x_b2_x_c0_x_d2: 0
cg.cross_abcd.a2_x_b2_x_c1_x_d0: 0
cg.cross_abcd.a2_x_b2_x_c1_x_d1: 0
cg.cross_abcd.a2_x_b2_x_c1_x_d2: 0
cg.cross_abcd.a2_x_b2_x_c2_x_d0: 0
cg.cross_abcd.a2_x_b2_x_c2_x_d1: 0
cg.cross_abcd.a2_x_b2_x_c2_x_d2: 0

View File

@ -10,9 +10,13 @@
import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=["--coverage-user"])
test.scenarios('vlt')
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -5,11 +5,6 @@
// SPDX-FileCopyrightText: 2024 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// 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
// Test large cross coverage with sparse map implementation
module t(/*AUTOARG*/
@ -70,11 +65,6 @@ module t(/*AUTOARG*/
d <= cyc[7:4];
if (cyc == 20) begin
automatic real inst_cov = cg_inst.get_inst_coverage();
$display("Coverage: %0.1f%%", inst_cov);
`checkr(inst_cov, 1100.0/93.0);
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -0,0 +1,3 @@
cg.data.high: 1
cg.data.low: 1
cg.data.other: 2

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -7,7 +7,6 @@
// Test default bins - catch-all for values not in other bins
module t;
/* verilator lint_off UNSIGNED */
bit [7:0] data;
covergroup cg;
@ -20,46 +19,25 @@ module t;
initial begin
cg cg_inst;
real cov;
cg_inst = new();
// Hit low bin
data = 2;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After low: %0.2f%%", cov);
if (cov < 30.0 || cov > 35.0) begin
$error("Expected ~33.33%% (1/3 bins), got %0.2f%%", cov);
end
// Hit high bin
data = 14;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After high: %0.2f%%", cov);
if (cov < 63.0 || cov > 70.0) begin
$error("Expected ~66.67%% (2/3 bins), got %0.2f%%", cov);
end
// Hit default bin with value 7 (not in low or high)
data = 7;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After default (7): %0.2f%%", cov);
if (cov != 100.0) begin
$error("Expected 100%% (3/3 bins), got %0.2f%%", cov);
end
// Hit another default value (should not increase coverage)
data = 20;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
if (cov != 100.0) begin
$error("Coverage should stay 100%%, got %0.2f%%", cov);
end
$display("Default bins test PASSED");
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -0,0 +1,2 @@
cg.data.high: 1
cg.data.low: 2

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -5,11 +5,6 @@
// SPDX-FileCopyrightText: 2024 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// 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
// Test dynamic covergroup creation with 'new' operator
module t;
@ -25,71 +20,19 @@ module t;
initial begin
cg cg_inst;
real cov;
// Test 1: Create single dynamic instance
$display("Test 1: Single dynamic instance");
// Create first dynamic instance
cg_inst = new;
data = 0; cg_inst.sample(); // low bin
data = 2; cg_inst.sample(); // high bin
// Initially no coverage
cov = cg_inst.get_inst_coverage();
$display(" Initial coverage: %f", cov);
`checkr(cov, 0.0);
// Sample low bin
data = 0;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display(" After sampling low: %f", cov);
`checkr(cov, 50.0); // ~50%
// Sample high bin
data = 2;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display(" After sampling high: %f", cov);
`checkr(cov, 100.0); // ~100%
$display("Test 2: Multiple dynamic instances");
// Create second independent instance
begin
cg cg1, cg2, cg3;
cg1 = new;
cg cg2;
cg2 = new;
cg3 = new;
// Sample different bins in each
data = 0;
cg1.sample();
data = 2;
cg2.sample();
data = 1;
cg3.sample();
// Check individual coverage
cov = cg1.get_inst_coverage();
$display(" cg1 coverage: %f", cov);
`checkr(cov, 50.0); // 50%
cov = cg2.get_inst_coverage();
$display(" cg2 coverage: %f", cov);
`checkr(cov, 50.0); // 50%
cov = cg3.get_inst_coverage();
$display(" cg3 coverage: %f", cov);
`checkr(cov, 50.0); // 50%
data = 0; cg2.sample(); // low bin
end
// Test 3: Reassignment (old instance should be cleaned up)
$display("Test 3: Instance reassignment");
cg_inst = new; // Create new, old should be freed
// New instance starts with 0% coverage
cov = cg_inst.get_inst_coverage();
$display(" New instance coverage: %f", cov);
`checkr(cov, 0.0);
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -0,0 +1,2 @@
Empty covergroup coverage: 100.000000%
*-* All Finished *-*

View File

@ -10,6 +10,6 @@ test.scenarios('vlt')
test.compile()
test.execute()
test.execute(expect_filename=test.golden_filename)
test.passes()

View File

@ -30,21 +30,11 @@ module t (/*AUTOARG*/
cg_inst.sample();
if (cyc == 5) begin
// Get coverage - should be 100% (nothing to fail)
begin
real cov;
cov = cg_inst.get_inst_coverage();
$display("Empty covergroup coverage: %f%%", cov);
// Empty covergroup should report 100% coverage
if (cov >= 99.9) begin
$write("*-* All Finished *-*\n");
$finish;
end else begin
$display("ERROR: Expected 100%% coverage for empty covergroup, got %f%%", cov);
$stop;
end
end
real cov;
cov = cg_inst.get_inst_coverage();
$display("Empty covergroup coverage: %f%%", cov);
$write("*-* All Finished *-*\n");
$finish;
end
if (cyc > 10) begin

View File

@ -1,40 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Covergroup inheritance with 'extends' is not yet supported
//
// This file ONLY is placed under the Creative Commons Public Domain
// SPDX-FileCopyrightText: 2025 Antmicro
// SPDX-License-Identifier: CC0-1.0
module t;
class base;
function new();
g1 = new(0);
endfunction
enum {red, green, blue} color;
covergroup g1 (bit [3:0] a) with function sample(bit b);
option.weight = 10;
option.per_instance = 1;
coverpoint a;
coverpoint b;
c: coverpoint color;
endgroup
endclass
class derived extends base;
bit d;
function new();
super.new();
endfunction
covergroup extends g1;
option.weight = 1; // overrides the weight from base g1
// uses per_instance = 1 from base g1
c: coverpoint color // overrides the c coverpoint in base g1
{
ignore_bins ignore = {blue};
}
coverpoint d; // adds new coverpoint
cross a, d; // crosses new coverpoint with inherited one
endgroup :g1
endclass
endmodule

View File

@ -1,4 +1,4 @@
%Error-UNSUPPORTED: t/t_covergroup_extends.v:26:5: Unsupported: covergroup inheritance (extends) is not implemented
%Error-UNSUPPORTED: t/t_covergroup_extends_unsup.v:26:5: Unsupported: covergroup inheritance (extends) is not implemented
26 | covergroup extends g1;
| ^~~~~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest

View File

@ -1,16 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of either the GNU Lesser General Public License Version 3
# or the Perl Artistic License Version 2.0.
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.passes()

View File

@ -1,24 +0,0 @@
// 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
module t (input clk);
int value = 0;
covergroup cg;
cp: coverpoint value {
bins low = {[0:5]};
}
endgroup
cg my_cg = new;
always @(posedge clk) begin
real cov;
cov = my_cg.get_inst_coverage();
my_cg.sample();
end
endmodule

View File

@ -0,0 +1,4 @@
cg_iff.cp_value.disabled_hi: 0
cg_iff.cp_value.disabled_lo: 0
cg_iff.cp_value.enabled_hi: 1
cg_iff.cp_value.enabled_lo: 1

View File

@ -11,6 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -5,20 +5,39 @@
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
module t (input clk);
logic enable = 0;
int value = 0;
// Test iff (enable) guard: sampling is gated by the enable condition.
// Samples taken while enable=0 must not increment bins.
// Bins 'disabled_*' are sampled only with enable=0 — they must NOT appear in
// coverage.dat. Bins 'enabled_*' are sampled only with enable=1 — they must
// appear. This makes pass/fail unambiguous from the coverage report alone.
module t;
logic enable;
int value;
covergroup cg_iff;
cp_value: coverpoint value iff (enable) {
bins low = {[0:5]};
bins mid = {[6:10]};
bins disabled_lo = {1};
bins disabled_hi = {2};
bins enabled_lo = {3};
bins enabled_hi = {4};
}
endgroup
cg_iff cg = new;
always @(posedge clk) begin
cg.sample();
initial begin
// Sample disabled_lo and disabled_hi with enable=0 — must not be recorded
enable = 0;
value = 1; cg.sample();
value = 2; cg.sample();
// Sample enabled_lo and enabled_hi with enable=1 — must be recorded
enable = 1;
value = 3; cg.sample();
value = 4; cg.sample();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,3 @@
cg.data.high: 1
cg.data.low: 1
cg.data.reserved [ignore]: 1

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -6,21 +6,14 @@
// Test ignore_bins - excluded from coverage
// 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 (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [3:0] data;
covergroup cg;
coverpoint data {
bins low = {[0:3]};
bins mid = {[4:7]};
bins high = {[8:11]};
ignore_bins reserved = {[12:15]}; // Should not count toward coverage
ignore_bins reserved = {[12:15]};
}
endgroup
@ -29,28 +22,9 @@ module t (/*AUTOARG*/);
initial begin
cg_inst = new;
// Initially 0% (0 of 3 regular bins)
`checkr(cg_inst.get_inst_coverage(), 0.0);
// Hit reserved bin - should still be 0%
data = 13;
cg_inst.sample();
`checkr(cg_inst.get_inst_coverage(), 0.0);
// Hit low bin - now 33.33% (1 of 3)
data = 1;
cg_inst.sample();
`checkr(cg_inst.get_inst_coverage(), 100.0 * (1.0/3.0));
// Hit another reserved value - still 33.33%
data = 15;
cg_inst.sample();
`checkr(cg_inst.get_inst_coverage(), 100.0 * (1.0/3.0));
// Complete regular bins
data = 5; cg_inst.sample(); // mid
data = 10; cg_inst.sample(); // high
`checkr(cg_inst.get_inst_coverage(), 100.0);
data = 13; cg_inst.sample(); // reserved - ignored
data = 1; cg_inst.sample(); // low
data = 10; cg_inst.sample(); // high
$write("*-* All Finished *-*\n");
$finish;

View File

@ -0,0 +1,4 @@
cg.data.forbidden [illegal]: 0
cg.data.high: 1
cg.data.low: 1
cg.data.mid: 1

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -8,7 +8,6 @@
// SPDX-License-Identifier: CC0-1.0
module t;
/* verilator lint_off UNSIGNED */
logic [1:0] data;
covergroup cg;
@ -26,15 +25,12 @@ module t;
// Sample legal values only
data = 0;
cg_inst.sample();
$display("Coverage after low: %f%% (expected ~33.33%%)", cg_inst.get_inst_coverage());
data = 1;
cg_inst.sample();
$display("Coverage after mid: %f%% (expected ~66.67%%)", cg_inst.get_inst_coverage());
data = 2;
cg_inst.sample();
$display("Coverage complete: %f%% (expected ~100.00%%)", cg_inst.get_inst_coverage());
$write("*-* All Finished *-*\n");
$finish;

View File

@ -1,19 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain
// SPDX-FileCopyrightText: 2025 Antmicro
// SPDX-License-Identifier: CC0-1.0
/* verilator lint_off COVERIGN */
class myClass;
covergroup embeddedCg;
endgroup
function new();
real r;
embeddedCg = new();
embeddedCg.sample();
r = embeddedCg.get_coverage();
endfunction
endclass

View File

@ -1,16 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of either the GNU Lesser General Public License Version 3
# or the Perl Artistic License Version 2.0.
# SPDX-FileCopyrightText: 2025 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.passes()

View File

@ -11,6 +11,6 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.passes()

View File

@ -4,17 +4,15 @@
// SPDX-FileCopyrightText: 2025 Antmicro
// SPDX-License-Identifier: CC0-1.0
/* verilator lint_off COVERIGN */
class myClass;
covergroup embeddedCg;
endgroup
function new();
real r;
embeddedCg = new();
embeddedCg.sample();
r = embeddedCg.get_coverage();
void'(embeddedCg.get_coverage());
endfunction
endclass
@ -24,9 +22,8 @@ class secondClass;
endgroup
function new();
real r;
embeddedCg = new();
embeddedCg.sample();
r = embeddedCg.get_coverage();
void'(embeddedCg.get_coverage());
endfunction
endclass

View File

@ -1,16 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of either the GNU Lesser General Public License Version 3
# or the Perl Artistic License Version 2.0.
# SPDX-FileCopyrightText: 2025 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.passes()

View File

@ -1,15 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain
// SPDX-FileCopyrightText: 2025 Antmicro
// SPDX-License-Identifier: CC0-1.0
/* verilator lint_off COVERIGN */
class C;
covergroup embedded(int x) with function sample (int a, bit b);
endgroup
function new();
embedded = new(1);
embedded.sample(2, 1'b0);
endfunction
endclass

View File

@ -1,11 +0,0 @@
%Error: t/t_covergroup_method_bad.v:16:10: Member 'some_unknown_method' not found in covergroup 'cg'
: ... note: In instance 't'
16 | cov1.some_unknown_method.name = "new_cov1_name";
| ^~~~~~~~~~~~~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error-UNSUPPORTED: t/t_covergroup_method_bad.v:16:30: Unsupported: Member call on object 'CONST '1'h0'' which is a 'BASICDTYPE 'bit''
: ... note: In instance 't'
16 | cov1.some_unknown_method.name = "new_cov1_name";
| ^~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

View File

@ -1,20 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2023 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
module t;
// verilator lint_off COVERIGN
covergroup cg();
endgroup
cg cov1;
initial begin
cov1 = new;
cov1.some_unknown_method.name = "new_cov1_name"; // <-- BAD
$finish;
end
endmodule

View File

@ -1,2 +0,0 @@
Coverage: 0.0%
*-* All Finished *-*

View File

@ -1,18 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of either the GNU Lesser General Public License Version 3
# or the Perl Artistic License Version 2.0.
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.execute(expect_filename=test.golden_filename)
test.passes()

View File

@ -1,34 +0,0 @@
// 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
// Minimal test for covergroup parsing and code generation
module t;
int unsigned addr; // Use unsigned to avoid comparison warnings
covergroup cg;
cp_addr: coverpoint addr {
bins low = {[0:127]};
bins high = {[128:255]};
}
endgroup
initial begin
cg cg_inst;
cg_inst = new;
// Sample some values
addr = 10;
cg_inst.sample();
addr = 200;
cg_inst.sample();
$display("Coverage: %0.1f%%", cg_inst.get_coverage());
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,5 @@
cg.opcode.arith: 1
cg.opcode.load: 1
cg.opcode.nop: 1
cg.opcode.others: 1
cg.opcode.store: 1

View File

@ -11,8 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -6,13 +6,7 @@
// Test mixed bin types: single values and ranges
// 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 (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [7:0] opcode;
covergroup cg;
@ -32,21 +26,16 @@ module t (/*AUTOARG*/);
// Test single value bins
opcode = 8'h00; cg_inst.sample(); // nop
`checkr(cg_inst.get_inst_coverage(), 20.0);
// Test multi-value list bin
opcode = 8'h02; cg_inst.sample(); // load
`checkr(cg_inst.get_inst_coverage(), 40.0);
opcode = 8'h05; cg_inst.sample(); // store
`checkr(cg_inst.get_inst_coverage(), 60.0);
// Test range bin
opcode = 8'h15; cg_inst.sample(); // arith
`checkr(cg_inst.get_inst_coverage(), 80.0);
opcode = 8'h80; cg_inst.sample(); // others
`checkr(cg_inst.get_inst_coverage(), 100.0);
$write("*-* All Finished *-*\n");
$finish;

View File

@ -1,56 +0,0 @@
// 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 multiple covergroup instances with separate tracking
// 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 (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [3:0] data1, data2;
covergroup cg;
coverpoint data1 {
bins low = {[0:3]};
bins high = {[4:15]};
}
endgroup
cg cg_inst1, cg_inst2;
initial begin
cg_inst1 = new;
cg_inst2 = new;
// Initially both have 0% coverage
`checkr(cg_inst1.get_inst_coverage(), 0.0);
`checkr(cg_inst2.get_inst_coverage(), 0.0);
// Sample different values in each instance
data1 = 1;
cg_inst1.sample(); // inst1: low covered (50%)
`checkr(cg_inst1.get_inst_coverage(), 50.0);
`checkr(cg_inst2.get_inst_coverage(), 0.0);
data1 = 10;
cg_inst2.sample(); // inst2: high covered (50%)
`checkr(cg_inst1.get_inst_coverage(), 50.0);
`checkr(cg_inst2.get_inst_coverage(), 50.0);
// Complete coverage in inst1
data1 = 8;
cg_inst1.sample(); // inst1: both covered (100%)
`checkr(cg_inst1.get_inst_coverage(), 100.0);
`checkr(cg_inst2.get_inst_coverage(), 50.0);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -1,15 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.execute()
test.passes()

View File

@ -1,80 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module - Edge case: multiple instances
// This file ONLY is placed into the Public Domain, for any use, without warranty.
// SPDX-FileCopyrightText: 2025 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// Test: Multiple instances of same covergroup type sampling the same coverpoint
// Expected: Each instance tracks coverage independently, achieving same coverage
// since they all sample the same expression (value1)
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
logic [2:0] value1;
covergroup cg;
cp: coverpoint value1 {
bins low = {[0:3]};
bins high = {[4:7]};
}
endgroup
// Create three independent instances
cg cg_inst1 = new;
cg cg_inst2 = new;
cg cg_inst3 = new;
int cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
case (cyc)
0: begin
value1 <= 1; // low bin for all instances
end
1: begin
value1 <= 6; // high bin for all instances -> 100%
end
2: begin
begin
real cov1, cov2, cov3;
cov1 = cg_inst1.get_inst_coverage();
cov2 = cg_inst2.get_inst_coverage();
cov3 = cg_inst3.get_inst_coverage();
$display("Instance 1 coverage: %f%%", cov1);
$display("Instance 2 coverage: %f%%", cov2);
$display("Instance 3 coverage: %f%%", cov3);
// All instances sample the same coverpoint (value1), so they should all be 100%
// This tests that multiple instances track coverage independently,
// even when sampling the same expression
if (cov1 >= 99.0 && cov2 >= 99.0 && cov3 >= 99.0) begin
$write("*-* All Finished *-*\n");
$finish;
end else begin
$display("ERROR: Coverage mismatch");
$display(" Expected: inst1=100%%, inst2=100%%, inst3=100%%");
$display(" Got: inst1=%f%%, inst2=%f%%, inst3=%f%%", cov1, cov2, cov3);
$stop;
end
end
end
endcase
// Each instance samples the same value (value1)
// But tracks coverage independently
cg_inst1.sample();
cg_inst2.sample();
cg_inst3.sample();
if (cyc > 10) begin
$display("ERROR: Test timed out");
$stop;
end
end
endmodule

View File

@ -0,0 +1,4 @@
cg.cp_neg.mixed: 4
cg.cp_neg.negative: 2
cg.cp_neg.positive: 3
cg.cp_neg.zero: 1

View File

@ -8,8 +8,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.compile(verilator_flags2=['--coverage'])
test.execute()
test.covergroup_coverage_report()
test.files_identical(test.obj_dir + '/covergroup_report.txt', test.golden_filename)
test.passes()

View File

@ -39,20 +39,8 @@ module t (/*AUTOARG*/
3: value <= -5; // Hit mixed bin (also negative)
4: value <= 5; // Hit mixed bin (also positive)
5: begin
begin
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage with negative ranges: %f%%", cov);
// All 4 bins should be hit = 100%
if (cov >= 99.0) begin
$write("*-* All Finished *-*\n");
$finish;
end else begin
$display("ERROR: Expected 100%% coverage, got %f%%", cov);
$stop;
end
end
$write("*-* All Finished *-*\n");
$finish;
end
endcase

View File

@ -13,6 +13,4 @@ test.scenarios('simulator')
test.compile()
test.execute()
test.passes()

Some files were not shown because too many files have changed in this diff Show More