mirror of
https://github.com/verilator/verilator.git
synced 2026-08-30 01:38:21 +02:00
Add ternary operator into branch coverage (#5880)
This commit is contained in:
+73
-8
@@ -142,6 +142,7 @@ class CoverageVisitor final : public VNVisitor {
|
||||
bool m_objective = false; // Expression objective
|
||||
bool m_ifCond = false; // Visiting if condition
|
||||
bool m_inToggleOff = false; // In function/task etc
|
||||
bool m_inLoopNotBody = false; // Inside a loop, but not in its body
|
||||
string m_beginHier; // AstBegin hier name for user coverage points
|
||||
|
||||
// STATE - cleared each module
|
||||
@@ -290,7 +291,28 @@ class CoverageVisitor final : public VNVisitor {
|
||||
// we can cover expressions in while loops, but the counting goes outside
|
||||
// the while, see: "minimally-intelligent decision about ... clock domain"
|
||||
// in the Toggle Coverage docs
|
||||
void visit(AstWhile* nodep) override { iterateProcedure(nodep, false); }
|
||||
void visit(AstWhile* nodep) override {
|
||||
VL_RESTORER(m_state);
|
||||
VL_RESTORER(m_inToggleOff);
|
||||
m_inToggleOff = true;
|
||||
createHandle(nodep);
|
||||
{
|
||||
VL_RESTORER(m_inLoopNotBody);
|
||||
m_inLoopNotBody = true;
|
||||
iterateAndNextNull(nodep->precondsp());
|
||||
iterateNull(nodep->condp());
|
||||
iterateAndNextNull(nodep->incsp());
|
||||
}
|
||||
iterateAndNextNull(nodep->stmtsp());
|
||||
if (m_state.lineCoverageOn(nodep)) {
|
||||
lineTrack(nodep);
|
||||
AstNode* const newp
|
||||
= newCoverInc(nodep->fileline(), "", "v_line", "block", linesCov(m_state, nodep),
|
||||
0, traceNameForLine(nodep, "block"));
|
||||
insertProcStatement(nodep, newp);
|
||||
}
|
||||
}
|
||||
|
||||
void visit(AstNodeFTask* nodep) override {
|
||||
if (!nodep->dpiImport()) iterateProcedure(nodep);
|
||||
}
|
||||
@@ -312,11 +334,11 @@ class CoverageVisitor final : public VNVisitor {
|
||||
nodep->v3fatalSrc("Bad node type");
|
||||
}
|
||||
}
|
||||
void iterateProcedure(AstNode* nodep, bool exprProc = true) {
|
||||
void iterateProcedure(AstNode* nodep) {
|
||||
VL_RESTORER(m_state);
|
||||
VL_RESTORER(m_exprStmtsp);
|
||||
VL_RESTORER(m_inToggleOff);
|
||||
if (exprProc) m_exprStmtsp = nodep;
|
||||
m_exprStmtsp = nodep;
|
||||
m_inToggleOff = true;
|
||||
createHandle(nodep);
|
||||
iterateChildren(nodep);
|
||||
@@ -482,8 +504,56 @@ class CoverageVisitor final : public VNVisitor {
|
||||
<< dtypep->prettyTypeName());
|
||||
}
|
||||
}
|
||||
bool includeCondToBranchRecursive(const AstNode* const nodep) {
|
||||
const AstNode* const backp = nodep->backp();
|
||||
if (VN_IS(backp, Cond) && VN_AS(backp, Cond)->condp() != nodep) {
|
||||
return includeCondToBranchRecursive(backp);
|
||||
} else if (VN_IS(backp, Sel) && VN_AS(backp, Sel)->fromp() == nodep) {
|
||||
return includeCondToBranchRecursive(backp);
|
||||
} else if (VN_IS(backp, NodeAssign) && VN_AS(backp, NodeAssign)->rhsp() == nodep
|
||||
&& !m_inLoopNotBody) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// VISITORS - LINE COVERAGE
|
||||
void visit(AstCond* nodep) override {
|
||||
UINFO(4, " COND: " << nodep << endl);
|
||||
|
||||
if (m_seeking == NONE) coverExprs(nodep->condp());
|
||||
|
||||
if (m_state.lineCoverageOn(nodep) && VN_IS(m_modp, Module)
|
||||
&& includeCondToBranchRecursive(nodep)) {
|
||||
VL_RESTORER(m_seeking);
|
||||
// Disable expression coverage in sub-expressions, since they were already visited
|
||||
m_seeking = ABORTED;
|
||||
|
||||
const CheckState lastState = m_state;
|
||||
createHandle(nodep);
|
||||
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});
|
||||
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});
|
||||
|
||||
m_state = lastState;
|
||||
} else {
|
||||
lineTrack(nodep);
|
||||
}
|
||||
}
|
||||
// Note not AstNodeIf; other types don't get covered
|
||||
void visit(AstIf* nodep) override {
|
||||
if (nodep->user2()) return;
|
||||
@@ -904,11 +974,6 @@ class CoverageVisitor final : public VNVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
void visit(AstCond* nodep) override {
|
||||
if (m_seeking == NONE) coverExprs(nodep->condp());
|
||||
lineTrack(nodep);
|
||||
}
|
||||
|
||||
void visit(AstFuncRef* nodep) override {
|
||||
if (nodep->taskp()->lifetime().isAutomatic()) {
|
||||
visit(static_cast<AstNodeExpr*>(nodep));
|
||||
|
||||
Reference in New Issue
Block a user