diff --git a/include/verilated_covergroup.cpp b/include/verilated_covergroup.cpp index f7cb3b6ae..3011fce77 100644 --- a/include/verilated_covergroup.cpp +++ b/include/verilated_covergroup.cpp @@ -134,6 +134,27 @@ void VlCoverCross::init(const char* hier, uint32_t dims, VlCoverpoint* const* cp m_flatCounts.assign(m_numAutoBins, 0); } +void VlCoverCross::addBin(uint32_t dim, uint32_t first, uint32_t bins, const char* namep, + const char* filep, int line, int col) { + if (!m_numAutoBins) return; // An empty product creates no cross bin. + if (m_bins.empty()) m_autoExcluded.assign(m_numAutoBins, false); + m_bins.emplace_back(dim, first, bins, namep, filep, line, col); + // Visit only selected tuples. Multiple explicit bins may select the same tuple. + const uint64_t stride = m_stride[dim]; + const uint64_t period = stride * m_cpBinCounts[dim]; + for (uint64_t base = first * stride; base < m_numAutoBins; base += period) { + for (uint64_t flat = base; flat < base + bins * stride; ++flat) { + m_autoExcluded[flat] = true; + } + } +} + +void VlCoverCross::finalizeBins() { + for (uint32_t flat = 0; flat < m_numAutoBins; ++flat) { + if (!m_autoExcluded[flat]) m_autoBins.push_back(flat); + } +} + void VlCoverCross::iterateProduct(VlCoverpoint* const* cps, uint32_t dim, uint32_t baseIdx) { const uint32_t hits = cps[dim]->hitCount(); const uint32_t* const list = cps[dim]->hitList(); @@ -149,15 +170,31 @@ void VlCoverCross::iterateProduct(VlCoverpoint* const* cps, uint32_t dim, uint32 } } -void VlCoverCross::sample(VlCoverpoint* const* cps) { +void VlCoverCross::sample(VlCoverpoint* const* cps, const bool* binIffs) { // Fast path: if any dimension had no Normal-bin hit, the cross cannot hit. for (uint32_t d = 0; d < m_dims; ++d) { if (cps[d]->hitCount() == 0) return; } + for (Bin& bin : m_bins) { + if (binIffs && !*binIffs++) continue; + const VlCoverpoint* const cpp = cps[bin.dim]; + for (uint32_t hit = 0; hit < cpp->hitCount(); ++hit) { + const uint32_t idx = cpp->hitList()[hit]; + if (idx >= bin.first && idx - bin.first < bin.bins) { + if (bin.count++ == 0) ++m_numCovered; + break; + } + } + } iterateProduct(cps, 0, 0); } -std::string VlCoverCross::binName(uint32_t flat) const { +std::string VlCoverCross::binName(uint32_t i) const { + if (i < m_bins.size()) return m_bins[i].namep; + return autoBinName(autoIndex(i - static_cast(m_bins.size()))); +} + +std::string VlCoverCross::autoBinName(uint32_t flat) const { // Built on demand by concatenating each coverpoint's own bin name. std::string name; for (uint32_t d = 0; d < m_dims; ++d) { @@ -170,12 +207,23 @@ std::string VlCoverCross::binName(uint32_t flat) const { #if VM_COVERAGE void VlCoverCross::registerBins(VerilatedCovContext* covcontextp, const char* page) { - // Register every auto cross bin (zero-count bins included), so the report - // shows the full Cartesian product of cross bins. Names are built on the fly. const std::string lineStr = std::to_string(m_line); const std::string colStr = std::to_string(m_col); - for (uint32_t flat = 0; flat < binCount(); ++flat) { - const std::string bin = binName(flat); // "b1_x_b2_x_..." + const uint32_t explicitCount = static_cast(m_bins.size()); + // Use the same indexed names for registration and the runtime read interface. + for (uint32_t i = 0; i < binCount(); ++i) { + const std::string bin = binName(i); + const std::string full = m_hier + "." + bin; + if (i < explicitCount) { + Bin& userBin = m_bins[i]; + const std::string binLineStr = std::to_string(userBin.line); + const std::string binColStr = std::to_string(userBin.col); + VL_COVER_INSERT(covcontextp, full.c_str(), &userBin.count, "page", page, "filename", + userBin.filep, "lineno", binLineStr.c_str(), "column", + binColStr.c_str(), "bin", bin.c_str(), "cross", "1"); + continue; + } + const uint32_t flat = autoIndex(i - explicitCount); // cross_bins metadata: the same components joined by ',' (not read by the report) std::string crossBins; for (uint32_t d = 0; d < m_dims; ++d) { @@ -183,7 +231,6 @@ void VlCoverCross::registerBins(VerilatedCovContext* covcontextp, const char* pa if (d > 0) crossBins += ","; crossBins += m_cps[d]->normalBinName(crossIdx); } - const std::string full = m_hier + "." + bin; VL_COVER_INSERT(covcontextp, full.c_str(), &m_flatCounts[flat], "page", page, "filename", m_file, "lineno", lineStr.c_str(), "column", colStr.c_str(), "bin", bin.c_str(), "cross", "1", "cross_bins", crossBins.c_str()); diff --git a/include/verilated_covergroup.h b/include/verilated_covergroup.h index 9c1825daf..ec0211a95 100644 --- a/include/verilated_covergroup.h +++ b/include/verilated_covergroup.h @@ -202,12 +202,34 @@ public: //============================================================================= // VlCoverCross -/// Per-instance auto cross runtime. Holds flat uint32_t[] storage over the +/// Per-instance cross runtime. Holds flat uint32_t[] storage over the /// Cartesian product of the feeding coverpoints' Normal bins. Each sample() /// walks the coverpoint hit lists (O(hits), not O(product)). Bin names are -/// built on demand from the coverpoints, so no per-bin name is stored. +/// built on demand for automatic bins; explicit bins select a Normal-bin span +/// in one dimension and replace the corresponding automatic cross bins. class VlCoverCross final : public VlCoverpointIf { + struct Bin final { + const uint32_t dim; // Selected coverpoint dimension + const uint32_t first; // First selected Normal bin index + const uint32_t bins; // Number of selected Normal bins + const char* const namep; // Explicit bin name + const char* const filep; // Bin declaration file + const int line; // Bin declaration line + const int col; // Bin declaration column + uint32_t count = 0; // Samples matching the selection and guard + + Bin(uint32_t dim, uint32_t first, uint32_t bins, const char* namep, const char* filep, + int line, int col) + : dim{dim} + , first{first} + , bins{bins} + , namep{namep} + , filep{filep} + , line{line} + , col{col} {} + }; + // MEMBERS std::string m_hier; // "covergroup.cross" const char* m_file = nullptr; // Cross declaration file (registration metadata) @@ -223,13 +245,20 @@ class VlCoverCross final : public VlCoverpointIf { std::vector m_cpBinCounts; // [m_dims] Normal bin count per dimension std::vector m_stride; // [m_dims] Flat-index stride per dimension std::vector m_flatCounts; // [m_numAutoBins] Per-bin hit counts - std::vector m_cps; // Feeding coverpoints (the only name source) + std::vector m_cps; // Feeding coverpoints (automatic-bin name source) + std::vector m_bins; // Explicit bins in declaration order + std::vector + m_autoExcluded; // Tuples replaced by explicit bins; empty for auto-only crosses + std::vector m_autoBins; // Retained flat indices, when explicit bins are present // PRIVATE METHODS void iterateProduct(VlCoverpoint* const* cps, uint32_t dim, uint32_t baseIdx); void incrementTuple(uint32_t idx) { + if (!m_autoExcluded.empty() && m_autoExcluded[idx]) return; if (m_flatCounts[idx]++ == 0) ++m_numCovered; } + uint32_t autoIndex(uint32_t i) const { return m_bins.empty() ? i : m_autoBins[i]; } + std::string autoBinName(uint32_t flat) const; public: // CONSTRUCTORS @@ -239,18 +268,27 @@ public: // ---- configuration (from generated constructor, after coverpoints init'd) ---- void init(const char* hier, uint32_t dims, VlCoverpoint* const* cps, const char* file, int line, int col); + /// Add a single-binsof cross bin using verilation-time resolved Normal-bin indices. + void addBin(uint32_t dim, uint32_t first, uint32_t bins, const char* namep, const char* filep, + int line, int col); + /// Retain only automatic cross bins not selected by any explicit bin. + void finalizeBins(); void registerBins(VerilatedCovContext* covcontextp, const char* page); // ---- hot path (from generated sample(), after all coverpoints sampled) ---- - void sample(VlCoverpoint* const* cps); + /// Sample automatic and explicit bins, optionally applying per-bin iff guards. + void sample(VlCoverpoint* const* cps, const bool* binIffs = nullptr); // ---- VlCoverpointIf ---- - // A cross is a coverpoint whose bins are the auto cross bins (all Normal). - uint32_t binCount() const override { return m_numAutoBins; } - std::string binName(uint32_t flat) const override; + // Explicit bins precede retained automatic bins; all are Normal bins. + uint32_t binCount() const override { + return m_bins.empty() ? m_numAutoBins + : static_cast(m_bins.size() + m_autoBins.size()); + } + std::string binName(uint32_t i) const override; void coverageParts(double& covered, double& total) const override { covered = m_numCovered; - total = m_numAutoBins; + total = binCount(); } }; diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 1c847cf26..949bbc2a7 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -1097,6 +1097,36 @@ public: bool isArray() const { return m_isArray; } void isArray(bool flag) { m_isArray = flag; } }; +class AstCoverBinsof final : public AstNode { + // A binsof selection of a coverpoint or one of its named bins + // @astgen op1 := pointp : AstCoverpointRef + string m_name; // Selected bin name, or empty for all bins of the coverpoint + +public: + AstCoverBinsof(FileLine* fl, AstCoverpointRef* pointp) + : ASTGEN_SUPER_CoverBinsof(fl) { + this->pointp(pointp); + } + ASTGEN_MEMBERS_AstCoverBinsof; + string name() const override VL_MT_STABLE { return m_name; } + void name(const string& name) override { m_name = name; } +}; +class AstCoverCrossBin final : public AstNode { + // A named cross bin and its selection expression + // @astgen op1 := selectp : Optional[AstNode] // Null for unsupported selections + // @astgen op2 := iffp : Optional[AstNodeExpr] + const string m_name; // Declared cross bin name + +public: + AstCoverCrossBin(FileLine* fl, const string& name, AstNode* selectp, AstNodeExpr* iffp) + : ASTGEN_SUPER_CoverCrossBin(fl) + , m_name{name} { + this->selectp(selectp); + this->iffp(iffp); + } + ASTGEN_MEMBERS_AstCoverCrossBin; + string name() const override VL_MT_STABLE { return m_name; } +}; class AstCoverOption final : public AstNode { // Coverage-option assignment // @astgen op1 := valuep : AstNodeExpr @@ -2807,8 +2837,8 @@ public: class AstCoverCross final : public AstNodeFuncCovItem { // @astgen op1 := itemsp : List[AstCoverpointRef] // @astgen op2 := optionsp : List[AstCoverOption] // post-LinkParse only - // @astgen op3 := rawBodyp : List[AstNode] // Parse: raw cross_body items; - // // post-LinkParse: empty + // @astgen op3 := binsp : List[AstNode] // Parse: mixed cross bins/options; + // // post-LinkParse: AstCoverCrossBin only // @astgen op4 := iffp : Optional[AstNodeExpr] // Conditional sampling guard public: AstCoverCross(FileLine* fl, const string& name, AstCoverpointRef* itemsp, diff --git a/src/V3Covergroup.cpp b/src/V3Covergroup.cpp index 77bb9d1fb..c04b3eb78 100644 --- a/src/V3Covergroup.cpp +++ b/src/V3Covergroup.cpp @@ -31,6 +31,7 @@ #include "V3MemberMap.h" #include +#include #include VL_DEFINE_DEBUG_FUNCTIONS; @@ -66,8 +67,13 @@ class CovergroupExprValidVisitor final : public VNVisitor { } void visit(AstCoverCross* nodep) override { iterateAndNextNull(nodep->itemsp()); + scanSampleExpression(nodep->iffp()); iterateAndNextNull(nodep->optionsp()); - iterateAndNextNull(nodep->rawBodyp()); + iterateAndNextNull(nodep->binsp()); + } + void visit(AstCoverCrossBin* nodep) override { + iterateAndNextNull(nodep->selectp()); + scanSampleExpression(nodep->iffp()); } void visit(AstCoverBin* nodep) override { scanCoverageExpression(nodep->rangesp()); @@ -156,6 +162,12 @@ class FunctionalCoverageVisitor final : public VNVisitor { std::vector m_cpVars; // VlCoverpoint member, one per coverpoint std::vector m_crossVars; // VlCoverCross member, one per cross std::map m_cpVarMap; // Coverpoint name -> its VlCoverpoint member + struct CoverpointBins final { + uint32_t total = 0; // Number of Normal bins + std::unordered_map> + spans; // Declared bin name -> first Normal index and number of bins + }; + std::map m_cpBins; // Runtime coverpoint -> binsof index ranges std::set m_droppedCrosses; // Crosses with a bare-variable item: drop (COVERIGN) std::map m_vlCoverpointTypes; // hit-list bound K -> "VlCoverpointT" type @@ -173,6 +185,7 @@ class FunctionalCoverageVisitor final : public VNVisitor { m_cpVars.clear(); m_crossVars.clear(); m_cpVarMap.clear(); + m_cpBins.clear(); m_droppedCrosses.clear(); // Scan every cross item to record the coverpoints it references (the cross dimensions) @@ -845,6 +858,11 @@ class FunctionalCoverageVisitor final : public VNVisitor { // Emit a 'this->m_cp.addSingleNamer/addArrayNamer(...)' statement for one bin AstCStmt* makeNamer(AstVar* cpVarp, AstCoverBin* binp, int count) { FileLine* const fl = binp->fileline(); + CoverpointBins& bins = m_cpBins.at(cpVarp); + const uint32_t normalCount + = binp->binsType().binIsNormal() ? static_cast(count < 0 ? 1 : count) : 0; + bins.spans.emplace(binp->name(), std::make_pair(bins.total, normalCount)); + bins.total += normalCount; AstCStmt* const cs = new AstCStmt{fl}; cs->add(memberRef(fl, cpVarp)); // Under --protect-ids the filename and bin name flow into the coverage database @@ -936,6 +954,7 @@ class FunctionalCoverageVisitor final : public VNVisitor { m_covergroupp->addMembersp(cpVarp); m_cpVars.push_back(cpVarp); m_cpVarMap[coverpointp->name()] = cpVarp; + m_cpBins.emplace(cpVarp, CoverpointBins{}); // A cross reads this coverpoint's hit list, so clear it at the start of the // coverpoint's sample() contribution (before any incrementBin appends to it). @@ -1304,12 +1323,27 @@ class FunctionalCoverageVisitor final : public VNVisitor { // Append a "{ VlCoverpoint* __Vcx_cps[] = {&cp0, &cp1, ...}; . }" statement. AstCStmt* makeCrossCpsCall(FileLine* fl, const std::vector& cpVars, AstVar* cxVarp, - const std::string& callText) { + const std::string& callText, + const std::vector& bins = {}) { AstCStmt* const cs = new AstCStmt{fl}; - cs->add("{ VlCoverpoint* __Vcx_cps[] = {"); - for (size_t d = 0; d < cpVars.size(); ++d) { - cs->add(d == 0 ? "&" : ", &"); - cs->add(memberRef(fl, cpVars[d])); + cs->add("{ "); + if (!bins.empty()) { + cs->add("const bool __Vcx_iffs[] = {"); + bool first = true; + for (const AstCoverCrossBin* const binp : bins) { + if (!first) cs->add(", "); + first = false; + cs->add(binp->iffp() ? binp->iffp()->cloneTree(false) + : new AstConst{fl, AstConst::BitTrue{}}); + } + cs->add("}; "); + } + cs->add("VlCoverpoint* __Vcx_cps[] = {"); + bool first = true; + for (AstVar* const cpVarp : cpVars) { + cs->add(first ? "&" : ", &"); + first = false; + cs->add(memberRef(fl, cpVarp)); } cs->add("}; "); cs->add(memberRef(fl, cxVarp)); @@ -1318,9 +1352,72 @@ class FunctionalCoverageVisitor final : public VNVisitor { return cs; } + std::vector + generateCrossBins(AstCoverCross* crossp, AstVar* cxVarp, const std::vector& cpVars, + const std::map& dimensions) { + std::vector bins; + std::set names; + for (AstNode* itemp = crossp->binsp(); itemp; itemp = itemp->nextp()) { + AstCoverCrossBin* const binp = VN_AS(itemp, CoverCrossBin); + if (!names.emplace(binp->name()).second) { + binp->v3error("Duplicate cross bin " << binp->prettyNameQ() + << " (IEEE 1800-2012 19.6.1)."); + continue; + } + const AstCoverBinsof* const selectp = VN_AS(binp->selectp(), CoverBinsof); + const auto dimIt = dimensions.find(selectp->pointp()->name()); + if (dimIt == dimensions.end()) { + selectp->v3error("binsof coverpoint " + << selectp->pointp()->prettyNameQ() << " is not an item of cross " + << crossp->prettyNameQ() << " (IEEE 1800-2012 19.6.1)."); + continue; + } + const uint32_t dim = dimIt->second; + const CoverpointBins& cpBins = m_cpBins.at(cpVars[dim]); + uint32_t first = 0; + uint32_t count = cpBins.total; + if (!selectp->name().empty()) { + const auto binIt = cpBins.spans.find(selectp->name()); + if (binIt == cpBins.spans.end()) { + selectp->v3error("Cannot find bin " << selectp->prettyNameQ() + << " in coverpoint " + << selectp->pointp()->prettyNameQ() + << " (IEEE 1800-2012 19.6.1)."); + continue; + } + first = binIt->second.first; + count = binIt->second.second; + } + // IEEE 1800-2012 19.6 excludes default, ignored and illegal coverpoint bins + // from cross products. An empty selection is valid, not an unsupported construct. + if (!count) continue; + FileLine* const fl = binp->fileline(); + const bool prot = v3Global.opt.protectIds(); + const std::string name = V3OutFormatter::quoteNameControls( + VIdProtect::protectWordsIf(binp->name(), prot)); + const std::string file + = V3OutFormatter::quoteNameControls(VIdProtect::protectIf(fl->filename(), prot)); + AstCStmt* const addp = new AstCStmt{fl}; + addp->add(memberRef(fl, cxVarp)); + addp->add(".addBin(" + std::to_string(dim) + ", " + std::to_string(first) + ", " + + std::to_string(count) + ", \"" + name + "\", \"" + file + "\", " + + std::to_string(fl->lineno()) + ", " + std::to_string(fl->firstColumn()) + + ");"); + m_constructorp->addStmtsp(addp); + bins.push_back(binp); + } + if (!bins.empty()) { + AstCStmt* const finishp = new AstCStmt{crossp->fileline()}; + finishp->add(memberRef(crossp->fileline(), cxVarp)); + finishp->add(".finalizeBins();"); + m_constructorp->addStmtsp(finishp); + } + return bins; + } + // Route a cross through a VlCoverCross member: emit the member, its constructor init + // registration, and the sample() call. The feeding coverpoints are already generated - // (their hit lists drive the cross), so only O(1) generated code is needed here. + // (their hit lists drive the cross). Each explicit bin adds one configuration call. void generateCross(AstCoverCross* crossp) { FileLine* const fl = crossp->fileline(); UINFO(4, " Generating VlCoverCross member: " << crossp->name()); @@ -1333,11 +1430,13 @@ class FunctionalCoverageVisitor final : public VNVisitor { // Resolve and unlink the coverpoint refs, in dimension order. Every ref resolves to a // known coverpoint (a cross with an unresolvable item was dropped earlier). std::vector cpVars; + std::map dimensions; for (AstNode* itemp = crossp->itemsp(); itemp;) { AstNode* const nextp = itemp->nextp(); AstCoverpointRef* const refp = VN_AS(itemp, CoverpointRef); const auto it = m_cpVarMap.find(refp->name()); UASSERT_OBJ(it != m_cpVarMap.end(), crossp, "Cross references an unknown coverpoint"); + dimensions.emplace(refp->name(), static_cast(cpVars.size())); cpVars.push_back(it->second); VL_DO_DANGLING(pushDeletep(refp->unlinkFrBack()), refp); itemp = nextp; @@ -1364,6 +1463,8 @@ class FunctionalCoverageVisitor final : public VNVisitor { + VIdProtect::protectIf(fl->filename(), prot) + "\", " + std::to_string(fl->lineno()) + ", " + std::to_string(fl->firstColumn()) + ");"; m_constructorp->addStmtsp(makeCrossCpsCall(fl, cpVars, cxVarp, initCall)); + const std::vector bins + = generateCrossBins(crossp, cxVarp, cpVars, dimensions); if (v3Global.opt.coverage()) { const std::string page = VIdProtect::protectIf("v_covergroup/" + m_covergroupp->name(), prot); @@ -1375,7 +1476,9 @@ class FunctionalCoverageVisitor final : public VNVisitor { // sample(): after all coverpoints have sampled (cross loop runs after coverpoint loop). UASSERT_OBJ(m_sampleFuncp, crossp, "sample() CFunc not set for cross"); - AstNodeStmt* const samplep = makeCrossCpsCall(fl, cpVars, cxVarp, ".sample(__Vcx_cps);"); + AstNodeStmt* const samplep = makeCrossCpsCall( + fl, cpVars, cxVarp, + bins.empty() ? ".sample(__Vcx_cps);" : ".sample(__Vcx_cps, __Vcx_iffs);", bins); if (AstNodeExpr* const iffp = crossp->iffp()) { m_sampleFuncp->addStmtsp(new AstIf{fl, iffp->cloneTree(false), samplep}); } else { diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 67290dd7e..3918cdff3 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -1415,14 +1415,43 @@ class LinkParseVisitor final : public VNVisitor { iterateChildren(nodep); } + void visit(AstCoverBinsof* nodep) override { + cleanFileline(nodep); + AstCoverpointRef* const refp = nodep->pointp(); + const AstParseRef* pointp = VN_CAST(refp->exprp(), ParseRef); + const AstParseRef* binp = nullptr; + const AstDot* const dotp = VN_CAST(refp->exprp(), Dot); + if (dotp) { + pointp = VN_CAST(dotp->lhsp(), ParseRef); + binp = VN_CAST(dotp->rhsp(), ParseRef); + } + if (!pointp || (dotp && !binp)) { + nodep->v3warn(COVERIGN, "Unsupported: 'binsof' in coverage select expression"); + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); + return; + } + // These names belong to the coverage namespace, not the sampled variables. + if (binp) nodep->name(binp->name()); + refp->replaceWith(new AstCoverpointRef{pointp->fileline(), pointp->name()}); + VL_DO_DANGLING(pushDeletep(refp), refp); + iterateChildren(nodep); + } + + void visit(AstCoverCrossBin* nodep) override { + cleanFileline(nodep); + iterateChildren(nodep); + if (!nodep->selectp()) { + nodep->v3warn(COVERIGN, "Unsupported: explicit coverage cross bins"); + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); + } + } + void visit(AstCoverCross* nodep) override { cleanFileline(nodep); - // Distribute the parse-time raw cross_body list (rawBodyp, op3) into the - // typed optionsp slot. The grammar produces AstCgOptionAssign nodes for - // option.* items; convert them to AstCoverOption exactly as visit(AstCoverpoint*) - // does. Other items (functions, unsupported bin selectors) are discarded. - for (AstNode *itemp = nodep->rawBodyp(), *nextp; itemp; itemp = nextp) { + // Move options out of the mixed parse-time body, leaving only cross bins. + for (AstNode *itemp = nodep->binsp(), *nextp; itemp; itemp = nextp) { nextp = itemp->nextp(); + if (VN_IS(itemp, CoverCrossBin)) continue; itemp->unlinkFrBack(); AstCgOptionAssign* const optp = VN_AS(itemp, CgOptionAssign); const VCoverOptionType optType = optp->optType(); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index e145995c1..467c908d0 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2066,7 +2066,11 @@ class WidthVisitor final : public VNVisitor { userIterateAndNext(nodep->itemsp(), nullptr); if (nodep->iffp()) iterateCheckBool(nodep, "iff condition", nodep->iffp(), BOTH); userIterateAndNext(nodep->optionsp(), nullptr); - userIterateAndNext(nodep->rawBodyp(), nullptr); + userIterateAndNext(nodep->binsp(), nullptr); + } + void visit(AstCoverCrossBin* nodep) override { + userIterateAndNext(nodep->selectp(), nullptr); + if (nodep->iffp()) iterateCheckBool(nodep, "iff condition", nodep->iffp(), BOTH); } void visit(AstCoverpoint* nodep) override { // The coverpoint expression is self-determined (IEEE 1800-2023 19.5). Width it diff --git a/src/verilog.y b/src/verilog.y index 2238b08ab..4170308ef 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -7323,7 +7323,7 @@ cover_cross: // ==IEEE: cover_cross { AstCoverCross* const nodep = new AstCoverCross{$3, *$1, VN_AS($4, CoverpointRef), $5}; - if ($6) nodep->addRawBodyp($6); + if ($6) nodep->addBinsp($6); $$ = nodep; } | yCROSS list_of_cross_items iffE cross_body @@ -7331,7 +7331,7 @@ cover_cross: // ==IEEE: cover_cross AstCoverCross* const nodep = new AstCoverCross{$1, "__cross" + cvtToStr(GRAMMARP->s_typeImpNum++), VN_AS($2, CoverpointRef), $3}; - if ($4) nodep->addRawBodyp($4); + if ($4) nodep->addBinsp($4); $$ = nodep; } ; @@ -7393,9 +7393,9 @@ cross_body_item: // ==IEEE: cross_body_item { $$ = nullptr; BBCOVERIGN($1->fileline(), "Unsupported: 'function' in coverage cross body"); DEL($1); } // // IEEE: bins_selection_or_option | coverage_option ';' { $$ = $1; } - // // IEEE: bins_selection - for now, we ignore explicit cross bins + // // IEEE: bins_selection | yBINS idAny/*new-bin_identifier*/ '=' select_expression iffE ';' - { $$ = nullptr; BBCOVERIGN($1, "Unsupported: explicit coverage cross bins"); DEL($4, $5); } + { $$ = new AstCoverCrossBin{$1, *$2, $4, $5}; } | yIGNORE_BINS idAny/*new-bin_identifier*/ '=' select_expression iffE ';' { $$ = nullptr; BBCOVERIGN($1, "Unsupported: explicit coverage cross bins"); DEL($4, $5); } | yILLEGAL_BINS idAny/*new-bin_identifier*/ '=' select_expression iffE ';' @@ -7416,11 +7416,11 @@ select_expression: // ==IEEE: select_expression select_expression_r: // // IEEE: select_condition expanded here yBINSOF '(' bins_expression ')' - { $$ = nullptr; BBCOVERIGN($1, "Unsupported: 'binsof' in coverage select expression"); DEL($3); } + { $$ = new AstCoverBinsof{$1, new AstCoverpointRef{$3->fileline(), $3}}; } | '!' yBINSOF '(' bins_expression ')' { $$ = nullptr; BBCOVERIGN($1, "Unsupported: 'binsof' in coverage select expression"); DEL($4); } | yBINSOF '(' bins_expression ')' yINTERSECT '{' covergroup_range_list '}' - { $$ = nullptr; BBCOVERIGN($5, "Unsupported: 'intersect' in coverage select expression"); DEL($7); } + { $$ = nullptr; BBCOVERIGN($5, "Unsupported: 'intersect' in coverage select expression"); DEL($3, $7); } | '!' yBINSOF '(' bins_expression ')' yINTERSECT '{' covergroup_range_list '}' { } { $$ = nullptr; BBCOVERIGN($5, "Unsupported: 'intersect' in coverage select expression"); DEL($4, $8); } | yWITH__PAREN '(' cgexpr ')' @@ -7450,7 +7450,7 @@ select_expression_r: //UNSUP // Above are all removed, replace with: ; -bins_expression: // ==IEEE: bins_expression +bins_expression: // ==IEEE: bins_expression // // "cover_point_identifier" and "variable_identifier" look identical // IEEE specifies: // bins_expression ::= @@ -7459,7 +7459,7 @@ bins_expression: // ==IEEE: bins_expression // Verilator supports hierarchical reference in a place of variable identifier. // This is an extension based on other simulators. idDotted - { $$ = nullptr; /*UNSUP*/ DEL($1); } + { $$ = $1; } ; coverage_eventE: // IEEE: [ coverage_event ] diff --git a/test_regress/t/t_covergroup_autobins_bad.out b/test_regress/t/t_covergroup_autobins_bad.out index 98bca7f0c..84e87a158 100644 --- a/test_regress/t/t_covergroup_autobins_bad.out +++ b/test_regress/t/t_covergroup_autobins_bad.out @@ -109,4 +109,20 @@ : ... note: In instance 't' 109 | cp_a: coverpoint cp_expr {bins x[] = {size_var};} | ^ +%Error: t/t_covergroup_autobins_bad.v:124:28: binsof coverpoint 'missing' is not an item of cross 'xc' (IEEE 1800-2012 19.6.1). + : ... note: In instance 't' + 124 | bins missing_point = binsof(missing); + | ^~~~~~ +%Error: t/t_covergroup_autobins_bad.v:125:30: binsof coverpoint 'cp_other' is not an item of cross 'xc' (IEEE 1800-2012 19.6.1). + : ... note: In instance 't' + 125 | bins uncrossed_point = binsof(cp_other); + | ^~~~~~ +%Error: t/t_covergroup_autobins_bad.v:126:26: Cannot find bin 'missing' in coverpoint 'cp_a' (IEEE 1800-2012 19.6.1). + : ... note: In instance 't' + 126 | bins missing_bin = binsof(cp_a.missing); + | ^~~~~~ +%Error: t/t_covergroup_autobins_bad.v:128:7: Duplicate cross bin 'duplicate' (IEEE 1800-2012 19.6.1). + : ... note: In instance 't' + 128 | bins duplicate = binsof(cp_b); + | ^~~~ %Error: Exiting due to diff --git a/test_regress/t/t_covergroup_autobins_bad.v b/test_regress/t/t_covergroup_autobins_bad.v index ed41554c7..113fe9a75 100644 --- a/test_regress/t/t_covergroup_autobins_bad.v +++ b/test_regress/t/t_covergroup_autobins_bad.v @@ -116,6 +116,19 @@ module t; xc: cross cp_a, cp_c; endgroup + covergroup cgx_binsof; + cp_a: coverpoint cp_expr {bins a = {0};} + cp_b: coverpoint cp_expr {bins b = {0};} + cp_other: coverpoint cp_expr {bins other = {0};} + xc: cross cp_a, cp_b { + bins missing_point = binsof(missing); + bins uncrossed_point = binsof(cp_other); + bins missing_bin = binsof(cp_a.missing); + bins duplicate = binsof(cp_a); + bins duplicate = binsof(cp_b); + } + endgroup + cg1 cg1_inst = new; cg2 cg2_inst = new; cg2b cg2b_inst = new; @@ -130,6 +143,7 @@ module t; cgx_arr_4state_hi cgx_arr_4state_hi_inst = new; cgx_arr_ncval cgx_arr_ncval_inst = new; cgx_arr_open cgx_arr_open_inst = new; + cgx_binsof cgx_binsof_inst = new; initial $finish; endmodule diff --git a/test_regress/t/t_covergroup_binsof.out b/test_regress/t/t_covergroup_binsof.out new file mode 100644 index 000000000..f360ab755 --- /dev/null +++ b/test_regress/t/t_covergroup_binsof.out @@ -0,0 +1,82 @@ +cg_auto.a.auto_0: 10 +cg_auto.a.auto_1: 8 +cg_auto.all_products.combined [cross]: 18 +cg_auto.b.auto_0: 9 +cg_auto.b.auto_1: 9 +cg_binsof.all_products.combined [cross]: 10 +cg_binsof.array_bins.high_x_either [cross]: 2 +cg_binsof.array_bins.high_x_high [cross]: 1 +cg_binsof.array_bins.high_x_low [cross]: 1 +cg_binsof.array_bins.low_x_either [cross]: 4 +cg_binsof.array_bins.low_x_high [cross]: 2 +cg_binsof.array_bins.low_x_low [cross]: 2 +cg_binsof.array_bins.selected [cross]: 4 +cg_binsof.cp_a.arrayed[0]: 2 +cg_binsof.cp_a.arrayed[1]: 2 +cg_binsof.cp_a.high: 2 +cg_binsof.cp_a.ignored [ignore]: 2 +cg_binsof.cp_a.low: 4 +cg_binsof.cp_a.rest [default]: 8 +cg_binsof.cp_b.either: 18 +cg_binsof.cp_b.high: 9 +cg_binsof.cp_b.low: 9 +cg_binsof.empty_selection.arrayed[0]_x_either [cross]: 2 +cg_binsof.empty_selection.arrayed[0]_x_high [cross]: 1 +cg_binsof.empty_selection.arrayed[0]_x_low [cross]: 1 +cg_binsof.empty_selection.arrayed[1]_x_either [cross]: 2 +cg_binsof.empty_selection.arrayed[1]_x_high [cross]: 1 +cg_binsof.empty_selection.arrayed[1]_x_low [cross]: 1 +cg_binsof.empty_selection.high_x_either [cross]: 2 +cg_binsof.empty_selection.high_x_high [cross]: 1 +cg_binsof.empty_selection.high_x_low [cross]: 1 +cg_binsof.empty_selection.low_x_either [cross]: 4 +cg_binsof.empty_selection.low_x_high [cross]: 2 +cg_binsof.empty_selection.low_x_low [cross]: 2 +cg_binsof.guarded.arrayed[0]_x_either [cross]: 2 +cg_binsof.guarded.arrayed[0]_x_high [cross]: 1 +cg_binsof.guarded.arrayed[0]_x_low [cross]: 1 +cg_binsof.guarded.arrayed[1]_x_either [cross]: 2 +cg_binsof.guarded.arrayed[1]_x_high [cross]: 1 +cg_binsof.guarded.arrayed[1]_x_low [cross]: 1 +cg_binsof.guarded.high_x_either [cross]: 2 +cg_binsof.guarded.high_x_high [cross]: 1 +cg_binsof.guarded.high_x_low [cross]: 1 +cg_binsof.guarded.selected [cross]: 1 +cg_binsof.guarded.selected_one [cross]: 2 +cg_binsof.named.arrayed[0]_x_either [cross]: 2 +cg_binsof.named.arrayed[0]_x_high [cross]: 1 +cg_binsof.named.arrayed[0]_x_low [cross]: 1 +cg_binsof.named.arrayed[1]_x_either [cross]: 2 +cg_binsof.named.arrayed[1]_x_high [cross]: 1 +cg_binsof.named.arrayed[1]_x_low [cross]: 1 +cg_binsof.named.high_x_either [cross]: 2 +cg_binsof.named.high_x_high [cross]: 1 +cg_binsof.named.high_x_low [cross]: 1 +cg_binsof.named.selected [cross]: 4 +cg_binsof.other_axis.arrayed[0]_x_either [cross]: 2 +cg_binsof.other_axis.arrayed[0]_x_high [cross]: 1 +cg_binsof.other_axis.arrayed[1]_x_either [cross]: 2 +cg_binsof.other_axis.arrayed[1]_x_high [cross]: 1 +cg_binsof.other_axis.high_x_either [cross]: 2 +cg_binsof.other_axis.high_x_high [cross]: 1 +cg_binsof.other_axis.low_x_either [cross]: 4 +cg_binsof.other_axis.low_x_high [cross]: 2 +cg_binsof.other_axis.selected [cross]: 5 +cg_binsof.overlapping.arrayed[0]_x_either [cross]: 2 +cg_binsof.overlapping.arrayed[0]_x_high [cross]: 1 +cg_binsof.overlapping.arrayed[1]_x_either [cross]: 2 +cg_binsof.overlapping.arrayed[1]_x_high [cross]: 1 +cg_binsof.overlapping.high_x_either [cross]: 2 +cg_binsof.overlapping.high_x_high [cross]: 1 +cg_binsof.overlapping.lhs [cross]: 4 +cg_binsof.overlapping.rhs [cross]: 5 +cg_empty.cp_a.ignored [ignore]: 18 +cg_empty.cp_b.auto_0: 9 +cg_empty.cp_b.auto_1: 9 +cg_transition.cp_a.seq: 2 +cg_transition.cp_a.two: 2 +cg_transition.cp_b.auto_0: 3 +cg_transition.cp_b.auto_1: 3 +cg_transition.transitions.selected [cross]: 2 +cg_transition.transitions.two_x_auto_0 [cross]: 1 +cg_transition.transitions.two_x_auto_1 [cross]: 1 diff --git a/test_regress/t/t_covergroup_binsof.py b/test_regress/t/t_covergroup_binsof.py new file mode 100755 index 000000000..6f388a5e4 --- /dev/null +++ b/test_regress/t/t_covergroup_binsof.py @@ -0,0 +1,26 @@ +#!/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') + +threads = 2 if test.vltmt else 1 +coverage_covergroup_common.run(test, threads=threads) + +merged = test.obj_dir + '/merged.dat' +test.run(cmd=[ + os.environ['VERILATOR_ROOT'] + '/bin/verilator_coverage', '--write', merged, + test.coverage_filename +], + verilator_run=True) +test.file_grep(merged, r"cg_binsof\.all_products\.combined.*' 10") + +test.passes() diff --git a/test_regress/t/t_covergroup_binsof.v b/test_regress/t/t_covergroup_binsof.v new file mode 100644 index 000000000..e36d38feb --- /dev/null +++ b/test_regress/t/t_covergroup_binsof.v @@ -0,0 +1,98 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Wilson Snyder +// SPDX-License-Identifier: CC0-1.0 + +// verilog_format: off +`define stop $stop +`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__, `__LINE__, (gotv), (expv)); `stop; end while (0); +// verilog_format: on + +module t ( + input clk +); + int cyc = 0; + + covergroup cg_binsof with function sample (bit [6:0] a, bit b, bit enabled); + cp_a: coverpoint a { + ignore_bins ignored = {7}; + bins low = {[0 : 1]}; + bins high = {2}; + bins arrayed[] = {3, 4}; + bins rest = default; + } + cp_b: coverpoint b {bins low = {0}; bins high = {1}; bins either = {[0 : 1]};} + // Overlapping coverpoint bins must not count a selected cross bin twice. + all_products: cross cp_a, cp_b{ + bins combined = binsof (cp_a); + } + named: cross cp_a, cp_b{bins selected = binsof (cp_a.low);} + other_axis: cross cp_a, cp_b{bins selected = (binsof (cp_b.low));} + array_bins: cross cp_a, cp_b{bins selected = binsof (cp_a.arrayed);} + overlapping: cross cp_a, cp_b{ + bins lhs = binsof (cp_a.low); + bins rhs = binsof (cp_b.low); + } + guarded: cross cp_a, cp_b iff (enabled) { + bins selected = binsof (cp_a.low) iff (a == 0); + bins selected_one = binsof (cp_a.low) iff (a == 1); + } + // Non-normal coverpoint bins do not contribute any cross products. + empty_selection: cross cp_a, cp_b{ + bins ignored = binsof (cp_a.ignored); + bins defaulted = binsof (cp_a.rest); + } + endgroup + + covergroup cg_auto with function sample (bit a, bit b); + coverpoint a; + coverpoint b; + all_products: cross a, b{bins combined = binsof (a);} + endgroup + + covergroup cg_transition with function sample (bit [6:0] a, bit b); + cp_a: coverpoint a {bins seq = (0 => 1); bins two = {2};} + cp_b: coverpoint b; + transitions: cross cp_a, cp_b{bins selected = binsof (cp_a.seq);} + endgroup + + covergroup cg_empty with function sample (bit a, bit b); + cp_a: coverpoint a {ignore_bins ignored = {0, 1};} + cp_b: coverpoint b; + empty_product: cross cp_a, cp_b{bins selected = binsof (cp_b);} + endgroup + + cg_binsof cov = new; + cg_auto auto_cov = new; + cg_transition trans_cov = new; + cg_empty empty_cov = new; + + always @(posedge clk) begin + if (cyc == 0) begin + `checkr(cov.get_inst_coverage(), 0.0); + `checkr(auto_cov.get_inst_coverage(), 0.0); + `checkr(trans_cov.get_inst_coverage(), 0.0); + `checkr(empty_cov.get_inst_coverage(), 0.0); + end + if (cyc < 18) begin + cov.sample(7'(cyc / 2), 1'(cyc), cyc != 0); + auto_cov.sample(1'(cyc / 2), 1'(cyc)); + empty_cov.sample(1'(cyc / 2), 1'(cyc)); + if (cyc < 6) trans_cov.sample(7'(cyc % 3), 1'(cyc / 3)); + if (cyc == 0) begin + `checkr(cov.get_inst_coverage(), 20.0); + `checkr(auto_cov.get_inst_coverage(), 60.0); + end + end + else begin + `checkr(cov.get_inst_coverage(), 100.0); + `checkr(auto_cov.get_inst_coverage(), 100.0); + `checkr(trans_cov.get_inst_coverage(), 100.0); + `checkr(empty_cov.get_inst_coverage(), 100.0); + $write("*-* All Finished *-*\n"); + $finish; + end + ++cyc; + end +endmodule diff --git a/test_regress/t/t_covergroup_binsof_no_coverage.py b/test_regress/t/t_covergroup_binsof_no_coverage.py new file mode 100755 index 000000000..97fd25056 --- /dev/null +++ b/test_regress/t/t_covergroup_binsof_no_coverage.py @@ -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_all') +test.top_filename = 't/t_covergroup_binsof.v' + +test.compile(verilator_flags2=['-CFLAGS -std=c++14'], threads=(2 if test.vltmt else 1)) +test.execute() + +test.passes() diff --git a/test_regress/t/t_covergroup_binsof_protect_ids.py b/test_regress/t/t_covergroup_binsof_protect_ids.py new file mode 100755 index 000000000..91d4713ab --- /dev/null +++ b/test_regress/t/t_covergroup_binsof_protect_ids.py @@ -0,0 +1,22 @@ +#!/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_all') +test.top_filename = 't/t_covergroup_binsof.v' + +test.compile( + verilator_flags2=['--coverage', '--protect-ids', '--protect-key BINSOF_KEY', '-Wno-INSECURE'], + threads=(2 if test.vltmt else 1)) +test.execute() +test.file_grep_not(test.coverage_filename, + r'cg_binsof|cg_auto|cg_transition|t_covergroup_binsof|combined|selected') + +test.passes() diff --git a/test_regress/t/t_covergroup_unsup.out b/test_regress/t/t_covergroup_unsup.out index 4b3c431c8..b1c7b79dc 100644 --- a/test_regress/t/t_covergroup_unsup.out +++ b/test_regress/t/t_covergroup_unsup.out @@ -9,9 +9,6 @@ %Warning-COVERIGN: t/t_covergroup_unsup.v:103:18: Unsupported: function call in coverage select expression 103 | bins one = crossfunc(); | ^~~~~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:103:7: Unsupported: explicit coverage cross bins - 103 | bins one = crossfunc(); - | ^~~~ %Warning-COVERIGN: t/t_covergroup_unsup.v:113:14: Unsupported: 'bins' explicit array size (treated as '[]') 113 | { bins ba[2] = {a}; } | ^ @@ -93,143 +90,50 @@ %Warning-COVERIGN: t/t_covergroup_unsup.v:162:32: Unsupported: 'with' in cover bin 162 | bins div_by_2_paren[] = a with (item % 2 == 0); | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:168:20: Unsupported: 'binsof' in coverage select expression - 168 | bins bin_a = binsof(a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:168:7: Unsupported: explicit coverage cross bins - 168 | bins bin_a = binsof(a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:169:21: Unsupported: 'binsof' in coverage select expression - 169 | bins bin_ai = binsof(a) iff (!rst); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:169:7: Unsupported: explicit coverage cross bins - 169 | bins bin_ai = binsof(a) iff (!rst); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:170:20: Unsupported: 'binsof' in coverage select expression - 170 | bins bin_c = binsof(cp.x); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:170:7: Unsupported: explicit coverage cross bins - 170 | bins bin_c = binsof(cp.x); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:171:21: Unsupported: 'binsof' in coverage select expression - 171 | bins bin_na = ! binsof(a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:168:21: Unsupported: 'binsof' in coverage select expression + 168 | bins bin_na = ! binsof(a); | ^ -%Warning-COVERIGN: t/t_covergroup_unsup.v:171:7: Unsupported: explicit coverage cross bins - 171 | bins bin_na = ! binsof(a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:173:30: Unsupported: 'intersect' in coverage select expression - 173 | bins bin_d = binsof(a) intersect { b }; +%Warning-COVERIGN: t/t_covergroup_unsup.v:170:30: Unsupported: 'intersect' in coverage select expression + 170 | bins bin_d = binsof(a) intersect { b }; | ^~~~~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:173:7: Unsupported: explicit coverage cross bins - 173 | bins bin_d = binsof(a) intersect { b }; - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:174:31: Unsupported: 'intersect' in coverage select expression - 174 | bins bin_nd = ! binsof(a) intersect { b }; +%Warning-COVERIGN: t/t_covergroup_unsup.v:171:31: Unsupported: 'intersect' in coverage select expression + 171 | bins bin_nd = ! binsof(a) intersect { b }; | ^ -%Warning-COVERIGN: t/t_covergroup_unsup.v:174:7: Unsupported: explicit coverage cross bins - 174 | bins bin_nd = ! binsof(a) intersect { b }; - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:176:20: Unsupported: 'with' in coverage select expression - 176 | bins bin_e = with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:173:20: Unsupported: 'with' in coverage select expression + 173 | bins bin_e = with (a); | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:176:7: Unsupported: explicit coverage cross bins - 176 | bins bin_e = with (a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:177:24: Unsupported: 'with' in coverage select expression - 177 | bins bin_not_e = ! with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:174:24: Unsupported: 'with' in coverage select expression + 174 | bins bin_not_e = ! with (a); | ^ -%Warning-COVERIGN: t/t_covergroup_unsup.v:177:7: Unsupported: explicit coverage cross bins - 177 | bins bin_not_e = ! with (a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:179:23: Unsupported: 'binsof' in coverage select expression - 179 | bins bin_par = (binsof(a)); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:179:7: Unsupported: explicit coverage cross bins - 179 | bins bin_par = (binsof(a)); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:180:22: Unsupported: 'binsof' in coverage select expression - 180 | bins bin_and = binsof(a) && binsof(b); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:180:35: Unsupported: 'binsof' in coverage select expression - 180 | bins bin_and = binsof(a) && binsof(b); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:180:32: Unsupported: '&&' in coverage select expression - 180 | bins bin_and = binsof(a) && binsof(b); +%Warning-COVERIGN: t/t_covergroup_unsup.v:176:32: Unsupported: '&&' in coverage select expression + 176 | bins bin_and = binsof(a) && binsof(b); | ^~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:180:7: Unsupported: explicit coverage cross bins - 180 | bins bin_and = binsof(a) && binsof(b); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:181:21: Unsupported: 'binsof' in coverage select expression - 181 | bins bin_or = binsof(a) || binsof(b); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:181:34: Unsupported: 'binsof' in coverage select expression - 181 | bins bin_or = binsof(a) || binsof(b); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:181:31: Unsupported: '||' in coverage select expression - 181 | bins bin_or = binsof(a) || binsof(b); +%Warning-COVERIGN: t/t_covergroup_unsup.v:177:31: Unsupported: '||' in coverage select expression + 177 | bins bin_or = binsof(a) || binsof(b); | ^~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:181:7: Unsupported: explicit coverage cross bins - 181 | bins bin_or = binsof(a) || binsof(b); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:182:23: Unsupported: 'binsof' in coverage select expression - 182 | bins bin_with = binsof(a) with (a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:182:33: Unsupported: 'with' in coverage select expression - 182 | bins bin_with = binsof(a) with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:178:33: Unsupported: 'with' in coverage select expression + 178 | bins bin_with = binsof(a) with (a); | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:182:7: Unsupported: explicit coverage cross bins - 182 | bins bin_with = binsof(a) with (a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:183:26: Unsupported: 'binsof' in coverage select expression - 183 | bins bin_or_with = binsof(a) || binsof(a) with (a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:183:39: Unsupported: 'binsof' in coverage select expression - 183 | bins bin_or_with = binsof(a) || binsof(a) with (a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:183:49: Unsupported: 'with' in coverage select expression - 183 | bins bin_or_with = binsof(a) || binsof(a) with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:179:49: Unsupported: 'with' in coverage select expression + 179 | bins bin_or_with = binsof(a) || binsof(a) with (a); | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:183:36: Unsupported: '||' in coverage select expression - 183 | bins bin_or_with = binsof(a) || binsof(a) with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:179:36: Unsupported: '||' in coverage select expression + 179 | bins bin_or_with = binsof(a) || binsof(a) with (a); | ^~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:183:7: Unsupported: explicit coverage cross bins - 183 | bins bin_or_with = binsof(a) || binsof(a) with (a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:184:27: Unsupported: 'binsof' in coverage select expression - 184 | bins bin_and_with = binsof(a) && binsof(a) with (a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:184:40: Unsupported: 'binsof' in coverage select expression - 184 | bins bin_and_with = binsof(a) && binsof(a) with (a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:184:50: Unsupported: 'with' in coverage select expression - 184 | bins bin_and_with = binsof(a) && binsof(a) with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:180:50: Unsupported: 'with' in coverage select expression + 180 | bins bin_and_with = binsof(a) && binsof(a) with (a); | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:184:37: Unsupported: '&&' in coverage select expression - 184 | bins bin_and_with = binsof(a) && binsof(a) with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:180:37: Unsupported: '&&' in coverage select expression + 180 | bins bin_and_with = binsof(a) && binsof(a) with (a); | ^~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:184:7: Unsupported: explicit coverage cross bins - 184 | bins bin_and_with = binsof(a) && binsof(a) with (a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:185:34: Unsupported: 'binsof' in coverage select expression - 185 | bins bin_multiple_fields = binsof(p.inner_packet.field); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:185:7: Unsupported: explicit coverage cross bins - 185 | bins bin_multiple_fields = binsof(p.inner_packet.field); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:187:30: Unsupported: 'binsof' in coverage select expression - 187 | ignore_bins ib_cross = binsof(a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:187:7: Unsupported: explicit coverage cross bins - 187 | ignore_bins ib_cross = binsof(a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:183:7: Unsupported: explicit coverage cross bins + 183 | ignore_bins ib_cross = binsof(a); | ^~~~~~~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:188:32: Unsupported: 'binsof' in coverage select expression - 188 | illegal_bins lib_cross = binsof(a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:188:7: Unsupported: explicit coverage cross bins - 188 | illegal_bins lib_cross = binsof(a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:184:7: Unsupported: explicit coverage cross bins + 184 | illegal_bins lib_cross = binsof(a); | ^~~~~~~~~~~~ -%Error-UNSUPPORTED: t/t_covergroup_unsup.v:213:5: Unsupported: covergroup inheritance (extends) - 213 | covergroup extends cg_empty; +%Error-UNSUPPORTED: t/t_covergroup_unsup.v:209:5: Unsupported: covergroup inheritance (extends) + 209 | covergroup extends cg_empty; | ^~~~~~~~~~ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest %Error: Exiting due to diff --git a/test_regress/t/t_covergroup_unsup.v b/test_regress/t/t_covergroup_unsup.v index 15aac2c65..ebb69ad21 100644 --- a/test_regress/t/t_covergroup_unsup.v +++ b/test_regress/t/t_covergroup_unsup.v @@ -165,9 +165,6 @@ module t ( covergroup cg_cross_bins; cross a, b { - bins bin_a = binsof(a); - bins bin_ai = binsof(a) iff (!rst); - bins bin_c = binsof(cp.x); bins bin_na = ! binsof(a); bins bin_d = binsof(a) intersect { b }; @@ -176,7 +173,6 @@ module t ( bins bin_e = with (a); bins bin_not_e = ! with (a); - bins bin_par = (binsof(a)); bins bin_and = binsof(a) && binsof(b); bins bin_or = binsof(a) || binsof(b); bins bin_with = binsof(a) with (a); diff --git a/test_regress/t/t_covergroup_unsup_ign2.out b/test_regress/t/t_covergroup_unsup_ign2.out index 744153410..895e28660 100644 --- a/test_regress/t/t_covergroup_unsup_ign2.out +++ b/test_regress/t/t_covergroup_unsup_ign2.out @@ -9,9 +9,6 @@ %Warning-COVERIGN: t/t_covergroup_unsup.v:103:18: Unsupported: function call in coverage select expression 103 | bins one = crossfunc(); | ^~~~~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:103:7: Unsupported: explicit coverage cross bins - 103 | bins one = crossfunc(); - | ^~~~ %Warning-COVERIGN: t/t_covergroup_unsup.v:113:14: Unsupported: 'bins' explicit array size (treated as '[]') 113 | { bins ba[2] = {a}; } | ^ @@ -93,140 +90,47 @@ %Warning-COVERIGN: t/t_covergroup_unsup.v:162:32: Unsupported: 'with' in cover bin 162 | bins div_by_2_paren[] = a with (item % 2 == 0); | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:168:20: Unsupported: 'binsof' in coverage select expression - 168 | bins bin_a = binsof(a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:168:7: Unsupported: explicit coverage cross bins - 168 | bins bin_a = binsof(a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:169:21: Unsupported: 'binsof' in coverage select expression - 169 | bins bin_ai = binsof(a) iff (!rst); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:169:7: Unsupported: explicit coverage cross bins - 169 | bins bin_ai = binsof(a) iff (!rst); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:170:20: Unsupported: 'binsof' in coverage select expression - 170 | bins bin_c = binsof(cp.x); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:170:7: Unsupported: explicit coverage cross bins - 170 | bins bin_c = binsof(cp.x); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:171:21: Unsupported: 'binsof' in coverage select expression - 171 | bins bin_na = ! binsof(a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:168:21: Unsupported: 'binsof' in coverage select expression + 168 | bins bin_na = ! binsof(a); | ^ -%Warning-COVERIGN: t/t_covergroup_unsup.v:171:7: Unsupported: explicit coverage cross bins - 171 | bins bin_na = ! binsof(a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:173:30: Unsupported: 'intersect' in coverage select expression - 173 | bins bin_d = binsof(a) intersect { b }; +%Warning-COVERIGN: t/t_covergroup_unsup.v:170:30: Unsupported: 'intersect' in coverage select expression + 170 | bins bin_d = binsof(a) intersect { b }; | ^~~~~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:173:7: Unsupported: explicit coverage cross bins - 173 | bins bin_d = binsof(a) intersect { b }; - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:174:31: Unsupported: 'intersect' in coverage select expression - 174 | bins bin_nd = ! binsof(a) intersect { b }; +%Warning-COVERIGN: t/t_covergroup_unsup.v:171:31: Unsupported: 'intersect' in coverage select expression + 171 | bins bin_nd = ! binsof(a) intersect { b }; | ^ -%Warning-COVERIGN: t/t_covergroup_unsup.v:174:7: Unsupported: explicit coverage cross bins - 174 | bins bin_nd = ! binsof(a) intersect { b }; - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:176:20: Unsupported: 'with' in coverage select expression - 176 | bins bin_e = with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:173:20: Unsupported: 'with' in coverage select expression + 173 | bins bin_e = with (a); | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:176:7: Unsupported: explicit coverage cross bins - 176 | bins bin_e = with (a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:177:24: Unsupported: 'with' in coverage select expression - 177 | bins bin_not_e = ! with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:174:24: Unsupported: 'with' in coverage select expression + 174 | bins bin_not_e = ! with (a); | ^ -%Warning-COVERIGN: t/t_covergroup_unsup.v:177:7: Unsupported: explicit coverage cross bins - 177 | bins bin_not_e = ! with (a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:179:23: Unsupported: 'binsof' in coverage select expression - 179 | bins bin_par = (binsof(a)); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:179:7: Unsupported: explicit coverage cross bins - 179 | bins bin_par = (binsof(a)); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:180:22: Unsupported: 'binsof' in coverage select expression - 180 | bins bin_and = binsof(a) && binsof(b); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:180:35: Unsupported: 'binsof' in coverage select expression - 180 | bins bin_and = binsof(a) && binsof(b); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:180:32: Unsupported: '&&' in coverage select expression - 180 | bins bin_and = binsof(a) && binsof(b); +%Warning-COVERIGN: t/t_covergroup_unsup.v:176:32: Unsupported: '&&' in coverage select expression + 176 | bins bin_and = binsof(a) && binsof(b); | ^~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:180:7: Unsupported: explicit coverage cross bins - 180 | bins bin_and = binsof(a) && binsof(b); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:181:21: Unsupported: 'binsof' in coverage select expression - 181 | bins bin_or = binsof(a) || binsof(b); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:181:34: Unsupported: 'binsof' in coverage select expression - 181 | bins bin_or = binsof(a) || binsof(b); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:181:31: Unsupported: '||' in coverage select expression - 181 | bins bin_or = binsof(a) || binsof(b); +%Warning-COVERIGN: t/t_covergroup_unsup.v:177:31: Unsupported: '||' in coverage select expression + 177 | bins bin_or = binsof(a) || binsof(b); | ^~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:181:7: Unsupported: explicit coverage cross bins - 181 | bins bin_or = binsof(a) || binsof(b); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:182:23: Unsupported: 'binsof' in coverage select expression - 182 | bins bin_with = binsof(a) with (a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:182:33: Unsupported: 'with' in coverage select expression - 182 | bins bin_with = binsof(a) with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:178:33: Unsupported: 'with' in coverage select expression + 178 | bins bin_with = binsof(a) with (a); | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:182:7: Unsupported: explicit coverage cross bins - 182 | bins bin_with = binsof(a) with (a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:183:26: Unsupported: 'binsof' in coverage select expression - 183 | bins bin_or_with = binsof(a) || binsof(a) with (a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:183:39: Unsupported: 'binsof' in coverage select expression - 183 | bins bin_or_with = binsof(a) || binsof(a) with (a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:183:49: Unsupported: 'with' in coverage select expression - 183 | bins bin_or_with = binsof(a) || binsof(a) with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:179:49: Unsupported: 'with' in coverage select expression + 179 | bins bin_or_with = binsof(a) || binsof(a) with (a); | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:183:36: Unsupported: '||' in coverage select expression - 183 | bins bin_or_with = binsof(a) || binsof(a) with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:179:36: Unsupported: '||' in coverage select expression + 179 | bins bin_or_with = binsof(a) || binsof(a) with (a); | ^~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:183:7: Unsupported: explicit coverage cross bins - 183 | bins bin_or_with = binsof(a) || binsof(a) with (a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:184:27: Unsupported: 'binsof' in coverage select expression - 184 | bins bin_and_with = binsof(a) && binsof(a) with (a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:184:40: Unsupported: 'binsof' in coverage select expression - 184 | bins bin_and_with = binsof(a) && binsof(a) with (a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:184:50: Unsupported: 'with' in coverage select expression - 184 | bins bin_and_with = binsof(a) && binsof(a) with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:180:50: Unsupported: 'with' in coverage select expression + 180 | bins bin_and_with = binsof(a) && binsof(a) with (a); | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:184:37: Unsupported: '&&' in coverage select expression - 184 | bins bin_and_with = binsof(a) && binsof(a) with (a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:180:37: Unsupported: '&&' in coverage select expression + 180 | bins bin_and_with = binsof(a) && binsof(a) with (a); | ^~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:184:7: Unsupported: explicit coverage cross bins - 184 | bins bin_and_with = binsof(a) && binsof(a) with (a); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:185:34: Unsupported: 'binsof' in coverage select expression - 185 | bins bin_multiple_fields = binsof(p.inner_packet.field); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:185:7: Unsupported: explicit coverage cross bins - 185 | bins bin_multiple_fields = binsof(p.inner_packet.field); - | ^~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:187:30: Unsupported: 'binsof' in coverage select expression - 187 | ignore_bins ib_cross = binsof(a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:187:7: Unsupported: explicit coverage cross bins - 187 | ignore_bins ib_cross = binsof(a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:183:7: Unsupported: explicit coverage cross bins + 183 | ignore_bins ib_cross = binsof(a); | ^~~~~~~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:188:32: Unsupported: 'binsof' in coverage select expression - 188 | illegal_bins lib_cross = binsof(a); - | ^~~~~~ -%Warning-COVERIGN: t/t_covergroup_unsup.v:188:7: Unsupported: explicit coverage cross bins - 188 | illegal_bins lib_cross = binsof(a); +%Warning-COVERIGN: t/t_covergroup_unsup.v:184:7: Unsupported: explicit coverage cross bins + 184 | illegal_bins lib_cross = binsof(a); | ^~~~~~~~~~~~ %Warning-COVERIGN: t/t_covergroup_unsup.v:98:18: Ignoring unsupported coverage cross option: 'comment' 98 | cross a, b { option.comment = "cross"; option.weight = 12; option.per_instance = 1; } @@ -237,6 +141,45 @@ %Warning-COVERIGN: t/t_covergroup_unsup.v:98:64: Ignoring unsupported coverage cross option: 'per_instance' 98 | cross a, b { option.comment = "cross"; option.weight = 12; option.per_instance = 1; } | ^~~~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:103:7: Unsupported: explicit coverage cross bins + 103 | bins one = crossfunc(); + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:168:7: Unsupported: explicit coverage cross bins + 168 | bins bin_na = ! binsof(a); + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:170:7: Unsupported: explicit coverage cross bins + 170 | bins bin_d = binsof(a) intersect { b }; + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:171:7: Unsupported: explicit coverage cross bins + 171 | bins bin_nd = ! binsof(a) intersect { b }; + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:173:7: Unsupported: explicit coverage cross bins + 173 | bins bin_e = with (a); + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:174:7: Unsupported: explicit coverage cross bins + 174 | bins bin_not_e = ! with (a); + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:176:7: Unsupported: explicit coverage cross bins + 176 | bins bin_and = binsof(a) && binsof(b); + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:177:7: Unsupported: explicit coverage cross bins + 177 | bins bin_or = binsof(a) || binsof(b); + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:178:7: Unsupported: explicit coverage cross bins + 178 | bins bin_with = binsof(a) with (a); + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:179:7: Unsupported: explicit coverage cross bins + 179 | bins bin_or_with = binsof(a) || binsof(a) with (a); + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:180:7: Unsupported: explicit coverage cross bins + 180 | bins bin_and_with = binsof(a) && binsof(a) with (a); + | ^~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:181:34: Unsupported: 'binsof' in coverage select expression + 181 | bins bin_multiple_fields = binsof(p.inner_packet.field); + | ^~~~~~ +%Warning-COVERIGN: t/t_covergroup_unsup.v:181:7: Unsupported: explicit coverage cross bins + 181 | bins bin_multiple_fields = binsof(p.inner_packet.field); + | ^~~~ %Warning-WIDTHTRUNC: t/t_covergroup_unsup.v:76:5: Logical operator COVERPOINT 'a' expects 1 bit on the iff condition, but iff condition's VARREF 'b' generates 32 bits. : ... note: In instance 't' 76 | coverpoint a iff (b);