parent
995534d3ed
commit
d456384d39
|
|
@ -1185,12 +1185,21 @@ public:
|
|||
};
|
||||
class AstCoverpointRef final : public AstNode {
|
||||
// Reference to a coverpoint used in a cross
|
||||
const string m_name; // coverpoint name
|
||||
// @astgen op1 := exprp : Optional[AstNodeExpr] // Non-standard: hierarchical/dotted
|
||||
// // reference (implicit coverpoint), e.g.
|
||||
// // 'cross a.b'; nullptr for a plain coverpoint
|
||||
// // name. An AstDot at parse time, resolved
|
||||
// // by the time V3Covergroup runs.
|
||||
const string m_name; // coverpoint name; empty when exprp() carries a hierarchical reference
|
||||
|
||||
public:
|
||||
AstCoverpointRef(FileLine* fl, const string& name)
|
||||
: ASTGEN_SUPER_CoverpointRef(fl)
|
||||
, m_name{name} {}
|
||||
AstCoverpointRef(FileLine* fl, AstNodeExpr* exprp)
|
||||
: ASTGEN_SUPER_CoverpointRef(fl) {
|
||||
this->exprp(exprp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverpointRef;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class FunctionalCoverageVisitor final : public VNVisitor {
|
|||
for (AstCoverCross* crossp : m_coverCrosses) {
|
||||
for (AstNode* itemp = crossp->itemsp(); itemp; itemp = itemp->nextp()) {
|
||||
if (const AstCoverpointRef* const refp = VN_CAST(itemp, CoverpointRef))
|
||||
m_crossedCpNames.insert(refp->name());
|
||||
if (!refp->exprp()) m_crossedCpNames.insert(refp->name());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1295,6 +1295,18 @@ class FunctionalCoverageVisitor final : public VNVisitor {
|
|||
while (itemp) {
|
||||
AstNode* const nextp = itemp->nextp();
|
||||
AstCoverpointRef* const refp = VN_AS(itemp, CoverpointRef);
|
||||
if (refp->exprp()) {
|
||||
// Non-standard hierarchical/dotted cross item (e.g. 'cross a.b'): an implicit
|
||||
// coverpoint over the referenced expression (carried in refp->exprp()). The
|
||||
// grammar already warned NONSTD; implicit coverpoints are not yet implemented, so
|
||||
// generate no sampling code for this cross. When support is added the implicit
|
||||
// coverpoint should be synthesized upstream (V3LinkParse) as a real AstCoverpoint
|
||||
// so it flows through the normal coverpoint path - by here coverpoint lowering has
|
||||
// already run.
|
||||
refp->v3warn(COVERIGN,
|
||||
"Unsupported: cross of hierarchical reference (implicit coverpoint)");
|
||||
return;
|
||||
}
|
||||
// Find the referenced coverpoint via name map (O(log n) vs O(n) linear scan)
|
||||
const auto it = m_coverpointMap.find(refp->name());
|
||||
AstCoverpoint* const foundCpp = (it != m_coverpointMap.end()) ? it->second : nullptr;
|
||||
|
|
|
|||
|
|
@ -7339,8 +7339,29 @@ cross_itemList<nodep>: // IEEE: part of list_of_cross_items
|
|||
;
|
||||
|
||||
cross_item<nodep>: // ==IEEE: cross_item
|
||||
id/*cover_point_identifier*/
|
||||
{ $$ = new AstCoverpointRef{$<fl>1, *$1}; }
|
||||
// // IEEE: cover_point_identifier | variable_identifier - both are a
|
||||
// // simple identifier. We parse idDotted (a plain hierarchical
|
||||
// // reference a.b.c, with no bit/array selects) to also accept the
|
||||
// // non-standard dotted form (e.g. 'cross a.b') that several
|
||||
// // simulators support; the common simple-identifier case is detected
|
||||
// // and handled exactly as before.
|
||||
idDotted
|
||||
{
|
||||
if (AstParseRef* const refp = VN_CAST($1, ParseRef)) {
|
||||
// Standard: simple cover_point_identifier / variable_identifier
|
||||
$$ = new AstCoverpointRef{refp->fileline(), refp->name()};
|
||||
VL_DO_DANGLING(refp->deleteTree(), refp);
|
||||
} else {
|
||||
// Verilator extension beyond strict IEEE (cross_item is a simple
|
||||
// identifier): some tools accept a hierarchical/dotted reference.
|
||||
// Carry the reference expression (still an AstDot here) out of the
|
||||
// parser unchanged; later stages resolve and, eventually, implement
|
||||
// it as an implicit coverpoint.
|
||||
$1->v3warn(NONSTD, "Non-standard hierarchical reference as a coverage "
|
||||
"cross item (an implicit coverpoint)");
|
||||
$$ = new AstCoverpointRef{$1->fileline(), $1};
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
cross_body<nodep>: // ==IEEE: cross_body
|
||||
|
|
|
|||
|
|
@ -109,10 +109,10 @@ cg_range.cp_addr.hi_range: 2
|
|||
cg_range.cp_addr.lo_range: 2
|
||||
cg_range.cp_cmd.read: 2
|
||||
cg_range.cp_cmd.write: 2
|
||||
cg_unnamed_cross.__cross7.a0_x_read [cross]: 1
|
||||
cg_unnamed_cross.__cross7.a0_x_write [cross]: 0
|
||||
cg_unnamed_cross.__cross7.a1_x_read [cross]: 0
|
||||
cg_unnamed_cross.__cross7.a1_x_write [cross]: 1
|
||||
cg_unnamed_cross.__cross8.a0_x_read [cross]: 1
|
||||
cg_unnamed_cross.__cross8.a0_x_write [cross]: 0
|
||||
cg_unnamed_cross.__cross8.a1_x_read [cross]: 0
|
||||
cg_unnamed_cross.__cross8.a1_x_write [cross]: 1
|
||||
cg_unnamed_cross.cp_a.a0: 1
|
||||
cg_unnamed_cross.cp_a.a1: 1
|
||||
cg_unnamed_cross.cp_c.read: 1
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ module t;
|
|||
logic mode;
|
||||
logic parity;
|
||||
|
||||
typedef struct packed {logic m_p; logic h_mode;} cfg_t;
|
||||
cfg_t s_cfg = '0;
|
||||
|
||||
// 2-way cross
|
||||
covergroup cg2;
|
||||
cp_addr: coverpoint addr {bins addr0 = {0}; bins addr1 = {1};}
|
||||
|
|
@ -90,6 +93,12 @@ module t;
|
|||
addr_cmd_unsup: cross cp_addr, cp_cmd{
|
||||
option.per_instance = 1; // unsupported for cross - expect COVERIGN warning
|
||||
}
|
||||
// Non-standard hierarchical reference as a cross item (an implicit coverpoint):
|
||||
// accepted with NONSTD, but implicit coverpoints are unsupported so the whole
|
||||
// cross is dropped (COVERIGN, suppressed here) - it contributes no bins.
|
||||
/* verilator lint_off NONSTD */
|
||||
cross_hier: cross cp_addr, s_cfg.m_p;
|
||||
/* verilator lint_on NONSTD */
|
||||
endgroup
|
||||
|
||||
// Covergroup with an unnamed cross - the cross is reported under the default name "cross"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
%Warning-NONSTD: t/t_covergroup_cross_opt_unsup.v:19:34: Non-standard hierarchical reference as a coverage cross item (an implicit coverpoint)
|
||||
19 | cross_hier: cross cp_a, s_cfg.m_p;
|
||||
| ^
|
||||
... For warning description see https://verilator.org/warn/NONSTD?v=latest
|
||||
... Use "/* verilator lint_off NONSTD */" and lint_on around source to disable this message.
|
||||
%Warning-COVERIGN: t/t_covergroup_cross_opt_unsup.v:13:7: Ignoring unsupported coverage cross option: 'per_instance'
|
||||
13 | option.per_instance = 1;
|
||||
| ^~~~~~
|
||||
|
|
@ -7,4 +12,8 @@
|
|||
: ... note: In instance 't'
|
||||
15 | cross_implicit: cross cp_a, var_x;
|
||||
| ^~~~~
|
||||
%Warning-COVERIGN: t/t_covergroup_cross_opt_unsup.v:19:34: Unsupported: cross of hierarchical reference (implicit coverpoint)
|
||||
: ... note: In instance 't'
|
||||
19 | cross_hier: cross cp_a, s_cfg.m_p;
|
||||
| ^
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -13,7 +13,13 @@ module t;
|
|||
option.per_instance = 1; // unsupported for cross; triggers COVERIGN
|
||||
}
|
||||
cross_implicit: cross cp_a, var_x;
|
||||
// Non-standard hierarchical/dotted cross item: can only be a data reference
|
||||
// (implicit coverpoint), never a coverpoint. Accepted with a NONSTD warning;
|
||||
// implicit coverpoints are unsupported so the cross is dropped (COVERIGN).
|
||||
cross_hier: cross cp_a, s_cfg.m_p;
|
||||
endgroup
|
||||
typedef struct packed {logic m_p; logic h_mode;} cfg_t;
|
||||
cfg_t s_cfg = '0;
|
||||
logic var_x = 1'b0;
|
||||
cg cg_i = new;
|
||||
initial begin
|
||||
|
|
|
|||
|
|
@ -28,6 +28,14 @@
|
|||
-000001 point: type=toggle comment=parity:0->1 hier=top.t
|
||||
-000000 point: type=toggle comment=parity:1->0 hier=top.t
|
||||
|
||||
typedef struct packed {logic m_p; logic h_mode;} cfg_t;
|
||||
%000001 cfg_t s_cfg = '0;
|
||||
-000001 point: type=line comment=block hier=top.t
|
||||
-000000 point: type=toggle comment=s_cfg.h_mode:0->1 hier=top.t
|
||||
-000000 point: type=toggle comment=s_cfg.h_mode:1->0 hier=top.t
|
||||
-000000 point: type=toggle comment=s_cfg.m_p:0->1 hier=top.t
|
||||
-000000 point: type=toggle comment=s_cfg.m_p:1->0 hier=top.t
|
||||
|
||||
// 2-way cross
|
||||
covergroup cg2;
|
||||
%000002 cp_addr: coverpoint addr {bins addr0 = {0}; bins addr1 = {1};}
|
||||
|
|
@ -257,6 +265,12 @@
|
|||
// cross: [addr1, write]
|
||||
option.per_instance = 1; // unsupported for cross - expect COVERIGN warning
|
||||
}
|
||||
// Non-standard hierarchical reference as a cross item (an implicit coverpoint):
|
||||
// accepted with NONSTD, but implicit coverpoints are unsupported so the whole
|
||||
// cross is dropped (COVERIGN, suppressed here) - it contributes no bins.
|
||||
/* verilator lint_off NONSTD */
|
||||
cross_hier: cross cp_addr, s_cfg.m_p;
|
||||
/* verilator lint_on NONSTD */
|
||||
endgroup
|
||||
|
||||
// Covergroup with an unnamed cross - the cross is reported under the default name "cross"
|
||||
|
|
@ -268,13 +282,13 @@
|
|||
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.cp_c.read
|
||||
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.cp_c.write
|
||||
%000001 cross cp_a, cp_c; // no label: reported under the default cross name
|
||||
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.__cross7.a0_x_read
|
||||
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.__cross8.a0_x_read
|
||||
// cross: [a0, read]
|
||||
-000000 point: type=covergroup comment= hier=cg_unnamed_cross.__cross7.a0_x_write
|
||||
-000000 point: type=covergroup comment= hier=cg_unnamed_cross.__cross8.a0_x_write
|
||||
// cross: [a0, write]
|
||||
-000000 point: type=covergroup comment= hier=cg_unnamed_cross.__cross7.a1_x_read
|
||||
-000000 point: type=covergroup comment= hier=cg_unnamed_cross.__cross8.a1_x_read
|
||||
// cross: [a1, read]
|
||||
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.__cross7.a1_x_write
|
||||
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.__cross8.a1_x_write
|
||||
// cross: [a1, write]
|
||||
endgroup
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue