Correct indent on coverage tests ; add required test drivers ; back out CMakeLists pch change and adjust test that required it to no longer need it

Signed-off-by: Matthew Ballance <matt.ballance@gmail.com>
This commit is contained in:
Matthew Ballance 2026-03-04 15:25:41 +00:00
parent e347943e3b
commit 80502fd9ee
57 changed files with 1892 additions and 2050 deletions

View File

@ -121,23 +121,6 @@ set(PACKAGE_VERSION ${PROJECT_VERSION})
set(CXX ${CMAKE_CXX_COMPILER})
set(AR ${CMAKE_AR})
# Detect precompiled header include flag (matches configure.ac logic)
execute_process(
COMMAND ${CMAKE_CXX_COMPILER} --help
OUTPUT_VARIABLE _cxx_help
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(_cxx_help MATCHES "include-pch")
# clang
set(CFG_CXXFLAGS_PCH_I "-include-pch")
set(CFG_GCH_IF_CLANG ".gch")
else()
# GCC
set(CFG_CXXFLAGS_PCH_I "-include")
set(CFG_GCH_IF_CLANG "")
endif()
configure_file(include/verilated_config.h.in include/verilated_config.h @ONLY)
configure_file(include/verilated.mk.in include/verilated.mk @ONLY)

View File

@ -0,0 +1,18 @@
#!/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

@ -7,81 +7,81 @@
// Test array bins - separate bin per value
module t;
/* verilator lint_off UNSIGNED */
bit [7:0] data;
/* verilator lint_off UNSIGNED */
bit [7:0] data;
covergroup cg;
coverpoint data {
// Array bins: creates 3 separate bins
bins values[] = {1, 5, 9};
covergroup cg;
coverpoint data {
// Array bins: creates 3 separate bins
bins values[] = {1, 5, 9};
// Non-array bin: creates 1 bin covering all values
bins grouped = {2, 6, 10};
}
endgroup
// Non-array bin: creates 1 bin covering all values
bins grouped = {2, 6, 10};
}
endgroup
initial begin
cg cg_inst;
real cov;
initial begin
cg cg_inst;
real cov;
cg_inst = new();
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;
// 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
endmodule

View File

@ -5,44 +5,44 @@
// SPDX-License-Identifier: CC0-1.0
module t;
/* verilator lint_off UNSIGNED */
/* verilator lint_off CMPCONST */
logic [2:0] data; // 3-bit: 0-7
/* verilator lint_off UNSIGNED */
/* verilator lint_off CMPCONST */
logic [2:0] data; // 3-bit: 0-7
covergroup cg;
coverpoint data {
bins auto[4]; // Should create 4 bins: [0:1], [2:3], [4:5], [6:7]
}
endgroup
/* verilator lint_on CMPCONST */
covergroup cg;
coverpoint data {
bins auto[4]; // Should create 4 bins: [0:1], [2:3], [4:5], [6:7]
}
endgroup
/* verilator lint_on CMPCONST */
initial begin
automatic cg cg_inst = new;
initial begin
automatic cg cg_inst = new;
// Initial coverage should be 0%
$display("Coverage initial: %f%% (expected ~0.00%%)", cg_inst.get_inst_coverage());
// 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 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 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 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());
// 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;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -3,53 +3,53 @@
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
logic [1:0] data;
logic [1:0] data;
// Covergroup with automatic sampling on posedge clk
covergroup cg @(posedge clk);
cp_data: coverpoint data {
bins zero = {2'b00};
bins one = {2'b01};
bins two = {2'b10};
bins three = {2'b11};
}
endgroup
// Covergroup with automatic sampling on posedge clk
covergroup cg @(posedge clk);
cp_data: coverpoint data {
bins zero = {2'b00};
bins one = {2'b01};
bins two = {2'b10};
bins three = {2'b11};
}
endgroup
cg cg_inst = new;
cg cg_inst = new;
int cyc = 0;
int cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
always @(posedge clk) begin
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
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
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
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
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
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

@ -7,116 +7,116 @@
// Test automatic bin creation when coverpoint has no explicit bins
module t(/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
logic [2:0] data3; // 3-bit: values 0-7
logic [1:0] data2; // 2-bit: values 0-3
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 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 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 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 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
// 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;
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;
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 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 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 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 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();
// 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());
$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
if (cg1_inst.get_inst_coverage() < 30.0 || cg1_inst.get_inst_coverage() > 45.0) begin
$display("FAIL: CG1 coverage out of range");
$stop;
end
if (cg2_inst.get_inst_coverage() < 45.0 || cg2_inst.get_inst_coverage() > 55.0) begin
$display("FAIL: CG2 coverage should be 50%% (2/4 bins with auto_bin_max=4)");
$stop;
end
if (cg3_inst.get_inst_coverage() < 27.0 || cg3_inst.get_inst_coverage() > 30.0) begin
$display("FAIL: CG3 coverage should be ~28.6%% (2/7 valid bins, value 7 ignored)");
$stop;
end
if (cg4_inst.get_inst_coverage() < 95.0) begin
$display("FAIL: CG4 coverage should be 100%%");
$stop;
end
if (cg5_inst.get_inst_coverage() < 99.0) begin
$display("FAIL: CG5 coverage should be 100%% (2/2 bins with auto_bin_max=2)");
$stop;
end
// Validate coverage results
if (cg1_inst.get_inst_coverage() < 30.0 || cg1_inst.get_inst_coverage() > 45.0) begin
$display("FAIL: CG1 coverage out of range");
$stop;
end
if (cg2_inst.get_inst_coverage() < 45.0 || cg2_inst.get_inst_coverage() > 55.0) begin
$display("FAIL: CG2 coverage should be 50%% (2/4 bins with auto_bin_max=4)");
$stop;
end
if (cg3_inst.get_inst_coverage() < 27.0 || cg3_inst.get_inst_coverage() > 30.0) begin
$display("FAIL: CG3 coverage should be ~28.6%% (2/7 valid bins, value 7 ignored)");
$stop;
end
if (cg4_inst.get_inst_coverage() < 95.0) begin
$display("FAIL: CG4 coverage should be 100%%");
$stop;
end
if (cg5_inst.get_inst_coverage() < 99.0) begin
$display("FAIL: CG5 coverage should be 100%% (2/2 bins with auto_bin_max=2)");
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -1,14 +1,14 @@
%Error: t/t_covergroup_autobins_bad.v:17:18: Automatic bins array size must be a constant
%Error: t/t_covergroup_autobins_bad.v:17:12: Automatic bins array size must be a constant
: ... note: In instance 't'
17 | bins auto[size_var];
| ^~~~
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:18: 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-10000, got 0
: ... note: In instance 't'
24 | bins auto[0];
| ^~~~
%Error: t/t_covergroup_autobins_bad.v:31:18: Automatic bins array size must be 1-10000, got 10001
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];
| ^~~~
31 | bins auto[10001];
| ^~~~
%Error: Exiting due to

View File

@ -8,33 +8,33 @@
// Tests for automatic bins error conditions
module t;
int size_var;
logic [3:0] cp_expr;
int size_var;
logic [3:0] cp_expr;
// Error: array size must be a constant
covergroup cg1;
cp1: coverpoint cp_expr {
bins auto[size_var];
}
endgroup
// Error: array size must be a constant
covergroup cg1;
cp1: coverpoint cp_expr {
bins auto[size_var];
}
endgroup
// Error: array size must be 1-10000 (zero)
covergroup cg2;
cp1: coverpoint cp_expr {
bins auto[0];
}
endgroup
// Error: array size must be 1-10000 (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
// 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;
cg1 cg1_inst = new;
cg2 cg2_inst = new;
cg3 cg3_inst = new;
initial $finish;
initial $finish;
endmodule

View File

@ -7,45 +7,45 @@
// Test viewing individual bin hit counts
module t (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [3:0] data;
/* 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]};
}
endgroup
covergroup cg;
coverpoint data {
bins zero = {0};
bins low = {[1:3]};
bins mid = {[4:7]};
bins high = {[8:15]};
}
endgroup
cg cg_inst;
cg cg_inst;
initial begin
cg_inst = new;
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
// 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)
check_coverage(100.0, "final");
// Verify coverage is 100% (all 4 bins hit)
check_coverage(100.0, "final");
$write("*-* All Finished *-*\n");
$finish;
$write("*-* All Finished *-*\n");
$finish;
end
task check_coverage(real expected, string label);
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
if (cov < expected - 0.5 || cov > expected + 0.5) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
task check_coverage(real expected, string label);
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
if (cov < expected - 0.5 || cov > expected + 0.5) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
endtask
endtask
endmodule

View File

@ -1,73 +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 bin options: at_least, weight, goal
module t;
/* verilator lint_off UNSIGNED */
bit [7:0] addr;
covergroup cg;
option.per_instance = 1;
option.comment = "Test covergroup with options";
coverpoint addr {
option.at_least = 2; // Each bin needs at least 2 hits
option.weight = 10; // This coverpoint has weight 10
bins low = {[0:3]};
bins mid = {[4:7]};
bins high = {[8:15]};
}
endgroup
initial begin
cg cg_inst;
real cov;
cg_inst = new();
// Hit low once - should be 0% because at_least = 2
addr = 2;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After 1 hit: %0.2f%%", cov);
if (cov != 0.0) begin
$error("Expected 0%% (bin needs 2 hits), got %0.2f%%", cov);
end
// Hit low again - should be 33.33% (1/3 bins)
addr = 1;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After 2 hits to low: %0.2f%%", cov);
if (cov < 30.0 || cov > 35.0) begin
$error("Expected ~33.33%%, got %0.2f%%", cov);
end
// Hit mid twice - should be 66.67% (2/3 bins)
addr = 5; cg_inst.sample();
addr = 6; cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After mid hits: %0.2f%%", cov);
if (cov < 63.0 || cov > 70.0) begin
$error("Expected ~66.67%%, got %0.2f%%", cov);
end
// Hit high twice - should be 100%
addr = 10; cg_inst.sample();
addr = 12; cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After all bins hit: %0.2f%%", cov);
if (cov != 100.0) begin
$error("Expected 100%%, got %0.2f%%", cov);
end
$display("Bin options test PASSED");
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -1,110 +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-License-Identifier: CC0-1.0
// Test advanced bin types that ARE supported:
// - ignore_bins
// - wildcard bins
// - array bins (explicit values only, not ranges yet)
module t;
logic [3:0] data;
int error_count = 0;
// Test 1: ignore_bins
covergroup cg_ignore;
coverpoint data {
bins low = {[0:3]};
bins mid = {[4:7]};
bins high = {[8:11]};
ignore_bins reserved = {[12:15]}; // Should not count toward coverage
}
endgroup
// Test 2: Array bins (with ranges - now working!)
covergroup cg_array;
coverpoint data {
bins values[] = {[0:3]}; // Creates 4 bins: values[0], values[1], values[2], values[3]
}
endgroup
// Test 3: wildcard bins (with don't-care bits)
covergroup cg_wildcard;
coverpoint data {
wildcard bins pattern0 = {4'b00??}; // Matches 0,1,2,3
wildcard bins pattern1 = {4'b01??}; // Matches 4,5,6,7
wildcard bins pattern2 = {4'b10??}; // Matches 8,9,10,11
wildcard bins pattern3 = {4'b11??}; // Matches 12,13,14,15
}
endgroup
initial begin
cg_ignore cg1;
cg_array cg2;
cg_wildcard cg3;
real cov;
cg1 = new;
cg2 = new;
cg3 = new;
// Test 1: ignore_bins
$display("Test 1: ignore_bins");
data = 0; cg1.sample(); // low
data = 5; cg1.sample(); // mid
data = 9; cg1.sample(); // high
data = 12; cg1.sample(); // ignored - should not affect coverage
data = 13; cg1.sample(); // ignored
cov = cg1.get_inst_coverage();
$display(" Coverage with ignore_bins: %0.1f%% (expect 100%%)", cov);
// 3 out of 3 non-ignored bins = 100%
if (cov < 99.0 || cov > 101.0) begin
$display("%%Error: Expected 100%%, got %0.1f%%", cov);
error_count++;
end
// Test 2: Array bins
$display("Test 2: Array bins (with ranges)");
data = 0; cg2.sample(); // values[0]
data = 1; cg2.sample(); // values[1]
data = 2; cg2.sample(); // values[2]
// Note: values[3] not sampled, so 75% coverage expected
cov = cg2.get_inst_coverage();
$display(" Coverage with array bins: %0.1f%% (expect 75%%)", cov);
// 3 out of 4 bins = 75%
if (cov < 74.0 || cov > 76.0) begin
$display("%%Error: Expected 75%%, got %0.1f%%", cov);
error_count++;
end
// Test 3: Wildcard bins
$display("Test 3: Wildcard bins");
data = 2; cg3.sample(); // pattern0 (00??)
data = 5; cg3.sample(); // pattern1 (01??)
data = 10; cg3.sample(); // pattern2 (10??)
// pattern3 not sampled, so 75% coverage
cov = cg3.get_inst_coverage();
$display(" Coverage with wildcard bins: %0.1f%% (expect 75%%)", cov);
// 3 out of 4 bins = 75%
if (cov < 74.0 || cov > 76.0) begin
$display("%%Error: Expected 75%%, got %0.1f%%", cov);
error_count++;
end
if (error_count == 0) begin
$write("*-* All Finished *-*\n");
end else begin
$display("%%Error: %0d test(s) failed", error_count);
$stop;
end
$finish;
end
endmodule

View File

@ -1,80 +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-License-Identifier: CC0-1.0
// Test default bins and illegal_bins
module t;
logic [3:0] data;
int error_count = 0;
// Test 1: default bins
covergroup cg_default;
coverpoint data {
bins special = {0, 5, 10};
bins others = default; // Catch-all for uncovered values
}
endgroup
// Test 2: illegal_bins (we'll test it doesn't crash on valid values)
covergroup cg_valid;
coverpoint data {
bins valid = {[0:10]};
illegal_bins reserved = {[11:15]};
}
endgroup
initial begin
cg_default cg1;
cg_valid cg2;
real cov;
cg1 = new;
cg2 = new;
// Test 1: default bins
$display("Test 1: default bins");
data = 0; cg1.sample(); // special bin
data = 1; cg1.sample(); // default/others bin
data = 5; cg1.sample(); // special bin
data = 7; cg1.sample(); // default/others bin
data = 10; cg1.sample(); // special bin
cov = cg1.get_inst_coverage();
$display(" Coverage with default bins: %0.1f%%", cov);
// Both bins hit: special (3 values: 0,5,10) and default (2 values: 1,7)
// Expected: 2/2 = 100%
if (cov < 99.0 || cov > 101.0) begin
$display("%%Error: Expected 100%%, got %0.1f%%", cov);
error_count++;
end
// Test 2: illegal_bins (test with valid values only)
$display("Test 2: illegal_bins (sampling valid values)");
data = 0; cg2.sample(); // valid
data = 5; cg2.sample(); // valid
data = 10; cg2.sample(); // valid
cov = cg2.get_inst_coverage();
$display(" Coverage with illegal_bins: %0.1f%%", cov);
// Only the valid bin counts, illegal bins don't count toward coverage
// 1 bin out of 1 = 100%
if (cov < 99.0 || cov > 101.0) begin
$display("%%Error: Expected 100%%, got %0.1f%%", cov);
error_count++;
end
if (error_count == 0) begin
$write("*-* All Finished *-*\n");
end else begin
$display("%%Error: %0d test(s) failed", error_count);
$stop;
end
$finish;
end
endmodule

View File

@ -14,63 +14,63 @@
// Solution: Call .sample() explicitly in an always block.
module t;
logic clk = 0;
always #5 clk = ~clk;
logic clk = 0;
always #5 clk = ~clk;
logic [1:0] data;
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 */
/* 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;
cg cg_inst = new;
// Explicit sampling workaround for internal clocks
always @(posedge clk) begin
cg_inst.sample();
end
// Explicit sampling workaround for internal clocks
always @(posedge clk) begin
cg_inst.sample();
end
initial begin
// Cycle 0
data = 2'b00;
@(posedge clk);
initial begin
// Cycle 0
data = 2'b00;
@(posedge clk);
// Cycle 1
data = 2'b01;
@(posedge clk);
// Cycle 1
data = 2'b01;
@(posedge clk);
// Cycle 2
data = 2'b10;
@(posedge clk);
// Cycle 2
data = 2'b10;
@(posedge clk);
// Cycle 3
data = 2'b11;
@(posedge clk);
// Cycle 3
data = 2'b11;
@(posedge clk);
// Check coverage
#1; // Small delay to ensure last sample completes
// Check coverage
#1; // Small delay to ensure last sample completes
begin
automatic real cov = cg_inst.get_inst_coverage();
$display("Coverage: %0.1f%%", cov);
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
// 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
end
endmodule

View File

@ -8,54 +8,54 @@
// Status: WORKS - Verilator correctly auto-samples when clk is a module port
module t(/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
logic [1:0] data;
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 */
/* 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;
cg cg_inst = new;
int cyc = 0;
int cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
always @(posedge clk) begin
cyc <= cyc + 1;
// Change data each cycle
data <= cyc[1:0];
// Change data each cycle
data <= cyc[1:0];
if (cyc == 5) begin
/* verilator lint_off IMPLICITSTATIC */
real cov = cg_inst.get_inst_coverage();
/* verilator lint_on IMPLICITSTATIC */
$display("Coverage: %0.1f%%", cov);
if (cyc == 5) begin
/* verilator lint_off IMPLICITSTATIC */
real cov = cg_inst.get_inst_coverage();
/* verilator lint_on IMPLICITSTATIC */
$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
// 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
if (cyc > 10) begin
$display("ERROR: Test timeout");
$stop;
end
end
endmodule

View File

@ -5,78 +5,78 @@
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
logic [1:0] data;
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
// 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;
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);
if (cov != 0.0) $stop;
initial begin
// Initially no bins covered - should be 0%
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage after 0 samples: %f", cov);
if (cov != 0.0) $stop;
// 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);
if (cov < 24.9 || cov > 25.1) begin
$display("%%Error: Expected 25%%, got %f", cov);
$stop;
end
// 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);
if (cov < 24.9 || cov > 25.1) begin
$display("%%Error: Expected 25%%, got %f", cov);
$stop;
end
// 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);
if (cov < 49.9 || cov > 50.1) begin
$display("%%Error: Expected 50%%, got %f", cov);
$stop;
end
// 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);
if (cov < 49.9 || cov > 50.1) begin
$display("%%Error: Expected 50%%, got %f", cov);
$stop;
end
// 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);
if (cov < 74.9 || cov > 75.1) begin
$display("%%Error: Expected 75%%, got %f", cov);
$stop;
end
// 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);
if (cov < 74.9 || cov > 75.1) begin
$display("%%Error: Expected 75%%, got %f", cov);
$stop;
end
// 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);
if (cov < 99.9 || cov > 100.1) begin
$display("%%Error: Expected 100%%, got %f", cov);
$stop;
end
// 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);
if (cov < 99.9 || cov > 100.1) begin
$display("%%Error: Expected 100%%, got %f", cov);
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -7,57 +7,57 @@
// Test querying coverage values via get_inst_coverage
module t (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [3:0] data;
/* verilator lint_off UNSIGNED */
logic [3:0] data;
covergroup cg;
coverpoint data {
bins low = {[0:3]};
bins mid = {[4:7]};
bins high = {[8:15]};
}
endgroup
covergroup cg;
coverpoint data {
bins low = {[0:3]};
bins mid = {[4:7]};
bins high = {[8:15]};
}
endgroup
cg cg_inst;
cg cg_inst;
initial begin
cg_inst = new;
initial begin
cg_inst = new;
// Initially no coverage
check_coverage(0.0, "initial");
// Initially no coverage
check_coverage(0.0, "initial");
// Sample low bin - should be 33.33% (1 of 3 bins)
data = 1;
cg_inst.sample();
check_coverage(33.33, "after low");
// Sample low bin - should be 33.33% (1 of 3 bins)
data = 1;
cg_inst.sample();
check_coverage(33.33, "after low");
// Sample mid bin - should be 66.67% (2 of 3 bins)
data = 5;
cg_inst.sample();
check_coverage(66.67, "after mid");
// Sample mid bin - should be 66.67% (2 of 3 bins)
data = 5;
cg_inst.sample();
check_coverage(66.67, "after mid");
// Sample high bin - should be 100% (3 of 3 bins)
data = 10;
cg_inst.sample();
check_coverage(100.0, "after high");
// Sample high bin - should be 100% (3 of 3 bins)
data = 10;
cg_inst.sample();
check_coverage(100.0, "after high");
// Sample again - coverage should still be 100%
data = 2;
cg_inst.sample();
check_coverage(100.0, "after resample");
// Sample again - coverage should still be 100%
data = 2;
cg_inst.sample();
check_coverage(100.0, "after resample");
$write("*-* All Finished *-*\n");
$finish;
$write("*-* All Finished *-*\n");
$finish;
end
task check_coverage(real expected, string label);
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
// Allow 0.5% tolerance for floating point
if (cov < expected - 0.5 || cov > expected + 0.5) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
task check_coverage(real expected, string label);
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
// Allow 0.5% tolerance for floating point
if (cov < expected - 0.5 || cov > expected + 0.5) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
endtask
endtask
endmodule

View File

@ -7,67 +7,67 @@
// Test 3-way cross coverage
module t;
logic [1:0] addr;
logic cmd;
logic mode;
logic [1:0] addr;
logic cmd;
logic mode;
// Covergroup with 3-way cross coverage
covergroup cg;
cp_addr: coverpoint addr {
bins addr0 = {0};
bins addr1 = {1};
bins addr2 = {2};
}
cp_cmd: coverpoint cmd {
bins read = {0};
bins write = {1};
}
cp_mode: coverpoint mode {
bins normal = {0};
bins debug = {1};
}
// 3-way cross: addr x cmd x mode = 3 x 2 x 2 = 12 cross bins
addr_cmd_mode: cross cp_addr, cp_cmd, cp_mode;
endgroup
// Covergroup with 3-way cross coverage
covergroup cg;
cp_addr: coverpoint addr {
bins addr0 = {0};
bins addr1 = {1};
bins addr2 = {2};
}
cp_cmd: coverpoint cmd {
bins read = {0};
bins write = {1};
}
cp_mode: coverpoint mode {
bins normal = {0};
bins debug = {1};
}
// 3-way cross: addr x cmd x mode = 3 x 2 x 2 = 12 cross bins
addr_cmd_mode: cross cp_addr, cp_cmd, cp_mode;
endgroup
cg cg_inst = new;
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);
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 = 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 = 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 = 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);
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());
// 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());
if (cg_inst.get_inst_coverage() < 62.0 || cg_inst.get_inst_coverage() > 64.0) begin
$display("%%Error: Expected coverage around 63%%, got %0.1f%%",
cg_inst.get_inst_coverage());
$stop;
end
if (cg_inst.get_inst_coverage() < 62.0 || cg_inst.get_inst_coverage() > 64.0) begin
$display("%%Error: Expected coverage around 63%%, got %0.1f%%",
cg_inst.get_inst_coverage());
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -7,68 +7,68 @@
// Test 4-way cross coverage
module t;
logic [1:0] addr;
logic cmd;
logic mode;
logic parity;
logic [1:0] addr;
logic cmd;
logic mode;
logic parity;
// Covergroup with 4-way cross coverage
covergroup cg;
cp_addr: coverpoint addr {
bins addr0 = {0};
bins addr1 = {1};
}
cp_cmd: coverpoint cmd {
bins read = {0};
bins write = {1};
}
cp_mode: coverpoint mode {
bins normal = {0};
bins debug = {1};
}
cp_parity: coverpoint parity {
bins even = {0};
bins odd = {1};
}
// 4-way cross: addr x cmd x mode x parity = 2 x 2 x 2 x 2 = 16 cross bins
addr_cmd_mode_parity: cross cp_addr, cp_cmd, cp_mode, cp_parity;
endgroup
// Covergroup with 4-way cross coverage
covergroup cg;
cp_addr: coverpoint addr {
bins addr0 = {0};
bins addr1 = {1};
}
cp_cmd: coverpoint cmd {
bins read = {0};
bins write = {1};
}
cp_mode: coverpoint mode {
bins normal = {0};
bins debug = {1};
}
cp_parity: coverpoint parity {
bins even = {0};
bins odd = {1};
}
// 4-way cross: addr x cmd x mode x parity = 2 x 2 x 2 x 2 = 16 cross bins
addr_cmd_mode_parity: cross cp_addr, cp_cmd, cp_mode, cp_parity;
endgroup
cg cg_inst = new;
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);
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 = 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 = 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);
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());
// 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());
if (cg_inst.get_inst_coverage() < 49.0 || cg_inst.get_inst_coverage() > 51.0) begin
$display("%%Error: Expected coverage around 50%%, got %0.1f%%",
cg_inst.get_inst_coverage());
$stop;
end
if (cg_inst.get_inst_coverage() < 49.0 || cg_inst.get_inst_coverage() > 51.0) begin
$display("%%Error: Expected coverage around 50%%, got %0.1f%%",
cg_inst.get_inst_coverage());
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/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

@ -7,77 +7,77 @@
// Test basic cross coverage functionality
module t;
/* verilator lint_off UNSIGNED */
bit [7:0] addr;
bit [7:0] cmd;
/* 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]};
}
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};
}
b: coverpoint cmd {
bins read = {0};
bins write = {1};
}
// 2-way cross creates 4 bins: lowread, lowwrite, highread, highwrite
c: cross a, b;
endgroup
// 2-way cross creates 4 bins: lowread, lowwrite, highread, highwrite
c: cross a, b;
endgroup
initial begin
cg cg_inst;
real cov;
initial begin
cg cg_inst;
real cov;
cg_inst = new();
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;
// 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

@ -7,80 +7,76 @@
// Test large cross coverage with sparse map implementation
module t(/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
int cyc = 0;
int cyc = 0;
logic [3:0] a;
logic [3:0] b;
logic [3:0] c;
logic [3:0] d;
logic [3:0] a;
logic [3:0] b;
logic [3:0] c;
logic [3:0] d;
covergroup cg @(posedge clk);
option.per_instance = 1;
covergroup cg @(posedge clk);
option.per_instance = 1;
// Each coverpoint has 4 bins, total cross: 4444 = 256 bins
// This exceeds threshold of 64, so should use sparse map
cp_a: coverpoint a {
bins a0 = {0,1,2,3};
bins a1 = {4,5,6,7};
bins a2 = {8,9,10,11};
bins a3 = {12,13,14,15};
}
// Each coverpoint has 3 bins, total cross: 3*3*3*3 = 81 bins
// This exceeds threshold of 64, so should use sparse map
cp_a: coverpoint a {
bins a0 = {0,1,2,3,4};
bins a1 = {5,6,7,8,9};
bins a2 = {10,11,12,13,14,15};
}
cp_b: coverpoint b {
bins b0 = {0,1,2,3};
bins b1 = {4,5,6,7};
bins b2 = {8,9,10,11};
bins b3 = {12,13,14,15};
}
cp_b: coverpoint b {
bins b0 = {0,1,2,3,4};
bins b1 = {5,6,7,8,9};
bins b2 = {10,11,12,13,14,15};
}
cp_c: coverpoint c {
bins c0 = {0,1,2,3};
bins c1 = {4,5,6,7};
bins c2 = {8,9,10,11};
bins c3 = {12,13,14,15};
}
cp_c: coverpoint c {
bins c0 = {0,1,2,3,4};
bins c1 = {5,6,7,8,9};
bins c2 = {10,11,12,13,14,15};
}
cp_d: coverpoint d {
bins d0 = {0,1,2,3};
bins d1 = {4,5,6,7};
bins d2 = {8,9,10,11};
bins d3 = {12,13,14,15};
}
cp_d: coverpoint d {
bins d0 = {0,1,2,3,4};
bins d1 = {5,6,7,8,9};
bins d2 = {10,11,12,13,14,15};
}
// 4-way cross: 4444 = 256 bins (> 64 threshold)
cross_abcd: cross cp_a, cp_b, cp_c, cp_d;
endgroup
// 4-way cross: 3*3*3*3 = 81 bins (> 64 threshold, uses sparse map)
cross_abcd: cross cp_a, cp_b, cp_c, cp_d;
endgroup
cg cg_inst = new;
cg cg_inst = new;
always @(posedge clk) begin
cyc <= cyc + 1;
always @(posedge clk) begin
cyc <= cyc + 1;
// Generate some cross coverage
a <= cyc[3:0];
b <= cyc[7:4];
c <= cyc[3:0]; // Intentionally correlate some
d <= cyc[7:4];
// Generate some cross coverage
a <= cyc[3:0];
b <= cyc[7:4];
c <= cyc[3:0]; // Intentionally correlate some
d <= cyc[7:4];
if (cyc == 20) begin
/* verilator lint_off IMPLICITSTATIC */
real inst_cov = cg_inst.get_inst_coverage();
/* verilator lint_on IMPLICITSTATIC */
$display("Coverage: %0.1f%%", inst_cov);
if (cyc == 20) begin
/* verilator lint_off IMPLICITSTATIC */
real inst_cov = cg_inst.get_inst_coverage();
/* verilator lint_on IMPLICITSTATIC */
$display("Coverage: %0.1f%%", inst_cov);
if (inst_cov < 1.0 || inst_cov > 100.0) begin
$display("%%Error: Invalid coverage value");
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
if (inst_cov < 1.0 || inst_cov > 100.0) begin
$display("%%Error: Invalid coverage value");
$stop;
end
end
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule

View File

@ -7,59 +7,59 @@
// Test basic cross coverage with 2-way cross
module t;
logic [1:0] addr;
logic cmd;
logic clk;
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 write = {1};
}
// Cross coverage: addr x cmd = 4 x 2 = 8 bins
addr_cmd: cross cp_addr, cp_cmd;
endgroup
// 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 write = {1};
}
// Cross coverage: addr x cmd = 4 x 2 = 8 bins
addr_cmd: cross cp_addr, cp_cmd;
endgroup
cg cg_inst = new;
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);
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 = 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 = 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);
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());
// 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());
if (cg_inst.get_inst_coverage() < 63.0 || cg_inst.get_inst_coverage() > 65.0) begin
$display("%%Error: Expected coverage around 64%%, got %0.1f%%",
cg_inst.get_inst_coverage());
$stop;
end
if (cg_inst.get_inst_coverage() < 63.0 || cg_inst.get_inst_coverage() > 65.0) begin
$display("%%Error: Expected coverage around 64%%, got %0.1f%%",
cg_inst.get_inst_coverage());
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/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

@ -7,54 +7,54 @@
// Test small cross coverage with inline implementation
module t(/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
int cyc = 0;
int cyc = 0;
logic [3:0] a;
logic [3:0] b;
logic [3:0] a;
logic [3:0] b;
covergroup cg @(posedge clk);
option.per_instance = 1;
covergroup cg @(posedge clk);
option.per_instance = 1;
// 2-way cross: 44 = 16 bins (< 64 threshold, should use inline)
cp_a: coverpoint a {
bins a0 = {0,1,2,3};
bins a1 = {4,5,6,7};
bins a2 = {8,9,10,11};
bins a3 = {12,13,14,15};
}
// 2-way cross: 44 = 16 bins (< 64 threshold, should use inline)
cp_a: coverpoint a {
bins a0 = {0,1,2,3};
bins a1 = {4,5,6,7};
bins a2 = {8,9,10,11};
bins a3 = {12,13,14,15};
}
cp_b: coverpoint b {
bins b0 = {0,1,2,3};
bins b1 = {4,5,6,7};
bins b2 = {8,9,10,11};
bins b3 = {12,13,14,15};
}
cp_b: coverpoint b {
bins b0 = {0,1,2,3};
bins b1 = {4,5,6,7};
bins b2 = {8,9,10,11};
bins b3 = {12,13,14,15};
}
cross_ab: cross cp_a, cp_b;
endgroup
cross_ab: cross cp_a, cp_b;
endgroup
cg cg_inst = new;
cg cg_inst = new;
always @(posedge clk) begin
cyc <= cyc + 1;
always @(posedge clk) begin
cyc <= cyc + 1;
a <= cyc[3:0];
b <= cyc[7:4];
a <= cyc[3:0];
b <= cyc[7:4];
if (cyc == 20) begin
/* verilator lint_off IMPLICITSTATIC */
real inst_cov = cg_inst.get_inst_coverage();
/* verilator lint_on IMPLICITSTATIC */
$display("Coverage: %0.1f%%", inst_cov);
if (cyc == 20) begin
/* verilator lint_off IMPLICITSTATIC */
real inst_cov = cg_inst.get_inst_coverage();
/* verilator lint_on IMPLICITSTATIC */
$display("Coverage: %0.1f%%", inst_cov);
$write("*-* All Finished *-*\n");
$finish;
end
end
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule

View File

@ -13,26 +13,26 @@
// - Hierarchy ("cg.cp.low", "cg.cp.high")
module t (/*AUTOARG*/);
logic [1:0] data;
logic [1:0] data;
covergroup cg;
cp: coverpoint data {
bins low = {2'b00};
bins high = {2'b11};
}
endgroup
covergroup cg;
cp: coverpoint data {
bins low = {2'b00};
bins high = {2'b11};
}
endgroup
cg cg_inst = new;
cg cg_inst = new;
initial begin
// Sample both bins
data = 2'b00;
cg_inst.sample();
initial begin
// Sample both bins
data = 2'b00;
cg_inst.sample();
data = 2'b11;
cg_inst.sample();
data = 2'b11;
cg_inst.sample();
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/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

@ -7,60 +7,60 @@
// Test default bins - catch-all for values not in other bins
module t;
/* verilator lint_off UNSIGNED */
bit [7:0] data;
/* verilator lint_off UNSIGNED */
bit [7:0] data;
covergroup cg;
coverpoint data {
bins low = {[0:3]};
bins high = {[12:15]};
bins other = default; // Catches everything else (4-11, 16+)
}
endgroup
covergroup cg;
coverpoint data {
bins low = {[0:3]};
bins high = {[12:15]};
bins other = default; // Catches everything else (4-11, 16+)
}
endgroup
initial begin
cg cg_inst;
real cov;
initial begin
cg cg_inst;
real cov;
cg_inst = new();
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;
// 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
endmodule

View File

@ -0,0 +1,18 @@
#!/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

@ -8,86 +8,86 @@
module t;
covergroup cg;
coverpoint data {
bins low = {[0:1]};
bins high = {[2:3]};
}
endgroup
covergroup cg;
coverpoint data {
bins low = {[0:1]};
bins high = {[2:3]};
}
endgroup
int data;
int data;
initial begin
cg cg_inst;
real cov;
initial begin
cg cg_inst;
real cov;
// Test 1: Create single dynamic instance
$display("Test 1: Single dynamic instance");
cg_inst = new;
// Test 1: Create single dynamic instance
$display("Test 1: Single dynamic instance");
cg_inst = new;
// Initially no coverage
cov = cg_inst.get_inst_coverage();
$display(" Initial coverage: %f", cov);
if (cov != 0.0) $stop;
// Initially no coverage
cov = cg_inst.get_inst_coverage();
$display(" Initial coverage: %f", cov);
if (cov != 0.0) $stop;
// Sample low bin
// Sample low bin
data = 0;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display(" After sampling low: %f", cov);
if (cov < 49.0 || cov > 51.0) $stop; // ~50%
// Sample high bin
data = 2;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display(" After sampling high: %f", cov);
if (cov < 99.0 || cov > 101.0) $stop; // ~100%
// Test 2: Multiple dynamic instances
$display("Test 2: Multiple dynamic instances");
begin
cg cg1, cg2, cg3;
cg1 = new;
cg2 = new;
cg3 = new;
// Sample different bins in each
data = 0;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display(" After sampling low: %f", cov);
if (cov < 49.0 || cov > 51.0) $stop; // ~50%
cg1.sample();
// Sample high bin
data = 2;
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display(" After sampling high: %f", cov);
if (cov < 99.0 || cov > 101.0) $stop; // ~100%
cg2.sample();
// Test 2: Multiple dynamic instances
$display("Test 2: Multiple dynamic instances");
begin
cg cg1, cg2, cg3;
data = 1;
cg3.sample();
cg1 = new;
cg2 = new;
cg3 = new;
// Check individual coverage
cov = cg1.get_inst_coverage();
$display(" cg1 coverage: %f", cov);
if (cov < 49.0 || cov > 51.0) $stop; // 50%
// Sample different bins in each
data = 0;
cg1.sample();
cov = cg2.get_inst_coverage();
$display(" cg2 coverage: %f", cov);
if (cov < 49.0 || cov > 51.0) $stop; // 50%
data = 2;
cg2.sample();
cov = cg3.get_inst_coverage();
$display(" cg3 coverage: %f", cov);
if (cov < 49.0 || cov > 51.0) $stop; // 50%
end
data = 1;
cg3.sample();
// Test 3: Reassignment (old instance should be cleaned up)
$display("Test 3: Instance reassignment");
cg_inst = new; // Create new, old should be freed
// Check individual coverage
cov = cg1.get_inst_coverage();
$display(" cg1 coverage: %f", cov);
if (cov < 49.0 || cov > 51.0) $stop; // 50%
// New instance starts with 0% coverage
cov = cg_inst.get_inst_coverage();
$display(" New instance coverage: %f", cov);
if (cov != 0.0) $stop;
cov = cg2.get_inst_coverage();
$display(" cg2 coverage: %f", cov);
if (cov < 49.0 || cov > 51.0) $stop; // 50%
cov = cg3.get_inst_coverage();
$display(" cg3 coverage: %f", cov);
if (cov < 49.0 || cov > 51.0) $stop; // 50%
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);
if (cov != 0.0) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -6,49 +6,49 @@
// Expected: Should compile, coverage should be 100% (nothing to cover)
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
logic [7:0] value;
logic [7:0] value;
// Empty covergroup - no coverpoints defined
covergroup cg_empty;
// Intentionally empty
endgroup
// Empty covergroup - no coverpoints defined
covergroup cg_empty;
// Intentionally empty
endgroup
cg_empty cg_inst = new;
cg_empty cg_inst = new;
int cyc = 0;
int cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
value <= value + 1;
always @(posedge clk) begin
cyc <= cyc + 1;
value <= value + 1;
cg_inst.sample();
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);
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
// 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
end
if (cyc > 10) begin
$display("ERROR: Test timed out");
$stop;
end
end
if (cyc > 10) begin
$display("ERROR: Test timed out");
$stop;
end
end
endmodule

View File

@ -5,19 +5,19 @@
// SPDX-License-Identifier: CC0-1.0
module t (input clk);
int value = 0;
int value = 0;
covergroup cg;
cp: coverpoint value {
bins low = {[0:5]};
}
endgroup
covergroup cg;
cp: coverpoint value {
bins low = {[0:5]};
}
endgroup
cg my_cg = new;
cg my_cg = new;
always @(posedge clk) begin
real cov;
cov = my_cg.get_inst_coverage();
my_cg.sample();
end
always @(posedge clk) begin
real cov;
cov = my_cg.get_inst_coverage();
my_cg.sample();
end
endmodule

View File

@ -5,19 +5,19 @@
// SPDX-License-Identifier: CC0-1.0
module t (input clk);
logic enable = 0;
int value = 0;
logic enable = 0;
int value = 0;
covergroup cg_iff;
cp_value: coverpoint value iff (enable) {
bins low = {[0:5]};
bins mid = {[6:10]};
}
endgroup
covergroup cg_iff;
cp_value: coverpoint value iff (enable) {
bins low = {[0:5]};
bins mid = {[6:10]};
}
endgroup
cg_iff cg = new;
cg_iff cg = new;
always @(posedge clk) begin
cg.sample();
end
always @(posedge clk) begin
cg.sample();
end
endmodule

View File

@ -7,57 +7,57 @@
// Test ignore_bins - excluded from coverage
module t (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [3:0] data;
/* 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
}
endgroup
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
}
endgroup
cg cg_inst;
cg cg_inst;
initial begin
cg_inst = new;
initial begin
cg_inst = new;
// Initially 0% (0 of 3 regular bins)
check_coverage(0.0, "initial");
// Initially 0% (0 of 3 regular bins)
check_coverage(0.0, "initial");
// Hit reserved bin - should still be 0%
data = 13;
cg_inst.sample();
check_coverage(0.0, "after reserved");
// Hit reserved bin - should still be 0%
data = 13;
cg_inst.sample();
check_coverage(0.0, "after reserved");
// Hit low bin - now 33.33% (1 of 3)
data = 1;
cg_inst.sample();
check_coverage(33.33, "after low");
// Hit low bin - now 33.33% (1 of 3)
data = 1;
cg_inst.sample();
check_coverage(33.33, "after low");
// Hit another reserved value - still 33.33%
data = 15;
cg_inst.sample();
check_coverage(33.33, "after another reserved");
// Hit another reserved value - still 33.33%
data = 15;
cg_inst.sample();
check_coverage(33.33, "after another reserved");
// Complete regular bins
data = 5; cg_inst.sample(); // mid
data = 10; cg_inst.sample(); // high
check_coverage(100.0, "complete");
// Complete regular bins
data = 5; cg_inst.sample(); // mid
data = 10; cg_inst.sample(); // high
check_coverage(100.0, "complete");
$write("*-* All Finished *-*\n");
$finish;
$write("*-* All Finished *-*\n");
$finish;
end
task check_coverage(real expected, string label);
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
if (cov < expected - 0.5 || cov > expected + 0.5) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
task check_coverage(real expected, string label);
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
if (cov < expected - 0.5 || cov > expected + 0.5) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
endtask
endtask
endmodule

View File

@ -5,35 +5,35 @@
// SPDX-License-Identifier: CC0-1.0
module t;
/* verilator lint_off UNSIGNED */
logic [1:0] data;
/* verilator lint_off UNSIGNED */
logic [1:0] data;
covergroup cg;
coverpoint data {
bins low = {0};
bins mid = {1};
bins high = {2};
illegal_bins forbidden = {3};
}
endgroup
covergroup cg;
coverpoint data {
bins low = {0};
bins mid = {1};
bins high = {2};
illegal_bins forbidden = {3};
}
endgroup
initial begin
automatic cg cg_inst = new;
initial begin
automatic cg cg_inst = new;
// Sample legal values only
data = 0;
cg_inst.sample();
$display("Coverage after low: %f%% (expected ~33.33%%)", cg_inst.get_inst_coverage());
// 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 = 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());
data = 2;
cg_inst.sample();
$display("Coverage complete: %f%% (expected ~100.00%%)", cg_inst.get_inst_coverage());
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

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

View File

@ -7,53 +7,53 @@
// Test mixed bin types: single values and ranges
module t (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [7:0] opcode;
/* verilator lint_off UNSIGNED */
logic [7:0] opcode;
covergroup cg;
coverpoint opcode {
bins nop = {8'h00};
bins load = {8'h01, 8'h02, 8'h03};
bins store = {8'h04, 8'h05};
bins arith = {[8'h10:8'h1F]};
bins others = {[8'h20:8'hFE]}; // Avoid 0xFF to prevent CMPCONST warning
}
endgroup
covergroup cg;
coverpoint opcode {
bins nop = {8'h00};
bins load = {8'h01, 8'h02, 8'h03};
bins store = {8'h04, 8'h05};
bins arith = {[8'h10:8'h1F]};
bins others = {[8'h20:8'hFE]}; // Avoid 0xFF to prevent CMPCONST warning
}
endgroup
cg cg_inst;
cg cg_inst;
initial begin
cg_inst = new;
initial begin
cg_inst = new;
// Test single value bins
opcode = 8'h00; cg_inst.sample(); // nop
check_coverage(20.0, "after nop");
// Test single value bins
opcode = 8'h00; cg_inst.sample(); // nop
check_coverage(20.0, "after nop");
// Test multi-value list bin
opcode = 8'h02; cg_inst.sample(); // load
check_coverage(40.0, "after load");
// Test multi-value list bin
opcode = 8'h02; cg_inst.sample(); // load
check_coverage(40.0, "after load");
opcode = 8'h05; cg_inst.sample(); // store
check_coverage(60.0, "after store");
opcode = 8'h05; cg_inst.sample(); // store
check_coverage(60.0, "after store");
// Test range bin
opcode = 8'h15; cg_inst.sample(); // arith
check_coverage(80.0, "after arith");
// Test range bin
opcode = 8'h15; cg_inst.sample(); // arith
check_coverage(80.0, "after arith");
opcode = 8'h80; cg_inst.sample(); // others
check_coverage(100.0, "after others");
opcode = 8'h80; cg_inst.sample(); // others
check_coverage(100.0, "after others");
$write("*-* All Finished *-*\n");
$finish;
$write("*-* All Finished *-*\n");
$finish;
end
task check_coverage(real expected, string label);
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
if (cov < expected - 0.5 || cov > expected + 0.5) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
task check_coverage(real expected, string label);
real cov;
cov = cg_inst.get_inst_coverage();
$display("Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
if (cov < expected - 0.5 || cov > expected + 0.5) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
endtask
endtask
endmodule

View File

@ -7,54 +7,54 @@
// Test multiple covergroup instances with separate tracking
module t (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [3:0] data1, data2;
/* verilator lint_off UNSIGNED */
logic [3:0] data1, data2;
covergroup cg;
coverpoint data1 {
bins low = {[0:3]};
bins high = {[4:15]};
}
endgroup
covergroup cg;
coverpoint data1 {
bins low = {[0:3]};
bins high = {[4:15]};
}
endgroup
cg cg_inst1, cg_inst2;
cg cg_inst1, cg_inst2;
initial begin
cg_inst1 = new;
cg_inst2 = new;
initial begin
cg_inst1 = new;
cg_inst2 = new;
// Initially both have 0% coverage
check_coverage(cg_inst1, 0.0, "inst1 initial");
check_coverage(cg_inst2, 0.0, "inst2 initial");
// Initially both have 0% coverage
check_coverage(cg_inst1, 0.0, "inst1 initial");
check_coverage(cg_inst2, 0.0, "inst2 initial");
// Sample different values in each instance
data1 = 1;
cg_inst1.sample(); // inst1: low covered (50%)
check_coverage(cg_inst1, 50.0, "inst1 after low");
check_coverage(cg_inst2, 0.0, "inst2 still empty");
// Sample different values in each instance
data1 = 1;
cg_inst1.sample(); // inst1: low covered (50%)
check_coverage(cg_inst1, 50.0, "inst1 after low");
check_coverage(cg_inst2, 0.0, "inst2 still empty");
data1 = 10;
cg_inst2.sample(); // inst2: high covered (50%)
check_coverage(cg_inst1, 50.0, "inst1 still 50%");
check_coverage(cg_inst2, 50.0, "inst2 after high");
data1 = 10;
cg_inst2.sample(); // inst2: high covered (50%)
check_coverage(cg_inst1, 50.0, "inst1 still 50%");
check_coverage(cg_inst2, 50.0, "inst2 after high");
// Complete coverage in inst1
data1 = 8;
cg_inst1.sample(); // inst1: both covered (100%)
check_coverage(cg_inst1, 100.0, "inst1 complete");
check_coverage(cg_inst2, 50.0, "inst2 still 50%");
// Complete coverage in inst1
data1 = 8;
cg_inst1.sample(); // inst1: both covered (100%)
check_coverage(cg_inst1, 100.0, "inst1 complete");
check_coverage(cg_inst2, 50.0, "inst2 still 50%");
$write("*-* All Finished *-*\n");
$finish;
$write("*-* All Finished *-*\n");
$finish;
end
task check_coverage(cg inst, real expected, string label);
real cov;
cov = inst.get_inst_coverage();
$display("Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
if (cov < expected - 0.5 || cov > expected + 0.5) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
task check_coverage(cg inst, real expected, string label);
real cov;
cov = inst.get_inst_coverage();
$display("Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
if (cov < expected - 0.5 || cov > expected + 0.5) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
endtask
endtask
endmodule

View File

@ -7,73 +7,73 @@
// since they all sample the same expression (value1)
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
logic [2:0] value1;
logic [2:0] value1;
covergroup cg;
cp: coverpoint value1 {
bins low = {[0:3]};
bins high = {[4:7]};
}
endgroup
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;
// Create three independent instances
cg cg_inst1 = new;
cg cg_inst2 = new;
cg cg_inst3 = new;
int cyc = 0;
int cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
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;
case (cyc)
0: begin
value1 <= 1; // low bin for all instances
end
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

@ -6,60 +6,60 @@
// Expected: Should handle negative numbers correctly
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
int signed value;
int signed value;
/* verilator lint_off CMPCONST */
covergroup cg;
cp_neg: coverpoint value {
bins negative = {[-100:-1]};
bins zero = {0};
bins positive = {[1:100]};
bins mixed = {[-10:10]};
}
endgroup
/* verilator lint_on CMPCONST */
/* verilator lint_off CMPCONST */
covergroup cg;
cp_neg: coverpoint value {
bins negative = {[-100:-1]};
bins zero = {0};
bins positive = {[1:100]};
bins mixed = {[-10:10]};
}
endgroup
/* verilator lint_on CMPCONST */
cg cg_inst = new;
cg cg_inst = new;
int cyc = 0;
int cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
always @(posedge clk) begin
cyc <= cyc + 1;
case (cyc)
0: value <= -50; // Hit negative bin
1: value <= 0; // Hit zero bin
2: value <= 50; // Hit positive bin
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);
case (cyc)
0: value <= -50; // Hit negative bin
1: value <= 0; // Hit zero bin
2: value <= 50; // Hit positive bin
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
// 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
endcase
cg_inst.sample();
if (cyc > 10) begin
$display("ERROR: Test timed out");
$stop;
end
end
endcase
cg_inst.sample();
if (cyc > 10) begin
$display("ERROR: Test timed out");
$stop;
end
end
endmodule

View File

@ -1,6 +1,6 @@
%Warning-COVERIGN: t/t_covergroup_option_unsup.v:15:13: Ignoring unsupported coverage option: foobar
15 | option.foobar = 1;
| ^~~~~~
%Warning-COVERIGN: t/t_covergroup_option_unsup.v:15:7: Ignoring unsupported coverage option: foobar
15 | option.foobar = 1;
| ^~~~~~
... 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.
%Error: Exiting due to

View File

@ -8,14 +8,14 @@
// Test: unsupported coverage option name in a coverpoint
module t;
logic [3:0] cp_expr;
logic [3:0] cp_expr;
covergroup cg;
cp1: coverpoint cp_expr {
option.foobar = 1;
}
endgroup
covergroup cg;
cp1: coverpoint cp_expr {
option.foobar = 1;
}
endgroup
cg cg_inst = new;
initial $finish;
cg cg_inst = new;
initial $finish;
endmodule

View File

@ -7,107 +7,107 @@
// Performance test for functional coverage - measures sample() overhead
module t;
logic [7:0] data;
logic [3:0] state;
logic [15:0] addr;
logic [7:0] data;
logic [3:0] state;
logic [15:0] addr;
// Large covergroup with multiple coverpoints and many bins
covergroup cg_perf;
// Coverpoint with many bins
cp_data: coverpoint data {
bins d0 = {0};
bins d1 = {1};
bins d2 = {2};
bins d3 = {3};
bins d4 = {4};
bins d5 = {5};
bins d6 = {6};
bins d7 = {7};
bins d8 = {8};
bins d9 = {9};
bins d10 = {[10:19]};
bins d20 = {[20:29]};
bins d30 = {[30:39]};
bins d40 = {[40:49]};
bins d50 = {[50:59]};
bins rest = {[60:255]};
}
// Large covergroup with multiple coverpoints and many bins
covergroup cg_perf;
// Coverpoint with many bins
cp_data: coverpoint data {
bins d0 = {0};
bins d1 = {1};
bins d2 = {2};
bins d3 = {3};
bins d4 = {4};
bins d5 = {5};
bins d6 = {6};
bins d7 = {7};
bins d8 = {8};
bins d9 = {9};
bins d10 = {[10:19]};
bins d20 = {[20:29]};
bins d30 = {[30:39]};
bins d40 = {[40:49]};
bins d50 = {[50:59]};
bins rest = {[60:255]};
}
cp_state: coverpoint state {
bins s0 = {0};
bins s1 = {1};
bins s2 = {2};
bins s3 = {3};
bins s4 = {4};
bins s5 = {5};
bins s6 = {6};
bins s7 = {7};
bins s8 = {8};
bins s9 = {9};
bins s10 = {10};
bins s11 = {11};
bins s12 = {12};
bins s13 = {13};
bins s14 = {14};
bins s15 = {15};
}
cp_state: coverpoint state {
bins s0 = {0};
bins s1 = {1};
bins s2 = {2};
bins s3 = {3};
bins s4 = {4};
bins s5 = {5};
bins s6 = {6};
bins s7 = {7};
bins s8 = {8};
bins s9 = {9};
bins s10 = {10};
bins s11 = {11};
bins s12 = {12};
bins s13 = {13};
bins s14 = {14};
bins s15 = {15};
}
// verilator lint_off UNSIGNED
// verilator lint_off CMPCONST
cp_addr: coverpoint addr {
bins low = {[16'h0000:16'h03FF]}; // [0:1023]
bins mid = {[16'h0400:16'h07FF]}; // [1024:2047]
bins high = {[16'h0800:16'hFFFF]}; // [2048:65535]
}
// verilator lint_on CMPCONST
// verilator lint_on UNSIGNED
// verilator lint_off UNSIGNED
// verilator lint_off CMPCONST
cp_addr: coverpoint addr {
bins low = {[16'h0000:16'h03FF]}; // [0:1023]
bins mid = {[16'h0400:16'h07FF]}; // [1024:2047]
bins high = {[16'h0800:16'hFFFF]}; // [2048:65535]
}
// verilator lint_on CMPCONST
// verilator lint_on UNSIGNED
// Cross coverage adds more bins
cross_data_state: cross cp_data, cp_state;
endgroup
// Cross coverage adds more bins
cross_data_state: cross cp_data, cp_state;
endgroup
cg_perf cg_inst = new;
cg_perf cg_inst = new;
initial begin
automatic longint start_time, end_time, elapsed;
automatic int iterations = 100000;
automatic real avg_time_ns;
initial begin
automatic longint start_time, end_time, elapsed;
automatic int iterations = 100000;
automatic real avg_time_ns;
$display("=== Functional Coverage Performance Test ===");
$display("Iterations: %0d", iterations);
$display("=== Functional Coverage Performance Test ===");
$display("Iterations: %0d", iterations);
// Measure sample() overhead
start_time = $time;
// Measure sample() overhead
start_time = $time;
for (int i = 0; i < iterations; i++) begin
// Vary the data to hit different bins
data = i[7:0];
state = i[3:0];
addr = i[15:0];
for (int i = 0; i < iterations; i++) begin
// Vary the data to hit different bins
data = i[7:0];
state = i[3:0];
addr = i[15:0];
cg_inst.sample();
end
cg_inst.sample();
end
end_time = $time;
elapsed = end_time - start_time;
end_time = $time;
elapsed = end_time - start_time;
avg_time_ns = real'(elapsed) / real'(iterations);
avg_time_ns = real'(elapsed) / real'(iterations);
$display("Total time: %0d time units", elapsed);
$display("Average time per sample(): %0.2f time units", avg_time_ns);
$display("Coverage: %0.1f%%", cg_inst.get_inst_coverage());
$display("Total time: %0d time units", elapsed);
$display("Average time per sample(): %0.2f time units", avg_time_ns);
$display("Coverage: %0.1f%%", cg_inst.get_inst_coverage());
// Performance target: < 100 cycles per sample()
// Assuming 1 time unit = 1 ns, typical CPU @ 3 GHz = 0.33 ns/cycle
// 100 cycles = 33 ns
if (avg_time_ns < 33.0) begin
$display("PASS: Performance within target (< 100 cycles)");
end else begin
$display("WARNING: Performance may need optimization (> 100 cycles)");
end
// Performance target: < 100 cycles per sample()
// Assuming 1 time unit = 1 ns, typical CPU @ 3 GHz = 0.33 ns/cycle
// 100 cycles = 33 ns
if (avg_time_ns < 33.0) begin
$display("PASS: Performance within target (< 100 cycles)");
end else begin
$display("WARNING: Performance may need optimization (> 100 cycles)");
end
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -7,64 +7,64 @@
// Realistic example: Bus transaction coverage
module t (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [31:0] addr;
logic [1:0] burst_type;
logic valid;
/* verilator lint_off UNSIGNED */
logic [31:0] addr;
logic [1:0] burst_type;
logic valid;
// Coverage for a memory bus interface
covergroup bus_cg;
// Address coverage with interesting regions
coverpoint addr {
bins zero_page = {[32'h0000_0000:32'h0000_00FF]};
bins boot_rom = {[32'h0000_1000:32'h0000_1FFF]};
bins dram = {[32'h4000_0000:32'h7FFF_FFFF]};
bins peripherals = {[32'h8000_0000:32'h9FFF_FFFF]};
}
// Coverage for a memory bus interface
covergroup bus_cg;
// Address coverage with interesting regions
coverpoint addr {
bins zero_page = {[32'h0000_0000:32'h0000_00FF]};
bins boot_rom = {[32'h0000_1000:32'h0000_1FFF]};
bins dram = {[32'h4000_0000:32'h7FFF_FFFF]};
bins peripherals = {[32'h8000_0000:32'h9FFF_FFFF]};
}
// Burst type coverage (only when valid)
coverpoint burst_type iff (valid) {
bins single = {2'b00};
bins incr = {2'b01};
bins wrap = {2'b10};
bins reserved = {2'b11};
}
endgroup
// Burst type coverage (only when valid)
coverpoint burst_type iff (valid) {
bins single = {2'b00};
bins incr = {2'b01};
bins wrap = {2'b10};
bins reserved = {2'b11};
}
endgroup
bus_cg cg_inst;
bus_cg cg_inst;
initial begin
cg_inst = new;
initial begin
cg_inst = new;
// Test various transactions
// Test various transactions
// Boot sequence - should hit zero_page and boot_rom
valid = 1;
addr = 32'h0000_0010; burst_type = 2'b00; cg_inst.sample();
addr = 32'h0000_1100; burst_type = 2'b01; cg_inst.sample();
// Boot sequence - should hit zero_page and boot_rom
valid = 1;
addr = 32'h0000_0010; burst_type = 2'b00; cg_inst.sample();
addr = 32'h0000_1100; burst_type = 2'b01; cg_inst.sample();
// After boot
check_coverage(50.0, "after boot");
// After boot
check_coverage(50.0, "after boot");
// DRAM access with wrap burst
addr = 32'h4000_0000; burst_type = 2'b10; cg_inst.sample();
check_coverage(75.0, "after dram access");
// DRAM access with wrap burst
addr = 32'h4000_0000; burst_type = 2'b10; cg_inst.sample();
check_coverage(75.0, "after dram access");
// Peripheral access completes all addr bins
addr = 32'h8000_0100; burst_type = 2'b11; cg_inst.sample();
check_coverage(100.0, "complete");
// Peripheral access completes all addr bins
addr = 32'h8000_0100; burst_type = 2'b11; cg_inst.sample();
check_coverage(100.0, "complete");
$write("*-* All Finished *-*\n");
$finish;
$write("*-* All Finished *-*\n");
$finish;
end
task check_coverage(real expected, string label);
real cov;
cov = cg_inst.get_inst_coverage();
$display("Bus Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
if (cov < expected - 1.0 || cov > expected + 1.0) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
task check_coverage(real expected, string label);
real cov;
cov = cg_inst.get_inst_coverage();
$display("Bus Coverage %s: %0.2f%% (expected ~%0.2f%%)", label, cov, expected);
if (cov < expected - 1.0 || cov > expected + 1.0) begin
$error("Coverage mismatch: got %0.2f%%, expected ~%0.2f%%", cov, expected);
$stop;
end
endtask
endtask
endmodule

View File

@ -7,30 +7,30 @@
// Test basic functional coverage sampling
module t (/*AUTOARG*/);
/* verilator lint_off UNSIGNED */
logic [3:0] data;
int cyc = 0;
/* verilator lint_off UNSIGNED */
logic [3:0] data;
int cyc = 0;
covergroup cg;
coverpoint data {
bins low = {[0:3]};
bins mid = {[4:7]};
bins high = {[8:15]};
}
endgroup
covergroup cg;
coverpoint data {
bins low = {[0:3]};
bins mid = {[4:7]};
bins high = {[8:15]};
}
endgroup
cg cg_inst;
cg cg_inst;
initial begin
cg_inst = new;
initial begin
cg_inst = new;
// Sample different values
data = 1; cg_inst.sample();
data = 5; cg_inst.sample();
data = 10; cg_inst.sample();
data = 2; cg_inst.sample(); // low hit twice
// Sample different values
data = 1; cg_inst.sample();
data = 5; cg_inst.sample();
data = 10; cg_inst.sample();
data = 2; cg_inst.sample(); // low hit twice
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -7,43 +7,43 @@
// Test basic covergroup with simple coverpoint
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
logic [7:0] addr;
logic cmd;
logic [7:0] addr;
logic cmd;
// Simple covergroup with two coverpoints
covergroup cg @(posedge clk);
cp_addr: coverpoint addr {
bins low = {[0:127]};
bins high = {[128:255]};
}
cp_cmd: coverpoint cmd {
bins read = {0};
bins write = {1};
}
endgroup
// Simple covergroup with two coverpoints
covergroup cg @(posedge clk);
cp_addr: coverpoint addr {
bins low = {[0:127]};
bins high = {[128:255]};
}
cp_cmd: coverpoint cmd {
bins read = {0};
bins write = {1};
}
endgroup
cg cg_inst = new;
cg cg_inst = new;
initial begin
// Sample some values
addr = 10; cmd = 0;
@(posedge clk);
initial begin
// Sample some values
addr = 10; cmd = 0;
@(posedge clk);
addr = 200; cmd = 1;
@(posedge clk);
addr = 200; cmd = 1;
@(posedge clk);
addr = 50; cmd = 0;
@(posedge clk);
addr = 50; cmd = 0;
@(posedge clk);
$display("Coverage: %0.1f%%", cg_inst.get_coverage());
$display("Coverage: %0.1f%%", cg_inst.get_coverage());
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -8,62 +8,62 @@
module t;
covergroup cg;
coverpoint data {
bins low = {[0:1]};
bins mid = {[2:3]};
bins high = {[4:5]};
}
endgroup
covergroup cg;
coverpoint data {
bins low = {[0:1]};
bins mid = {[2:3]};
bins high = {[4:5]};
}
endgroup
int data;
int data;
initial begin
cg cg1, cg2, cg3;
real type_cov;
initial begin
cg cg1, cg2, cg3;
real type_cov;
cg1 = new;
cg2 = new;
cg3 = new;
cg1 = new;
cg2 = new;
cg3 = new;
// Initially, no bins covered - should be 0%
type_cov = cg::get_coverage();
$display("Initial type coverage: %f", type_cov);
if (type_cov != 0.0) $stop;
// Initially, no bins covered - should be 0%
type_cov = cg::get_coverage();
$display("Initial type coverage: %f", type_cov);
if (type_cov != 0.0) $stop;
// Sample cg1 with low bin
data = 0;
cg1.sample();
type_cov = cg::get_coverage();
$display("After cg1.sample(low): %f", type_cov);
// 1 bin covered out of 3 = 33.33%
if (type_cov < 33.0 || type_cov > 34.0) $stop;
// Sample cg1 with low bin
data = 0;
cg1.sample();
type_cov = cg::get_coverage();
$display("After cg1.sample(low): %f", type_cov);
// 1 bin covered out of 3 = 33.33%
if (type_cov < 33.0 || type_cov > 34.0) $stop;
// Sample cg2 with mid bin
data = 2;
cg2.sample();
type_cov = cg::get_coverage();
$display("After cg2.sample(mid): %f", type_cov);
// 2 bins covered out of 3 = 66.67%
if (type_cov < 66.0 || type_cov > 67.0) $stop;
// Sample cg2 with mid bin
data = 2;
cg2.sample();
type_cov = cg::get_coverage();
$display("After cg2.sample(mid): %f", type_cov);
// 2 bins covered out of 3 = 66.67%
if (type_cov < 66.0 || type_cov > 67.0) $stop;
// Sample cg3 with high bin
data = 4;
cg3.sample();
type_cov = cg::get_coverage();
$display("After cg3.sample(high): %f", type_cov);
// 3 bins covered out of 3 = 100%
if (type_cov < 99.9 || type_cov > 100.1) $stop;
// Sample cg3 with high bin
data = 4;
cg3.sample();
type_cov = cg::get_coverage();
$display("After cg3.sample(high): %f", type_cov);
// 3 bins covered out of 3 = 100%
if (type_cov < 99.9 || type_cov > 100.1) $stop;
// Sample cg1 again with same bin - should not change coverage
data = 1;
cg1.sample();
type_cov = cg::get_coverage();
$display("After cg1.sample(low again): %f", type_cov);
if (type_cov < 99.9 || type_cov > 100.1) $stop;
// Sample cg1 again with same bin - should not change coverage
data = 1;
cg1.sample();
type_cov = cg::get_coverage();
$display("After cg1.sample(low again): %f", type_cov);
if (type_cov < 99.9 || type_cov > 100.1) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -3,49 +3,49 @@
// SPDX-License-Identifier: CC0-1.0
module t;
logic [2:0] state;
int errors = 0;
logic [2:0] state;
int errors = 0;
covergroup cg;
cp_state: coverpoint state {
bins trans_3val = (0 => 1 => 2); // 3-value sequence
bins trans_3val_2 = (2 => 3 => 4); // Another 3-value sequence
}
endgroup
covergroup cg;
cp_state: coverpoint state {
bins trans_3val = (0 => 1 => 2); // 3-value sequence
bins trans_3val_2 = (2 => 3 => 4); // Another 3-value sequence
}
endgroup
cg cg_inst = new;
cg cg_inst = new;
initial begin
// Test sequence 1: 0 => 1 => 2 (should complete trans_3val)
state = 0;
cg_inst.sample();
initial begin
// Test sequence 1: 0 => 1 => 2 (should complete trans_3val)
state = 0;
cg_inst.sample();
state = 1; // 0 => 1 (state machine now at position 1)
cg_inst.sample();
state = 1; // 0 => 1 (state machine now at position 1)
cg_inst.sample();
state = 2; // 1 => 2 (completes trans_3val: 0=>1=>2)
cg_inst.sample();
state = 2; // 1 => 2 (completes trans_3val: 0=>1=>2)
cg_inst.sample();
// Test sequence 2: 2 => 3 => 4 (should complete trans_3val_2)
state = 3; // 2 => 3 (state machine now at position 1 for trans_3val_2)
cg_inst.sample();
// Test sequence 2: 2 => 3 => 4 (should complete trans_3val_2)
state = 3; // 2 => 3 (state machine now at position 1 for trans_3val_2)
cg_inst.sample();
state = 4; // 3 => 4 (completes trans_3val_2: 2=>3=>4)
cg_inst.sample();
state = 4; // 3 => 4 (completes trans_3val_2: 2=>3=>4)
cg_inst.sample();
// Check coverage
$display("Coverage: %f%%", cg_inst.get_inst_coverage());
if (cg_inst.get_inst_coverage() < 99.0) begin
$display("ERROR: Expected 100%% coverage, got %f%%", cg_inst.get_inst_coverage());
errors++;
end
// Check coverage
$display("Coverage: %f%%", cg_inst.get_inst_coverage());
if (cg_inst.get_inst_coverage() < 99.0) begin
$display("ERROR: Expected 100%% coverage, got %f%%", cg_inst.get_inst_coverage());
errors++;
end
if (errors == 0) begin
$write("*-* All Finished *-*\n");
end else begin
$display("*-* FAILED with %0d errors *-*", errors);
end
$finish;
end
if (errors == 0) begin
$write("*-* All Finished *-*\n");
end else begin
$display("*-* FAILED with %0d errors *-*", errors);
end
$finish;
end
endmodule

View File

@ -1,11 +1,11 @@
%Warning-COVERIGN: t/t_covergroup_trans_empty_bad.v:15:26: Ignoring unsupported: cover '[*'
15 | bins t1 = (1 [*2]);
| ^~
%Warning-COVERIGN: t/t_covergroup_trans_empty_bad.v:15:20: Ignoring unsupported: cover '[*'
15 | bins t1 = (1 [*2]);
| ^~
... 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.
%Error: t/t_covergroup_trans_empty_bad.v:15:18: Transition set without items
%Error: t/t_covergroup_trans_empty_bad.v:15:12: Transition set without items
: ... note: In instance 't'
15 | bins t1 = (1 [*2]);
| ^~
15 | bins t1 = (1 [*2]);
| ^~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -8,14 +8,14 @@
// Test: transition bin with unsupported repetition operator causes empty transition set
module t;
logic [3:0] cp_expr;
logic [3:0] cp_expr;
covergroup cg;
cp1: coverpoint cp_expr {
bins t1 = (1 [*2]);
}
endgroup
covergroup cg;
cp1: coverpoint cp_expr {
bins t1 = (1 [*2]);
}
endgroup
cg cg_inst = new;
initial $finish;
cg cg_inst = new;
initial $finish;
endmodule

View File

@ -3,51 +3,51 @@
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
logic [2:0] state;
logic [2:0] state;
covergroup cg;
// Test array bins: creates separate bin for each transition
cp_array: coverpoint state {
bins trans_array[] = (0 => 1), (1 => 2), (2 => 3);
}
endgroup
covergroup cg;
// Test array bins: creates separate bin for each transition
cp_array: coverpoint state {
bins trans_array[] = (0 => 1), (1 => 2), (2 => 3);
}
endgroup
cg cg_inst = new;
cg cg_inst = new;
int cyc = 0;
int cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
always @(posedge clk) begin
cyc <= cyc + 1;
case (cyc)
0: state <= 0;
1: state <= 1; // 0 => 1 (hits trans_array[0=>1])
2: state <= 2; // 1 => 2 (hits trans_array[1=>2])
3: state <= 3; // 2 => 3 (hits trans_array[2=>3])
4: begin
real cov = cg_inst.get_inst_coverage();
$display("Coverage: %f%%", cov);
// We should have hit all 3 array bins = 100%
if (cov >= 99.0) begin
$write("*-* All Finished *-*\n");
$finish;
end else begin
$display("ERROR: Expected 100%% coverage, got %f%%", cov);
$stop;
end
case (cyc)
0: state <= 0;
1: state <= 1; // 0 => 1 (hits trans_array[0=>1])
2: state <= 2; // 1 => 2 (hits trans_array[1=>2])
3: state <= 3; // 2 => 3 (hits trans_array[2=>3])
4: begin
real cov = cg_inst.get_inst_coverage();
$display("Coverage: %f%%", cov);
// We should have hit all 3 array bins = 100%
if (cov >= 99.0) begin
$write("*-* All Finished *-*\n");
$finish;
end else begin
$display("ERROR: Expected 100%% coverage, got %f%%", cov);
$stop;
end
endcase
cg_inst.sample();
if (cyc > 10) begin
$display("ERROR: Test timed out");
$stop;
end
end
endcase
cg_inst.sample();
if (cyc > 10) begin
$display("ERROR: Test timed out");
$stop;
end
end
endmodule

View File

@ -3,55 +3,55 @@
// SPDX-License-Identifier: CC0-1.0
module t;
logic [2:0] state;
int errors = 0;
logic [2:0] state;
int errors = 0;
covergroup cg;
cp_state: coverpoint state {
bins trans_restart = (1 => 2 => 3); // Should handle restart correctly
}
endgroup
covergroup cg;
cp_state: coverpoint state {
bins trans_restart = (1 => 2 => 3); // Should handle restart correctly
}
endgroup
cg cg_inst = new;
cg cg_inst = new;
initial begin
// Sequence: 1, 2, 1, 2, 3
// This tests restart logic: when we see 1 again while in middle of sequence,
// we should restart from position 1 (not reset to 0)
initial begin
// Sequence: 1, 2, 1, 2, 3
// This tests restart logic: when we see 1 again while in middle of sequence,
// we should restart from position 1 (not reset to 0)
state = 1; // Start: position = 1
cg_inst.sample();
$display("After state=1: seqpos should be 1");
state = 1; // Start: position = 1
cg_inst.sample();
$display("After state=1: seqpos should be 1");
state = 2; // Advance: position = 2
cg_inst.sample();
$display("After state=2: seqpos should be 2");
state = 2; // Advance: position = 2
cg_inst.sample();
$display("After state=2: seqpos should be 2");
state = 1; // Restart! Should go to position 1 (not 0)
cg_inst.sample();
$display("After state=1 (restart): seqpos should be 1");
state = 1; // Restart! Should go to position 1 (not 0)
cg_inst.sample();
$display("After state=1 (restart): seqpos should be 1");
state = 2; // Advance: position = 2
cg_inst.sample();
$display("After state=2: seqpos should be 2");
state = 2; // Advance: position = 2
cg_inst.sample();
$display("After state=2: seqpos should be 2");
state = 3; // Complete! Bin should increment
cg_inst.sample();
$display("After state=3: bin should have incremented, seqpos reset to 0");
state = 3; // Complete! Bin should increment
cg_inst.sample();
$display("After state=3: bin should have incremented, seqpos reset to 0");
// Check coverage
$display("Coverage: %f%%", cg_inst.get_inst_coverage());
if (cg_inst.get_inst_coverage() < 99.0) begin
$display("ERROR: Expected 100%% coverage, got %f%%", cg_inst.get_inst_coverage());
errors++;
end
// Check coverage
$display("Coverage: %f%%", cg_inst.get_inst_coverage());
if (cg_inst.get_inst_coverage() < 99.0) begin
$display("ERROR: Expected 100%% coverage, got %f%%", cg_inst.get_inst_coverage());
errors++;
end
if (errors == 0) begin
$write("*-* All Finished *-*\n");
end else begin
$display("*-* FAILED with %0d errors *-*", errors);
end
$finish;
end
if (errors == 0) begin
$write("*-* All Finished *-*\n");
end else begin
$display("*-* FAILED with %0d errors *-*", errors);
end
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/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

@ -3,52 +3,52 @@
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// Inputs
clk
);
input clk;
logic [2:0] state;
logic [2:0] state;
covergroup cg;
cp_state: coverpoint state {
bins trans1 = (0 => 1);
bins trans2 = (1 => 2);
bins trans3 = (2 => 3);
}
endgroup
covergroup cg;
cp_state: coverpoint state {
bins trans1 = (0 => 1);
bins trans2 = (1 => 2);
bins trans3 = (2 => 3);
}
endgroup
cg cg_inst = new;
cg cg_inst = new;
int cyc = 0;
int cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
always @(posedge clk) begin
cyc <= cyc + 1;
case (cyc)
0: state <= 0;
1: state <= 1; // 0 => 1 (trans1 should hit)
2: state <= 2; // 1 => 2 (trans2 should hit)
3: state <= 3; // 2 => 3 (trans3 should hit)
4: begin
$display("Coverage: %f%%", cg_inst.get_inst_coverage());
if (cg_inst.get_inst_coverage() >= 99.0) begin // Allow for rounding
$write("*-* All Finished *-*\n");
$finish;
end else begin
$display("ERROR: Expected 100%% coverage, got %f%%", cg_inst.get_inst_coverage());
$stop;
end
case (cyc)
0: state <= 0;
1: state <= 1; // 0 => 1 (trans1 should hit)
2: state <= 2; // 1 => 2 (trans2 should hit)
3: state <= 3; // 2 => 3 (trans3 should hit)
4: begin
$display("Coverage: %f%%", cg_inst.get_inst_coverage());
if (cg_inst.get_inst_coverage() >= 99.0) begin // Allow for rounding
$write("*-* All Finished *-*\n");
$finish;
end else begin
$display("ERROR: Expected 100%% coverage, got %f%%", cg_inst.get_inst_coverage());
$stop;
end
endcase
// Sample the covergroup manually each clock
cg_inst.sample();
// Auto-stop after 10 cycles to prevent infinite loop
if (cyc > 10) begin
$display("ERROR: Test timed out");
$stop;
end
end
endcase
// Sample the covergroup manually each clock
cg_inst.sample();
// 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,6 +1,6 @@
%Error: t/t_covergroup_trans_single_bad.v:15:18: Transition requires at least two values
%Error: t/t_covergroup_trans_single_bad.v:15:12: Transition requires at least two values
: ... note: In instance 't'
15 | bins t1 = (1);
| ^~
15 | bins t1 = (1);
| ^~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -8,14 +8,14 @@
// Test: transition bin requires at least two values
module t;
logic [3:0] cp_expr;
logic [3:0] cp_expr;
covergroup cg;
cp1: coverpoint cp_expr {
bins t1 = (1);
}
endgroup
covergroup cg;
cp1: coverpoint cp_expr {
bins t1 = (1);
}
endgroup
cg cg_inst = new;
initial $finish;
cg cg_inst = new;
initial $finish;
endmodule

View File

@ -0,0 +1,18 @@
#!/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

@ -7,73 +7,73 @@
// Test wildcard bins with don't care matching
module t;
/* verilator lint_off UNSIGNED */
bit [7:0] data;
/* verilator lint_off UNSIGNED */
bit [7:0] data;
covergroup cg;
coverpoint data {
// Match any value with upper nibble = 4'b0000
wildcard bins low = {8'b0000_????};
covergroup cg;
coverpoint data {
// Match any value with upper nibble = 4'b0000
wildcard bins low = {8'b0000_????};
// Match any value with upper nibble = 4'b1111
wildcard bins high = {8'b1111_????};
// Match any value with upper nibble = 4'b1111
wildcard bins high = {8'b1111_????};
// Match specific pattern with don't cares
wildcard bins pattern = {8'b10?0_11??};
}
endgroup
// Match specific pattern with don't cares
wildcard bins pattern = {8'b10?0_11??};
}
endgroup
initial begin
cg cg_inst;
real cov;
initial begin
cg cg_inst;
real cov;
cg_inst = new();
cg_inst = new();
// Test low bin (upper nibble = 0000)
data = 8'b0000_0101; // Should match 'low'
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After sample 1 (low): %0.2f%%", cov);
if (cov < 30.0 || cov > 35.0) begin
$error("Expected ~33.33%% (1/3 bins), got %0.2f%%", cov);
end
// Test high bin (upper nibble = 1111)
data = 8'b1111_1010; // Should match 'high'
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After sample 2 (high): %0.2f%%", cov);
if (cov < 63.0 || cov > 70.0) begin
$error("Expected ~66.67%% (2/3 bins), got %0.2f%%", cov);
end
// Test pattern bin (10?0_11??)
data = 8'b1000_1101; // Should match 'pattern' (10[0]0_11[0]1)
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After sample 3 (pattern): %0.2f%%", cov);
if (cov != 100.0) begin
$error("Expected 100%% (3/3 bins), got %0.2f%%", cov);
end
// Verify another pattern match
data = 8'b1010_1111; // Should also match 'pattern' (10[1]0_11[1]1)
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
if (cov != 100.0) begin
$error("Pattern should still be 100%%, got %0.2f%%", cov);
end
// Verify non-matching value doesn't change coverage
data = 8'b0101_0101; // Shouldn't match any bin
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
if (cov != 100.0) begin
$error("Non-matching value shouldn't change coverage, got %0.2f%%", cov);
end
$display("Wildcard bins test PASSED - final coverage: %0.2f%%", cov);
$write("*-* All Finished *-*\n");
$finish;
// Test low bin (upper nibble = 0000)
data = 8'b0000_0101; // Should match 'low'
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After sample 1 (low): %0.2f%%", cov);
if (cov < 30.0 || cov > 35.0) begin
$error("Expected ~33.33%% (1/3 bins), got %0.2f%%", cov);
end
// Test high bin (upper nibble = 1111)
data = 8'b1111_1010; // Should match 'high'
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After sample 2 (high): %0.2f%%", cov);
if (cov < 63.0 || cov > 70.0) begin
$error("Expected ~66.67%% (2/3 bins), got %0.2f%%", cov);
end
// Test pattern bin (10?0_11??)
data = 8'b1000_1101; // Should match 'pattern' (10[0]0_11[0]1)
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
$display("After sample 3 (pattern): %0.2f%%", cov);
if (cov != 100.0) begin
$error("Expected 100%% (3/3 bins), got %0.2f%%", cov);
end
// Verify another pattern match
data = 8'b1010_1111; // Should also match 'pattern' (10[1]0_11[1]1)
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
if (cov != 100.0) begin
$error("Pattern should still be 100%%, got %0.2f%%", cov);
end
// Verify non-matching value doesn't change coverage
data = 8'b0101_0101; // Shouldn't match any bin
cg_inst.sample();
cov = cg_inst.get_inst_coverage();
if (cov != 100.0) begin
$error("Non-matching value shouldn't change coverage, got %0.2f%%", cov);
end
$display("Wildcard bins test PASSED - final coverage: %0.2f%%", cov);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule