From 7affb3e580ba72cffeb457aaca512aeb05d24080 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 23 Aug 2025 21:10:46 -0400 Subject: [PATCH] Internals: Add $past variable statistic --- src/V3Assert.cpp | 8 +++++++- src/V3AssertPre.cpp | 24 ++++++++++++------------ test_regress/t/t_past.py | 5 ++++- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 72279d547..a8a3b984f 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -23,7 +23,7 @@ VL_DEFINE_DEBUG_FUNCTIONS; //###################################################################### -// Assert class functions +// AssertVisitor class AssertVisitor final : public VNVisitor { // CONSTANTS @@ -48,6 +48,7 @@ class AssertVisitor final : public VNVisitor { VDouble0 m_statAsNotImm; // Statistic tracking VDouble0 m_statAsImm; // Statistic tracking VDouble0 m_statAsFull; // Statistic tracking + VDouble0 m_statPastVars; // Statistic tracking bool m_inSampled = false; // True inside a sampled expression // METHODS @@ -466,9 +467,13 @@ class AssertVisitor final : public VNVisitor { = new AstAlways{nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, nullptr}; m_modp->addStmtsp(alwaysp); for (uint32_t i = 0; i < ticks; ++i) { + // TODO recognize AstVarRef is getting delayed and share variables between + // $pasts with same reference (or same expression). Saves downstream + // optimizations from identifying and removing duplication. AstVar* const outvarp = new AstVar{ nodep->fileline(), VVarType::MODULETEMP, "_Vpast_" + cvtToStr(m_modPastNum++) + "_" + cvtToStr(i), inp->dtypep()}; + ++m_statPastVars; m_modp->addStmtsp(outvarp); AstNode* const assp = new AstAssignDly{ nodep->fileline(), new AstVarRef{nodep->fileline(), outvarp, VAccess::WRITE}, inp}; @@ -719,6 +724,7 @@ public: V3Stats::addStat("Assertions, assert immediate statements", m_statAsImm); V3Stats::addStat("Assertions, cover statements", m_statCover); V3Stats::addStat("Assertions, full/parallel case", m_statAsFull); + V3Stats::addStat("Assertions, $past variables", m_statPastVars); } }; diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index 7b6a21bc0..89fdc83b1 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -461,9 +461,9 @@ private: if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1}; AstSenTree* sentreep = nodep->sentreep(); if (sentreep) sentreep->unlinkFrBack(); - AstNodeExpr* const past = new AstPast{fl, exprp}; - past->dtypeFrom(exprp); - exprp = new AstAnd{fl, past, new AstNot{fl, exprp->cloneTreePure(false)}}; + AstNodeExpr* const pastp = new AstPast{fl, exprp}; + pastp->dtypeFrom(exprp); + exprp = new AstAnd{fl, pastp, new AstNot{fl, exprp->cloneTreePure(false)}}; exprp->dtypeSetBit(); nodep->replaceWith(exprp); nodep->sentreep(newSenTree(nodep, sentreep)); @@ -482,9 +482,9 @@ private: if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1}; AstSenTree* sentreep = nodep->sentreep(); if (sentreep) sentreep->unlinkFrBack(); - AstNodeExpr* const past = new AstPast{fl, exprp}; - past->dtypeFrom(exprp); - exprp = new AstAnd{fl, new AstNot{fl, past}, exprp->cloneTreePure(false)}; + AstNodeExpr* const pastp = new AstPast{fl, exprp}; + pastp->dtypeFrom(exprp); + exprp = new AstAnd{fl, new AstNot{fl, pastp}, exprp->cloneTreePure(false)}; exprp->dtypeSetBit(); nodep->replaceWith(exprp); nodep->sentreep(newSenTree(nodep, sentreep)); @@ -497,9 +497,9 @@ private: AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack(); AstSenTree* sentreep = nodep->sentreep(); if (sentreep) sentreep->unlinkFrBack(); - AstNodeExpr* const past = new AstPast{fl, exprp}; - past->dtypeFrom(exprp); - exprp = new AstEq{fl, past, exprp->cloneTreePure(false)}; + AstNodeExpr* const pastp = new AstPast{fl, exprp}; + pastp->dtypeFrom(exprp); + exprp = new AstEq{fl, pastp, exprp->cloneTreePure(false)}; exprp->dtypeSetBit(); nodep->replaceWith(exprp); nodep->sentreep(newSenTree(nodep, sentreep)); @@ -515,9 +515,9 @@ private: if (m_disablep) lhsp = new AstAnd{fl, new AstNot{fl, m_disablep}, lhsp}; - AstNodeExpr* const past = new AstPast{fl, lhsp}; - past->dtypeFrom(lhsp); - AstNodeExpr* const exprp = new AstOr{fl, new AstNot{fl, past}, rhsp}; + AstNodeExpr* const pastp = new AstPast{fl, lhsp}; + pastp->dtypeFrom(lhsp); + AstNodeExpr* const exprp = new AstOr{fl, new AstNot{fl, pastp}, rhsp}; exprp->dtypeSetBit(); nodep->replaceWith(exprp); nodep->sentreep(newSenTree(nodep)); diff --git a/test_regress/t/t_past.py b/test_regress/t/t_past.py index d4f986441..bd043aa76 100755 --- a/test_regress/t/t_past.py +++ b/test_regress/t/t_past.py @@ -11,8 +11,11 @@ import vltest_bootstrap test.scenarios('simulator') -test.compile() +test.compile(verilator_flags2=['--stats']) test.execute() +# Check that $past shared common variables +test.file_grep(test.stats, r'Assertions, \$past variables\s+(\d+)', 11) + test.passes()