Support covergroups, coverpoints, and bins (#784) (#7117)

Fixes #784.
This commit is contained in:
Matthew Ballance
2026-06-05 09:35:01 -04:00
committed by GitHub
parent 7e2fe64ae2
commit 2886291eba
163 changed files with 7575 additions and 1123 deletions
+77
View File
@@ -307,6 +307,72 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
void visit(AstCoverInc*) override {} // N/A
void visit(AstCoverToggle*) override {} // N/A
void visit(AstCovergroup* nodep) override {
// AstCovergroup appears as a member inside the lowered AstClass body.
// The outer covergroup/endcovergroup wrapper is already emitted by the
// AstNodeModule visitor (verilogKwd()="covergroup" on AstClass::isCovergroup).
// Here we only emit the clocking event, if any.
if (nodep->eventp()) {
putfs(nodep, "");
iterateConst(nodep->eventp());
}
}
void visit(AstCoverpoint* nodep) override {
putfs(nodep, nodep->name() + ": coverpoint ");
iterateAndNextConstNull(nodep->exprp());
if (nodep->binsp() || nodep->optionsp()) {
puts(" {\n");
iterateAndNextConstNull(nodep->optionsp());
iterateAndNextConstNull(nodep->binsp());
puts("}");
}
puts(";\n");
}
void visit(AstCoverBin* nodep) override {
switch (nodep->binsType()) {
case VCoverBinsType::BINS_IGNORE: putfs(nodep, "ignore_bins "); break;
case VCoverBinsType::BINS_ILLEGAL: putfs(nodep, "illegal_bins "); break;
default: putfs(nodep, "bins "); break;
}
puts(nodep->name());
if (nodep->binsType() == VCoverBinsType::BINS_DEFAULT) {
puts(" = default");
} else if (nodep->transp()) {
puts(" = ");
for (AstNode* setp = nodep->transp(); setp; setp = setp->nextp()) {
if (setp != nodep->transp()) puts(", ");
iterateConst(setp);
}
} else if (nodep->rangesp()) { // LCOV_EXCL_BR_LINE - false: CoverBin always has
// transp/rangesp/default
puts(" = {");
for (AstNode* rangep = nodep->rangesp(); rangep; rangep = rangep->nextp()) {
if (rangep != nodep->rangesp()) puts(", ");
iterateConst(rangep);
}
puts("}");
}
puts(";\n");
}
void visit(AstCoverpointRef* nodep) override { putfs(nodep, nodep->name()); }
void visit(AstCoverCross* nodep) override {
putfs(nodep, nodep->name() + ": cross ");
for (AstNode* itemp = nodep->itemsp(); itemp; itemp = itemp->nextp()) {
if (itemp != nodep->itemsp()) puts(", ");
iterateConst(itemp);
}
puts(";\n");
}
void visit(AstCoverTransSet* nodep) override {
puts("(");
for (AstNode* itemp = nodep->itemsp(); itemp; itemp = itemp->nextp()) {
if (itemp != nodep->itemsp()) puts(" => ");
iterateConst(itemp);
}
puts(")");
}
void visit(AstCoverTransItem* nodep) override { iterateChildrenConst(nodep); }
void visit(AstCvtPackString* nodep) override {
putfs(nodep, "");
if (AstConst* const lhsConstp = VN_CAST(nodep->lhsp(), Const)) {
@@ -745,6 +811,13 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
iterateAndNextConstNull(nodep->elsep());
puts(")");
}
void visit(AstInsideRange* nodep) override {
puts("[");
iterateAndNextConstNull(nodep->lhsp());
puts(":");
iterateAndNextConstNull(nodep->rhsp());
puts("]");
}
void visit(AstRange* nodep) override {
puts("[");
if (VN_IS(nodep->leftp(), Const) && VN_IS(nodep->rightp(), Const)) {
@@ -942,6 +1015,10 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
puts("\n???? // "s + nodep->prettyTypeName() + " -> UNLINKED\n");
}
}
void visit(AstClassRefDType* nodep) override {
UASSERT_OBJ(nodep->classp(), nodep, "AstClassRefDType not linked");
putfs(nodep, EmitCUtil::prefixNameProtect(nodep->classp()));
}
void visit(AstRequireDType* nodep) override { iterateConst(nodep->lhsp()); }
void visit(AstModport* nodep) override {
puts(nodep->verilogKwd());