Fix covergroup '0/'1 bin values not filling to coverpoint width (#8458) (#8460)

This commit is contained in:
David Harris
2026-09-23 12:50:39 -04:00
committed by GitHub
parent e9a24647d8
commit a99ced0ed4
4 changed files with 93 additions and 10 deletions
+20 -10
View File
@@ -2115,39 +2115,49 @@ class WidthVisitor final : public VNVisitor {
// with a context so a bit/part-select (AstSel) is sized here; otherwise it would
// reach assertAtExpr() with m_vup==null and fail as an internal error.
userIterateAndNext(nodep->exprp(), WidthVP{SELF, BOTH}.p());
userIterateAndNext(nodep->binsp(), nullptr);
// Bin values compare against the coverpoint expression
userIterateAndNext(nodep->binsp(), WidthVP{nodep->exprp()->dtypep(), BOTH}.p());
if (nodep->iffp()) iterateCheckBool(nodep, "iff condition", nodep->iffp(), BOTH);
userIterateAndNext(nodep->optionsp(), nullptr);
}
void widthCovergroupRanges(AstNode* rangesp) {
void widthCovergroupRanges(AstNode* rangesp, int fillWidth) {
// Bin range/value entries are self-determined expressions (IEEE 1800-2023
// 19.5). Width each plain single-value entry self-determined so a referenced
// parameter acquires a dtype, then constify so the reference folds to the AstConst
// value that V3Covergroup requires. AstInsideRange entries fold their own bounds in
// visit(AstInsideRange).
// '0/'1 entries then fill to fillWidth, the coverpoint width (IEEE 1800-2023 19.5.7).
const auto fill = [&](AstNode* nodep) {
if (!fillWidth) return;
AstNodeExpr* exprp = VN_AS(nodep, NodeExpr);
fixAutoExtend(exprp /*ref*/, fillWidth);
};
for (AstNode *nextp, *itemp = rangesp; itemp; itemp = nextp) {
nextp = itemp->nextp();
if (VN_IS(itemp, InsideRange)) {
userIterate(itemp, nullptr);
if (AstInsideRange* const rangep = VN_CAST(itemp, InsideRange)) {
userIterate(rangep, nullptr);
fill(rangep->lhsp());
fill(rangep->rhsp());
} else {
itemp = userIterateSubtreeReturnEdits(itemp, WidthVP{SELF, BOTH}.p());
V3Const::constifyEdit(itemp);
fill(V3Const::constifyEdit(itemp));
}
}
}
void visit(AstCoverBinsof* nodep) override {
userIterateAndNext(nodep->pointp(), nullptr);
widthCovergroupRanges(nodep->rangesp());
widthCovergroupRanges(nodep->rangesp(), 0);
}
void visit(AstCoverBin* nodep) override {
widthCovergroupRanges(nodep->rangesp());
// No m_vup for a bin directly in a covergroup body (unsupported, already warned)
widthCovergroupRanges(nodep->rangesp(), m_vup ? m_vup->dtypep()->width() : 0);
if (nodep->iffp()) iterateCheckBool(nodep, "iff condition", nodep->iffp(), BOTH);
userIterateAndNext(nodep->arraySizep(), nullptr);
userIterateAndNext(nodep->transp(), nullptr);
userIterateAndNext(nodep->transp(), m_vup);
}
void visit(AstCoverTransSet* nodep) override { userIterateAndNext(nodep->itemsp(), nullptr); }
void visit(AstCoverTransSet* nodep) override { userIterateAndNext(nodep->itemsp(), m_vup); }
void visit(AstCoverTransItem* nodep) override {
userIterateAndNext(nodep->valuesp(), WidthVP{SELF, BOTH}.p());
widthCovergroupRanges(nodep->valuesp(), m_vup ? m_vup->dtypep()->width() : 0);
}
void visit(AstPow* nodep) override {
// Pow is special, output sign only depends on LHS sign, but
+12
View File
@@ -0,0 +1,12 @@
cg.cp_b8.hi: 1
cg.cp_b8.lo: 1
cg.cp_insn.one: 0
cg.cp_insn.ones: 1
cg.cp_insn.rise: 1
cg.cp_insn.zeros: 1
cg.cp_mode.m: 2
cg.cp_sb.m1: 2
cg.cx.m_x_one [cross]: 0
cg.cx.m_x_ones [cross]: 1
cg.cx.m_x_rise [cross]: 1
cg.cx.m_x_zeros [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)
+45
View File
@@ -0,0 +1,45 @@
// 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 that '0 and '1 bin values fill to the coverpoint width
module t;
bit [31:0] insn;
bit [7:0] b8;
bit [1:0] mode;
bit signed [7:0] sb;
covergroup cg;
cp_insn: coverpoint insn {
bins zeros = {'0};
bins ones = {'1};
bins one = {1};
bins rise = ('0 => '1);
}
cp_b8: coverpoint b8 {
bins hi = {[8'h80 : '1]};
bins lo = {['0 : 8'h7f]};
}
cp_sb: coverpoint sb {bins m1 = {'1};}
cp_mode: coverpoint mode {bins m = {3};}
cx: cross cp_mode, cp_insn;
endgroup
cg cg_i = new;
initial begin
mode = 3;
insn = 32'h0;
b8 = 8'h01;
sb = -1;
cg_i.sample();
insn = 32'hffff_ffff;
b8 = 8'hff;
cg_i.sample();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule