mirror of
https://github.com/verilator/verilator.git
synced 2026-09-01 18:36:28 +02:00
Internals: Optimize updates of Vtogcov signals. No functional change intended. (#6110)
This commit is contained in:
+82
-70
@@ -180,22 +180,8 @@ class CoverageVisitor final : public VNVisitor {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AstCoverInc* newCoverInc(FileLine* fl, const string& hier, const string& page_prefix,
|
||||
const string& comment, const string& linescov, int offset,
|
||||
AstCoverInc* newCoverInc(FileLine* fl, AstNodeCoverDecl* const declp,
|
||||
const string& trace_var_name) {
|
||||
// We could use the basename of the filename to the page, but seems
|
||||
// better for code from an include file to be listed under the
|
||||
// module using it rather than the include file.
|
||||
// Note the module name could have parameters appended, we'll consider this
|
||||
// a feature as it allows for each parameterized block to be counted separately.
|
||||
// Someday the user might be allowed to specify a different page suffix
|
||||
const string page = page_prefix + "/" + m_modp->prettyName();
|
||||
|
||||
AstCoverDecl* const declp = new AstCoverDecl{fl, page, comment, linescov, offset};
|
||||
declp->hier(hier);
|
||||
m_modp->addStmtsp(declp);
|
||||
UINFO(9, "new " << declp);
|
||||
|
||||
AstCoverInc* const incp = new AstCoverInc{fl, declp};
|
||||
if (!trace_var_name.empty()
|
||||
&& v3Global.opt.traceCoverage()
|
||||
@@ -316,9 +302,12 @@ class CoverageVisitor final : public VNVisitor {
|
||||
iterateAndNextNull(nodep->stmtsp());
|
||||
if (m_state.lineCoverageOn(nodep)) {
|
||||
lineTrack(nodep);
|
||||
AstCoverOtherDecl* const declp
|
||||
= new AstCoverOtherDecl{nodep->fileline(), "v_line/" + m_modp->prettyName(),
|
||||
"block", linesCov(m_state, nodep), 0};
|
||||
m_modp->addStmtsp(declp);
|
||||
AstNode* const newp
|
||||
= newCoverInc(nodep->fileline(), "", "v_line", "block", linesCov(m_state, nodep),
|
||||
0, traceNameForLine(nodep, "block"));
|
||||
= newCoverInc(nodep->fileline(), declp, traceNameForLine(nodep, "block"));
|
||||
insertProcStatement(nodep, newp);
|
||||
}
|
||||
}
|
||||
@@ -354,9 +343,12 @@ class CoverageVisitor final : public VNVisitor {
|
||||
iterateChildren(nodep);
|
||||
if (m_state.lineCoverageOn(nodep)) {
|
||||
lineTrack(nodep);
|
||||
AstCoverOtherDecl* const declp
|
||||
= new AstCoverOtherDecl{nodep->fileline(), "v_line/" + m_modp->prettyName(),
|
||||
"block", linesCov(m_state, nodep), 0};
|
||||
m_modp->addStmtsp(declp);
|
||||
AstNode* const newp
|
||||
= newCoverInc(nodep->fileline(), "", "v_line", "block", linesCov(m_state, nodep),
|
||||
0, traceNameForLine(nodep, "block"));
|
||||
= newCoverInc(nodep->fileline(), declp, traceNameForLine(nodep, "block"));
|
||||
insertProcStatement(nodep, newp);
|
||||
}
|
||||
}
|
||||
@@ -402,35 +394,23 @@ class CoverageVisitor final : public VNVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
void toggleVarBottom(const ToggleEnt& above, const AstVar* varp) {
|
||||
void toggleVarBottom(const ToggleEnt& above, const AstVar* varp, const VNumRange& range) {
|
||||
const std::string hierPrefix
|
||||
= (m_beginHier != "") ? AstNode::prettyName(m_beginHier) + "." : "";
|
||||
AstCoverToggleDecl* const declp
|
||||
= new AstCoverToggleDecl{varp->fileline(), "v_toggle/" + m_modp->prettyName(),
|
||||
hierPrefix + varp->name() + above.m_comment, range};
|
||||
m_modp->addStmtsp(declp);
|
||||
AstCoverToggle* const newp = new AstCoverToggle{
|
||||
varp->fileline(),
|
||||
newCoverInc(varp->fileline(), "", "v_toggle",
|
||||
hierPrefix + varp->name() + above.m_comment, "", 0, ""),
|
||||
varp->fileline(), newCoverInc(varp->fileline(), declp, ""),
|
||||
above.m_varRefp->cloneTree(false), above.m_chgRefp->cloneTree(false)};
|
||||
m_modp->addStmtsp(newp);
|
||||
}
|
||||
|
||||
void toggleVarRecurse(const AstNodeDType* const dtypep, const int depth, // per-iteration
|
||||
const ToggleEnt& above, const AstVar* const varp) { // Constant
|
||||
if (const AstBasicDType* const bdtypep = VN_CAST(dtypep, BasicDType)) {
|
||||
if (bdtypep->isRanged()) {
|
||||
for (int index_docs = bdtypep->lo(); index_docs < bdtypep->hi() + 1;
|
||||
++index_docs) {
|
||||
const int index_code = index_docs - bdtypep->lo();
|
||||
ToggleEnt newent{above.m_comment + "["s + cvtToStr(index_docs) + "]",
|
||||
new AstSel{varp->fileline(),
|
||||
above.m_varRefp->cloneTree(false), index_code, 1},
|
||||
new AstSel{varp->fileline(),
|
||||
above.m_chgRefp->cloneTree(false), index_code, 1}};
|
||||
toggleVarBottom(newent, varp);
|
||||
newent.cleanup();
|
||||
}
|
||||
} else {
|
||||
toggleVarBottom(above, varp);
|
||||
}
|
||||
if (const AstBasicDType* const basicp = VN_CAST(dtypep, BasicDType)) {
|
||||
toggleVarBottom(above, varp, basicp->nrange());
|
||||
} else if (const AstUnpackArrayDType* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
|
||||
for (int index_docs = adtypep->lo(); index_docs <= adtypep->hi(); ++index_docs) {
|
||||
const int index_code = index_docs - adtypep->lo();
|
||||
@@ -543,20 +523,26 @@ class CoverageVisitor final : public VNVisitor {
|
||||
iterate(nodep->thenp());
|
||||
lineTrack(nodep);
|
||||
AstNodeExpr* const thenp = nodep->thenp()->unlinkFrBack();
|
||||
nodep->thenp(new AstExprStmt{thenp->fileline(),
|
||||
newCoverInc(nodep->fileline(), "", "v_branch",
|
||||
"cond_then", linesCov(m_state, nodep), 0,
|
||||
traceNameForLine(nodep, "cond_then")),
|
||||
thenp});
|
||||
AstCoverOtherDecl* const thenDeclp
|
||||
= new AstCoverOtherDecl{thenp->fileline(), "v_branch/" + m_modp->prettyName(),
|
||||
"cond_then", linesCov(m_state, nodep), 0};
|
||||
m_modp->addStmtsp(thenDeclp);
|
||||
nodep->thenp(new AstExprStmt{
|
||||
thenp->fileline(),
|
||||
newCoverInc(nodep->fileline(), thenDeclp, traceNameForLine(nodep, "cond_then")),
|
||||
thenp});
|
||||
m_state = lastState;
|
||||
createHandle(nodep);
|
||||
iterate(nodep->elsep());
|
||||
AstNodeExpr* const elsep = nodep->elsep()->unlinkFrBack();
|
||||
nodep->elsep(new AstExprStmt{elsep->fileline(),
|
||||
newCoverInc(nodep->fileline(), "", "v_branch",
|
||||
"cond_else", linesCov(m_state, nodep), 1,
|
||||
traceNameForLine(nodep, "cond_else")),
|
||||
elsep});
|
||||
AstCoverOtherDecl* const elseDeclp
|
||||
= new AstCoverOtherDecl{thenp->fileline(), "v_branch/" + m_modp->prettyName(),
|
||||
"cond_else", linesCov(m_state, nodep), 1};
|
||||
m_modp->addStmtsp(elseDeclp);
|
||||
nodep->elsep(new AstExprStmt{
|
||||
elsep->fileline(),
|
||||
newCoverInc(nodep->fileline(), elseDeclp, traceNameForLine(nodep, "cond_else")),
|
||||
elsep});
|
||||
|
||||
m_state = lastState;
|
||||
} else {
|
||||
@@ -613,22 +599,32 @@ class CoverageVisitor final : public VNVisitor {
|
||||
// Normal if. Linecov shows what's inside the if (not condition that is
|
||||
// always executed)
|
||||
UINFO(4, " COVER-branch: " << nodep);
|
||||
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_branch", "if",
|
||||
linesCov(ifState, nodep), 0,
|
||||
traceNameForLine(nodep, "if")));
|
||||
AstCoverOtherDecl* const ifDeclp
|
||||
= new AstCoverOtherDecl{nodep->fileline(), "v_branch/" + m_modp->prettyName(),
|
||||
"if", linesCov(ifState, nodep), 0};
|
||||
m_modp->addStmtsp(ifDeclp);
|
||||
nodep->addThensp(
|
||||
newCoverInc(nodep->fileline(), ifDeclp, traceNameForLine(nodep, "if")));
|
||||
// The else has a column offset of 1 to uniquify it relative to the if
|
||||
// As "if" and "else" are more than one character wide, this won't overlap
|
||||
// another token
|
||||
nodep->addElsesp(newCoverInc(nodep->fileline(), "", "v_branch", "else",
|
||||
linesCov(elseState, nodep), 1,
|
||||
traceNameForLine(nodep, "else")));
|
||||
AstCoverOtherDecl* const elseDeclp
|
||||
= new AstCoverOtherDecl{nodep->fileline(), "v_branch/" + m_modp->prettyName(),
|
||||
"else", linesCov(elseState, nodep), 1};
|
||||
m_modp->addStmtsp(elseDeclp);
|
||||
nodep->addElsesp(
|
||||
newCoverInc(nodep->fileline(), elseDeclp, traceNameForLine(nodep, "else")));
|
||||
}
|
||||
// If/else attributes to each block as non-branch coverage
|
||||
else if (first_elsif || cont_elsif) {
|
||||
UINFO(4, " COVER-elsif: " << nodep);
|
||||
if (ifState.lineCoverageOn(nodep)) {
|
||||
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_line", "elsif",
|
||||
linesCov(ifState, nodep), 0,
|
||||
AstCoverOtherDecl* const elsifDeclp = new AstCoverOtherDecl{
|
||||
nodep->fileline(), "v_line/" + m_modp->prettyName(), "elsif",
|
||||
linesCov(ifState, nodep), 0};
|
||||
m_modp->addStmtsp(elsifDeclp);
|
||||
|
||||
nodep->addThensp(newCoverInc(nodep->fileline(), elsifDeclp,
|
||||
traceNameForLine(nodep, "elsif")));
|
||||
}
|
||||
// and we don't insert the else as the child if-else will do so
|
||||
@@ -636,14 +632,21 @@ class CoverageVisitor final : public VNVisitor {
|
||||
// Cover as separate blocks (not a branch as is not two-legged)
|
||||
if (ifState.lineCoverageOn(nodep)) {
|
||||
UINFO(4, " COVER-half-if: " << nodep);
|
||||
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_line", "if",
|
||||
linesCov(ifState, nodep), 0,
|
||||
traceNameForLine(nodep, "if")));
|
||||
AstCoverOtherDecl* const ifDeclp = new AstCoverOtherDecl{
|
||||
nodep->fileline(), "v_line/" + m_modp->prettyName(), "if",
|
||||
linesCov(ifState, nodep), 0};
|
||||
m_modp->addStmtsp(ifDeclp);
|
||||
nodep->addThensp(
|
||||
newCoverInc(nodep->fileline(), ifDeclp, traceNameForLine(nodep, "if")));
|
||||
}
|
||||
if (elseState.lineCoverageOn(nodep)) {
|
||||
UINFO(4, " COVER-half-el: " << nodep);
|
||||
nodep->addElsesp(newCoverInc(nodep->fileline(), "", "v_line", "else",
|
||||
linesCov(elseState, nodep), 1,
|
||||
AstCoverOtherDecl* const elseDeclp = new AstCoverOtherDecl{
|
||||
nodep->fileline(), "v_line/" + m_modp->prettyName(), "else",
|
||||
linesCov(elseState, nodep), 1};
|
||||
m_modp->addStmtsp(elseDeclp);
|
||||
|
||||
nodep->addElsesp(newCoverInc(nodep->fileline(), elseDeclp,
|
||||
traceNameForLine(nodep, "else")));
|
||||
}
|
||||
}
|
||||
@@ -665,9 +668,12 @@ class CoverageVisitor final : public VNVisitor {
|
||||
if (m_state.lineCoverageOn(nodep)) { // if the case body didn't disable it
|
||||
lineTrack(nodep);
|
||||
UINFO(4, " COVER: " << nodep);
|
||||
nodep->addStmtsp(newCoverInc(nodep->fileline(), "", "v_line", "case",
|
||||
linesCov(m_state, nodep), 0,
|
||||
traceNameForLine(nodep, "case")));
|
||||
AstCoverOtherDecl* const declp
|
||||
= new AstCoverOtherDecl{nodep->fileline(), "v_line/" + m_modp->prettyName(),
|
||||
"case", linesCov(m_state, nodep), 0};
|
||||
m_modp->addStmtsp(declp);
|
||||
nodep->addStmtsp(
|
||||
newCoverInc(nodep->fileline(), declp, traceNameForLine(nodep, "case")));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -680,9 +686,13 @@ class CoverageVisitor final : public VNVisitor {
|
||||
if (!nodep->coverincsp() && v3Global.opt.coverageUser()) {
|
||||
// Note the name may be overridden by V3Assert processing
|
||||
lineTrack(nodep);
|
||||
nodep->addCoverincsp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
|
||||
linesCov(m_state, nodep), 0,
|
||||
m_beginHier + "_vlCoverageUserTrace"));
|
||||
AstCoverOtherDecl* const declp
|
||||
= new AstCoverOtherDecl{nodep->fileline(), "v_user/" + m_modp->prettyName(),
|
||||
"cover", linesCov(m_state, nodep), 0};
|
||||
declp->hier(m_beginHier);
|
||||
m_modp->addStmtsp(declp);
|
||||
nodep->addCoverincsp(
|
||||
newCoverInc(nodep->fileline(), declp, m_beginHier + "_vlCoverageUserTrace"));
|
||||
}
|
||||
}
|
||||
void visit(AstStop* nodep) override {
|
||||
@@ -754,8 +764,10 @@ class CoverageVisitor final : public VNVisitor {
|
||||
}
|
||||
comment += ") => ";
|
||||
comment += (m_objective ? '1' : '0');
|
||||
AstNode* const newp
|
||||
= newCoverInc(fl, "", "v_expr", comment, "", 0, traceNameForLine(nodep, name));
|
||||
AstCoverOtherDecl* const declp = new AstCoverOtherDecl{
|
||||
nodep->fileline(), "v_expr/" + m_modp->prettyName(), comment, "", 0};
|
||||
m_modp->addStmtsp(declp);
|
||||
AstNode* const newp = newCoverInc(fl, declp, traceNameForLine(nodep, name));
|
||||
UASSERT_OBJ(condp, nodep, "No terms in expression coverage branch");
|
||||
AstIf* const ifp = new AstIf{fl, condp, newp, nullptr};
|
||||
ifp->user2(true);
|
||||
|
||||
Reference in New Issue
Block a user