Support automatic bins for enum coverpoints (#8462) (#8464)

This commit is contained in:
David Harris
2026-09-24 09:58:22 -04:00
committed by GitHub
parent 976ec63531
commit 88082a4e96
4 changed files with 110 additions and 0 deletions
+19
View File
@@ -493,12 +493,31 @@ class FunctionalCoverageVisitor final : public VNVisitor {
}
// IEEE 1800-2023 19.5.3/19.11.1: partition first, then apply exclusions.
// IEEE 1800-2023 19.5.2: an enum coverpoint has one automatic bin per enumeration value
void createEnumAutoBins(AstCoverpoint* coverpointp, AstNodeExpr* exprp,
const AstEnumDType* enump) {
FileLine* const fl = coverpointp->fileline();
for (const AstEnumItem* itemp = enump->itemsp(); itemp;
itemp = VN_AS(itemp->nextp(), EnumItem)) {
AstConst* const lop = newValueConst(fl, VN_AS(itemp->valuep(), Const)->num(), exprp);
AstInsideRange* const rangep = new AstInsideRange{fl, lop, lop->cloneTree(false)};
rangep->dtypeFrom(exprp);
coverpointp->addBinsp(
new AstCoverBin{fl, "auto[" + itemp->name() + "]", rangep, false, false});
}
}
void createImplicitAutoBins(AstCoverpoint* coverpointp, AstNodeExpr* exprp, int autoBinMax) {
for (AstNode* nodep = coverpointp->binsp(); nodep; nodep = nodep->nextp()) {
const VCoverBinsType kind = VN_AS(nodep, CoverBin)->binsType();
if (kind != VCoverBinsType::BINS_IGNORE && kind != VCoverBinsType::BINS_ILLEGAL)
return;
}
if (const AstEnumDType* const enump
= VN_CAST(exprp->dtypep()->skipRefToEnump(), EnumDType)) {
createEnumAutoBins(coverpointp, exprp, enump);
return;
}
const int width = exprp->width();
const int arithmeticWidth = width + 1;
V3Number total{coverpointp, arithmeticWidth};
@@ -0,0 +1,20 @@
cg.cp_call.auto[A]: 0
cg.cp_call.auto[B]: 0
cg.cp_call.auto[C]: 2
cg.cp_max.auto[A]: 0
cg.cp_max.auto[B]: 1
cg.cp_max.auto[C]: 1
cg.cp_var.auto[A]: 0
cg.cp_var.auto[B]: 1
cg.cp_var.auto[C]: 1
cg.cp_wide.auto[E01]: 0
cg.cp_wide.auto[ELARGE]: 1
cg.cx.auto[A]_x_auto[A] [cross]: 0
cg.cx.auto[A]_x_auto[B] [cross]: 0
cg.cx.auto[A]_x_auto[C] [cross]: 0
cg.cx.auto[B]_x_auto[A] [cross]: 0
cg.cx.auto[B]_x_auto[B] [cross]: 0
cg.cx.auto[B]_x_auto[C] [cross]: 1
cg.cx.auto[C]_x_auto[A] [cross]: 0
cg.cx.auto[C]_x_auto[B] [cross]: 0
cg.cx.auto[C]_x_auto[C] [cross]: 1
+16
View File
@@ -0,0 +1,16 @@
#!/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
import coverage_covergroup_common
test.scenarios('vlt_all')
coverage_covergroup_common.run(test)
@@ -0,0 +1,55 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain
// SPDX-FileCopyrightText: 2026 David Harris
// SPDX-License-Identifier: CC0-1.0
// Test automatic bins of an enum coverpoint: one bin per enumeration value
typedef enum logic [2:0] {
A = 3'd5,
B = 3'd1,
C = 3'd7
} e_t;
typedef enum logic [59:0] {
E01 = 60'h1,
ELARGE = 60'h1234_4567_abcd
} wide_t;
class Item;
e_t e;
function e_t get_e();
return e;
endfunction
endclass
module t;
e_t v;
wide_t w;
covergroup cg with function sample(Item item);
cp_var: coverpoint v;
cp_call: coverpoint item.get_e();
cp_max: coverpoint v {option.auto_bin_max = 2;}
cx: cross cp_var, cp_call;
cp_wide: coverpoint w;
endgroup
cg cg_i = new;
initial begin
Item item;
item = new;
v = B;
item.e = C;
w = ELARGE;
cg_i.sample(item);
v = C;
item.e = C;
w = wide_t'(60'h1_0000_0001); // not an enum value; aliases E01 in the low 32 bits
cg_i.sample(item);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule