Add ternary operator into branch coverage (#5880)

This commit is contained in:
Ryszard Rozak
2025-05-19 09:35:35 -04:00
committed by GitHub
parent ad08302e5f
commit bed0456eca
13 changed files with 1907 additions and 644 deletions
+73 -8
View File
@@ -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));