From feea221f3904052bfaf6fc778872c994cb79a2d2 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 4 Sep 2025 22:18:46 -0400 Subject: [PATCH] Fix COVERAGEIGN-ignored `get_inst_coverage` and other covergroup methods (#6383). --- Changes | 1 + src/V3Ast.h | 1 + src/V3AstNodes.cpp | 1 + src/V3Task.cpp | 2 +- src/verilog.y | 69 +++++++++++++++---- test_regress/t/t_covergroup_args.v | 37 +++++++--- test_regress/t/t_covergroup_in_class.v | 15 ++-- .../t/t_covergroup_in_class_colliding.v | 30 ++++---- 8 files changed, 113 insertions(+), 43 deletions(-) diff --git a/Changes b/Changes index ebcdcea2a..ee47f384a 100644 --- a/Changes +++ b/Changes @@ -18,6 +18,7 @@ Verilator 5.041 devel * Fix cmake APPLE variable (#6351). [Lan Zongwei] * Fix randomize local after parameters applied (#6371). [Alex Solomatnikov] * Fix package imports not found after parameters applied (#6373). [Alex Solomatnikov] +* Fix COVERAGEIGN-ignored `get_inst_coverage` and other covergroup methods (#6383). [Alex Solomatnikov] Verilator 5.040 2025-08-30 diff --git a/src/V3Ast.h b/src/V3Ast.h index 8421db2fb..88d295549 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -2411,6 +2411,7 @@ public: // Data type locators AstNodeDType* findBitDType() const { return findBasicDType(VBasicDTypeKwd::LOGIC); } AstNodeDType* findDoubleDType() const { return findBasicDType(VBasicDTypeKwd::DOUBLE); } + AstNodeDType* findIntDType() const { return findBasicDType(VBasicDTypeKwd::INT); } AstNodeDType* findStringDType() const { return findBasicDType(VBasicDTypeKwd::STRING); } AstNodeDType* findSigned8DType() const { return findBasicDType(VBasicDTypeKwd::BYTE); } AstNodeDType* findSigned32DType() const { return findBasicDType(VBasicDTypeKwd::INTEGER); } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index c07b28c47..b7a2507fc 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -2865,6 +2865,7 @@ void AstNodeFTask::dump(std::ostream& str) const { if (pureVirtual()) str << " [PUREVIRTUAL]"; if (recursive()) str << " [RECURSIVE]"; if (taskPublic()) str << " [PUBLIC]"; + if (isStatic()) str << " [STATIC]"; if ((dpiImport() || dpiExport()) && cname() != name()) str << " [c=" << cname() << "]"; } bool AstNodeFTask::isPure() { diff --git a/src/V3Task.cpp b/src/V3Task.cpp index df587935e..07f569a2b 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1870,7 +1870,7 @@ AstNodeFTask* V3Task::taskConnectWrapNew(AstNodeFTask* taskp, const string& newn AstNode* newCallInsertp = nullptr; if (VN_IS(taskp, Func)) { AstVar* const fvarp = VN_AS(taskp->fvarp(), Var); - UASSERT(fvarp, "FuncRef without fvar"); + UASSERT_OBJ(fvarp, taskp, "FuncRef without fvar"); AstVar* const newFVarp = fvarp->cloneTree(true); oldNewVars.emplace(fvarp, newFVarp); newFVarp->name(newTaskp->name()); diff --git a/src/verilog.y b/src/verilog.y index 29e18999c..f2f11e294 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -147,6 +147,61 @@ public: nodep->trace(GRAMMARP->allTracingOn(fileline)); return nodep; } + void createCoverGroupMethods(AstClass* nodep) { + // Hidden static to take unspecified reference argument results + AstVar* const defaultVarp + = new AstVar{nodep->fileline(), VVarType::MEMBER, "__Vint", nodep->findIntDType()}; + defaultVarp->lifetime(VLifetime::STATIC); + nodep->addStmtsp(defaultVarp); + // IEEE: function void sample(), void start(), void stop() + for (const string& name : {"sample"s, "start"s, "stop"s}) { + AstFunc* const funcp = new AstFunc{nodep->fileline(), name, nullptr, nullptr}; + funcp->classMethod(true); + funcp->dtypep(funcp->findVoidDType()); + nodep->addMembersp(funcp); + } + // IEEE: static function real get_coverage(optional ref int, optional ref int) + // IEEE: function real get_inst_coverage(optional ref int, optional ref int) + for (const string& name : {"get_coverage"s, "get_inst_coverage"s}) { + AstFunc* const funcp = new AstFunc{nodep->fileline(), name, nullptr, nullptr}; + funcp->isStatic(name == "get_coverage"); + funcp->classMethod(true); + funcp->dtypep(funcp->findVoidDType()); + nodep->addMembersp(funcp); + { + AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, name, + nodep->findDoubleDType()}; + varp->lifetime(VLifetime::AUTOMATIC); + varp->funcLocal(true); + varp->direction(VDirection::OUTPUT); + varp->funcReturn(true); + funcp->fvarp(varp); + } + for (const string& varname : {"covered_bins"s, "total_bins"s}) { + AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, varname, + nodep->findStringDType()}; + varp->lifetime(VLifetime::AUTOMATIC); + varp->funcLocal(true); + varp->direction(VDirection::INPUT); + varp->valuep(new AstVarRef{nodep->fileline(), defaultVarp, VAccess::READ}); + funcp->addStmtsp(varp); + } + } + // IEEE: function void set_inst_name(string) + { + AstFunc* const funcp + = new AstFunc{nodep->fileline(), "set_inst_name", nullptr, nullptr}; + funcp->classMethod(true); + funcp->dtypep(funcp->findVoidDType()); + nodep->addMembersp(funcp); + AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, "name", + nodep->findStringDType()}; + varp->lifetime(VLifetime::AUTOMATIC); + varp->funcLocal(true); + varp->direction(VDirection::INPUT); + funcp->addStmtsp(varp); + } + } AstDisplay* createDisplayError(FileLine* fileline) { AstDisplay* nodep = new AstDisplay{fileline, VDisplayType::DT_ERROR, "", nullptr, nullptr}; AstNode::addNext(nodep, new AstStop{fileline, false}); @@ -6915,19 +6970,9 @@ covergroup_extendsE: // IEEE: Part of covergroup_declaration covergroup_declarationFront: // IEEE: part of covergroup_declaration yCOVERGROUP covergroup_extendsE idAny { + BBCOVERIGN($1, "Ignoring unsupported: covergroup"); $$ = new AstClass{$3, *$3, PARSEP->libname()}; - - AstFunc* const sample = new AstFunc{$1, "sample", nullptr, nullptr}; - sample->classMethod(true); - sample->dtypep(sample->findVoidDType()); - $$->addMembersp(sample); - - AstFunc* const getCoverage = new AstFunc{$1, "get_coverage", nullptr, nullptr}; - getCoverage->classMethod(true); - getCoverage->dtypep(getCoverage->findVoidDType()); - $$->addMembersp(getCoverage); - - BBCOVERIGN($1, "Ignoring unsupported: covergroup"); } + GRAMMARP->createCoverGroupMethods($$); } ; cgexpr: // IEEE-2012: covergroup_expression, before that just expression diff --git a/test_regress/t/t_covergroup_args.v b/test_regress/t/t_covergroup_args.v index fdd1eb144..d72b9c23f 100644 --- a/test_regress/t/t_covergroup_args.v +++ b/test_regress/t/t_covergroup_args.v @@ -4,16 +4,35 @@ // any use, without warranty, 2025 by Antmicro. // SPDX-License-Identifier: CC0-1.0 -/* verilator lint_off COVERIGN */ +// verilator lint_off COVERIGN module t; - covergroup cgArgs(int var1, int var2=42); - endgroup + covergroup cg(int var1, int var2 = 42); + endgroup + + cg cov1 = new(69, 77); + cg cov2 = new(69); + + int i, j; + real r; + + function x(); + cov1.set_inst_name("the_inst_name"); + cov1.start(); + cov1.sample(); + cov1.stop(); + + void'(cov2.get_coverage()); + r = cov2.get_coverage(); + r = cov2.get_coverage(i, j); + // verilator lint_off IGNOREDRETURN + cov2.get_inst_coverage(); + // verilator lint_on IGNOREDRETURN + r = cov2.get_inst_coverage(i, j); + + cg::get_coverage(); + r = cg::get_coverage(); + r = cg::get_coverage(i, j); + endfunction - cgArgs cov1 = new(69, 77); - cgArgs cov2 = new(69); - function x(); - cov1.sample(); - cov2.get_coverage(); - endfunction; endmodule diff --git a/test_regress/t/t_covergroup_in_class.v b/test_regress/t/t_covergroup_in_class.v index a08670322..5fe57773d 100644 --- a/test_regress/t/t_covergroup_in_class.v +++ b/test_regress/t/t_covergroup_in_class.v @@ -6,13 +6,14 @@ /* verilator lint_off COVERIGN */ class myClass; - covergroup embeddedCg; + covergroup embeddedCg; - endgroup + endgroup - function new(); - embeddedCg = new(); - embeddedCg.sample(); - embeddedCg.get_coverage(); - endfunction + function new(); + real r; + embeddedCg = new(); + embeddedCg.sample(); + r = embeddedCg.get_coverage(); + endfunction endclass diff --git a/test_regress/t/t_covergroup_in_class_colliding.v b/test_regress/t/t_covergroup_in_class_colliding.v index acd931744..1d9225f08 100644 --- a/test_regress/t/t_covergroup_in_class_colliding.v +++ b/test_regress/t/t_covergroup_in_class_colliding.v @@ -6,25 +6,27 @@ /* verilator lint_off COVERIGN */ class myClass; - covergroup embeddedCg; + covergroup embeddedCg; - endgroup + endgroup - function new(); - embeddedCg = new(); - embeddedCg.sample(); - embeddedCg.get_coverage(); - endfunction + function new(); + real r; + embeddedCg = new(); + embeddedCg.sample(); + r = embeddedCg.get_coverage(); + endfunction endclass class secondClass; - covergroup embeddedCg; + covergroup embeddedCg; - endgroup + endgroup - function new(); - embeddedCg = new(); - embeddedCg.sample(); - embeddedCg.get_coverage(); - endfunction + function new(); + real r; + embeddedCg = new(); + embeddedCg.sample(); + r = embeddedCg.get_coverage(); + endfunction endclass