Internals: Create if statements for triggers during scheduling (#6280) (#6581)

The AstIf nodes conditional on events being triggered used to be created
in V3Clock. Now it is in V3Sched*, in order to avoid having to pass
AstActive in CFunc or MTask bodies. No functional change intended, some
improved optimization due to simplifying timing triggers that were
previously missed, also fixes what seems like a bug in the original
timing commit code.
This commit is contained in:
Geza Lore
2025-10-27 10:41:30 +00:00
committed by GitHub
parent 6ec5c85bea
commit 60c532908e
10 changed files with 100 additions and 133 deletions
+3 -75
View File
@@ -1,6 +1,6 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
// DESCRIPTION: Verilator: Post scheduling transformations
//
// Code available from: https://verilator.org
//
@@ -15,15 +15,7 @@
//*************************************************************************
// V3Clock's Transformations:
//
// Top Scope:
// Check created ACTIVEs
// Compress adjacent ACTIVEs with same sensitivity list
// Form master _eval function
// Add around the SENTREE a (IF POSEDGE(..))
// Add a __Vlast_{clock} for the comparison
// Set the __Vlast_{clock} at the end of the block
// Replace UNTILSTABLEs with loops until specified signals become const.
// Create global calling function for any per-scope functions. (For FINALs).
// This pass is historic and does some arbitray post scheduling rewrites
//
//*************************************************************************
@@ -71,32 +63,7 @@ class ClockVisitor final : public VNVisitor {
// STATE
AstCFunc* const m_evalp = nullptr; // The '_eval' function
AstSenTree* m_lastSenp = nullptr; // Last sensitivity match, so we can detect duplicates.
AstIf* m_lastIfp = nullptr; // Last sensitivity if active to add more under
// METHODS
AstNodeExpr* createSenseEquation(AstSenItem* nodesp) {
AstNodeExpr* senEqnp = nullptr;
for (AstSenItem* senp = nodesp; senp; senp = VN_AS(senp->nextp(), SenItem)) {
UASSERT_OBJ(senp->edgeType() == VEdgeType::ET_TRUE, senp, "Should have been lowered");
if (senp->sensp()) {
AstNodeExpr* const senOnep = senp->sensp()->cloneTree(false);
senEqnp = senEqnp ? new AstOr{senp->fileline(), senEqnp, senOnep} : senOnep;
}
}
return senEqnp;
}
AstIf* makeActiveIf(AstSenTree* sentreep) {
AstNodeExpr* const senEqnp = createSenseEquation(sentreep->sensesp());
UASSERT_OBJ(senEqnp, sentreep, "No sense equation, shouldn't be in sequent activation.");
AstIf* const newifp = new AstIf{sentreep->fileline(), senEqnp};
return newifp;
}
void clearLastSen() {
m_lastSenp = nullptr;
m_lastIfp = nullptr;
}
// VISITORS
void visit(AstCoverToggle* nodep) override {
// UINFOTREE(1, nodep, "", "ct");
@@ -125,41 +92,7 @@ class ClockVisitor final : public VNVisitor {
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void visit(AstSenTree* nodep) override {
nodep->unlinkFrBack();
pushDeletep(nodep); // Delete it later, AstActives still pointing to it
}
void visit(AstActive* nodep) override {
UASSERT_OBJ(nodep->hasClocked(), nodep, "Should have been converted by V3Sched");
UASSERT_OBJ(nodep->stmtsp(), nodep, "Should not have been created if empty");
AstNode* const stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
// Create 'if' statement, if needed
if (!m_lastSenp || !nodep->sentreep()->sameTree(m_lastSenp)) {
VNRelinker relinker;
nodep->unlinkFrBack(&relinker);
clearLastSen();
m_lastSenp = nodep->sentreep();
// Make a new if statement
m_lastIfp = makeActiveIf(m_lastSenp);
relinker.relink(m_lastIfp);
} else {
nodep->unlinkFrBack();
}
// Move statements to if
m_lastIfp->addThensp(stmtsp);
// Dispose of the AstActive
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void visit(AstExecGraph* nodep) override {
for (AstMTaskBody* mtaskBodyp = nodep->mTaskBodiesp(); mtaskBodyp;
mtaskBodyp = VN_AS(mtaskBodyp->nextp(), MTaskBody)) {
clearLastSen();
iterate(mtaskBodyp);
}
clearLastSen();
pushDeletep(nodep->unlinkFrBack()); // No longer needed
}
//========== Move sampled assignments
@@ -187,11 +120,6 @@ public:
// CONSTRUCTORS
explicit ClockVisitor(AstNetlist* netlistp)
: m_evalp{netlistp->evalp()} {
// Simplify all SenTrees
for (AstSenTree* senTreep = netlistp->topScopep()->senTreesp(); senTreep;
senTreep = VN_AS(senTreep->nextp(), SenTree)) {
V3Const::constifyExpensiveEdit(senTreep);
}
iterate(netlistp);
}
~ClockVisitor() override = default;