Internals: Add $past variable statistic
This commit is contained in:
parent
b226be7f98
commit
7affb3e580
|
|
@ -23,7 +23,7 @@
|
||||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Assert class functions
|
// AssertVisitor
|
||||||
|
|
||||||
class AssertVisitor final : public VNVisitor {
|
class AssertVisitor final : public VNVisitor {
|
||||||
// CONSTANTS
|
// CONSTANTS
|
||||||
|
|
@ -48,6 +48,7 @@ class AssertVisitor final : public VNVisitor {
|
||||||
VDouble0 m_statAsNotImm; // Statistic tracking
|
VDouble0 m_statAsNotImm; // Statistic tracking
|
||||||
VDouble0 m_statAsImm; // Statistic tracking
|
VDouble0 m_statAsImm; // Statistic tracking
|
||||||
VDouble0 m_statAsFull; // Statistic tracking
|
VDouble0 m_statAsFull; // Statistic tracking
|
||||||
|
VDouble0 m_statPastVars; // Statistic tracking
|
||||||
bool m_inSampled = false; // True inside a sampled expression
|
bool m_inSampled = false; // True inside a sampled expression
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|
@ -466,9 +467,13 @@ class AssertVisitor final : public VNVisitor {
|
||||||
= new AstAlways{nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, nullptr};
|
= new AstAlways{nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, nullptr};
|
||||||
m_modp->addStmtsp(alwaysp);
|
m_modp->addStmtsp(alwaysp);
|
||||||
for (uint32_t i = 0; i < ticks; ++i) {
|
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{
|
AstVar* const outvarp = new AstVar{
|
||||||
nodep->fileline(), VVarType::MODULETEMP,
|
nodep->fileline(), VVarType::MODULETEMP,
|
||||||
"_Vpast_" + cvtToStr(m_modPastNum++) + "_" + cvtToStr(i), inp->dtypep()};
|
"_Vpast_" + cvtToStr(m_modPastNum++) + "_" + cvtToStr(i), inp->dtypep()};
|
||||||
|
++m_statPastVars;
|
||||||
m_modp->addStmtsp(outvarp);
|
m_modp->addStmtsp(outvarp);
|
||||||
AstNode* const assp = new AstAssignDly{
|
AstNode* const assp = new AstAssignDly{
|
||||||
nodep->fileline(), new AstVarRef{nodep->fileline(), outvarp, VAccess::WRITE}, inp};
|
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, assert immediate statements", m_statAsImm);
|
||||||
V3Stats::addStat("Assertions, cover statements", m_statCover);
|
V3Stats::addStat("Assertions, cover statements", m_statCover);
|
||||||
V3Stats::addStat("Assertions, full/parallel case", m_statAsFull);
|
V3Stats::addStat("Assertions, full/parallel case", m_statAsFull);
|
||||||
|
V3Stats::addStat("Assertions, $past variables", m_statPastVars);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -461,9 +461,9 @@ private:
|
||||||
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
|
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
|
||||||
AstSenTree* sentreep = nodep->sentreep();
|
AstSenTree* sentreep = nodep->sentreep();
|
||||||
if (sentreep) sentreep->unlinkFrBack();
|
if (sentreep) sentreep->unlinkFrBack();
|
||||||
AstNodeExpr* const past = new AstPast{fl, exprp};
|
AstNodeExpr* const pastp = new AstPast{fl, exprp};
|
||||||
past->dtypeFrom(exprp);
|
pastp->dtypeFrom(exprp);
|
||||||
exprp = new AstAnd{fl, past, new AstNot{fl, exprp->cloneTreePure(false)}};
|
exprp = new AstAnd{fl, pastp, new AstNot{fl, exprp->cloneTreePure(false)}};
|
||||||
exprp->dtypeSetBit();
|
exprp->dtypeSetBit();
|
||||||
nodep->replaceWith(exprp);
|
nodep->replaceWith(exprp);
|
||||||
nodep->sentreep(newSenTree(nodep, sentreep));
|
nodep->sentreep(newSenTree(nodep, sentreep));
|
||||||
|
|
@ -482,9 +482,9 @@ private:
|
||||||
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
|
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
|
||||||
AstSenTree* sentreep = nodep->sentreep();
|
AstSenTree* sentreep = nodep->sentreep();
|
||||||
if (sentreep) sentreep->unlinkFrBack();
|
if (sentreep) sentreep->unlinkFrBack();
|
||||||
AstNodeExpr* const past = new AstPast{fl, exprp};
|
AstNodeExpr* const pastp = new AstPast{fl, exprp};
|
||||||
past->dtypeFrom(exprp);
|
pastp->dtypeFrom(exprp);
|
||||||
exprp = new AstAnd{fl, new AstNot{fl, past}, exprp->cloneTreePure(false)};
|
exprp = new AstAnd{fl, new AstNot{fl, pastp}, exprp->cloneTreePure(false)};
|
||||||
exprp->dtypeSetBit();
|
exprp->dtypeSetBit();
|
||||||
nodep->replaceWith(exprp);
|
nodep->replaceWith(exprp);
|
||||||
nodep->sentreep(newSenTree(nodep, sentreep));
|
nodep->sentreep(newSenTree(nodep, sentreep));
|
||||||
|
|
@ -497,9 +497,9 @@ private:
|
||||||
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
|
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
|
||||||
AstSenTree* sentreep = nodep->sentreep();
|
AstSenTree* sentreep = nodep->sentreep();
|
||||||
if (sentreep) sentreep->unlinkFrBack();
|
if (sentreep) sentreep->unlinkFrBack();
|
||||||
AstNodeExpr* const past = new AstPast{fl, exprp};
|
AstNodeExpr* const pastp = new AstPast{fl, exprp};
|
||||||
past->dtypeFrom(exprp);
|
pastp->dtypeFrom(exprp);
|
||||||
exprp = new AstEq{fl, past, exprp->cloneTreePure(false)};
|
exprp = new AstEq{fl, pastp, exprp->cloneTreePure(false)};
|
||||||
exprp->dtypeSetBit();
|
exprp->dtypeSetBit();
|
||||||
nodep->replaceWith(exprp);
|
nodep->replaceWith(exprp);
|
||||||
nodep->sentreep(newSenTree(nodep, sentreep));
|
nodep->sentreep(newSenTree(nodep, sentreep));
|
||||||
|
|
@ -515,9 +515,9 @@ private:
|
||||||
|
|
||||||
if (m_disablep) lhsp = new AstAnd{fl, new AstNot{fl, m_disablep}, lhsp};
|
if (m_disablep) lhsp = new AstAnd{fl, new AstNot{fl, m_disablep}, lhsp};
|
||||||
|
|
||||||
AstNodeExpr* const past = new AstPast{fl, lhsp};
|
AstNodeExpr* const pastp = new AstPast{fl, lhsp};
|
||||||
past->dtypeFrom(lhsp);
|
pastp->dtypeFrom(lhsp);
|
||||||
AstNodeExpr* const exprp = new AstOr{fl, new AstNot{fl, past}, rhsp};
|
AstNodeExpr* const exprp = new AstOr{fl, new AstNot{fl, pastp}, rhsp};
|
||||||
exprp->dtypeSetBit();
|
exprp->dtypeSetBit();
|
||||||
nodep->replaceWith(exprp);
|
nodep->replaceWith(exprp);
|
||||||
nodep->sentreep(newSenTree(nodep));
|
nodep->sentreep(newSenTree(nodep));
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,11 @@ import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
|
||||||
test.compile()
|
test.compile(verilator_flags2=['--stats'])
|
||||||
|
|
||||||
test.execute()
|
test.execute()
|
||||||
|
|
||||||
|
# Check that $past shared common variables
|
||||||
|
test.file_grep(test.stats, r'Assertions, \$past variables\s+(\d+)', 11)
|
||||||
|
|
||||||
test.passes()
|
test.passes()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue