Fix invalidating variable caches in SenExprBulider (#5834) (#5835)

This commit is contained in:
Geza Lore 2025-03-07 12:18:34 +00:00 committed by GitHub
parent b2093b513a
commit 96bffd49aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 33 deletions

View File

@ -737,16 +737,14 @@ const TriggerKit createTriggers(AstNetlist* netlistp, AstCFunc* const initFuncp,
map[senTreep] = trigpSenp;
}
// Get the SenExprBuilder results
const SenExprBuilder::Results senResults = senExprBuilder.getAndClearResults();
// Add the init and update statements
for (AstNodeStmt* const nodep : senExprBuilder.getAndClearInits()) {
initFuncp->addStmtsp(nodep);
}
for (AstNodeStmt* const nodep : senExprBuilder.getAndClearPostUpdates()) {
funcp->addStmtsp(nodep);
}
const auto& preUpdates = senExprBuilder.getAndClearPreUpdates();
if (!preUpdates.empty()) {
for (AstNodeStmt* const nodep : vlstd::reverse_view(preUpdates)) {
for (AstNodeStmt* const nodep : senResults.m_inits) initFuncp->addStmtsp(nodep);
for (AstNodeStmt* const nodep : senResults.m_postUpdates) funcp->addStmtsp(nodep);
if (!senResults.m_preUpdates.empty()) {
for (AstNodeStmt* const nodep : vlstd::reverse_view(senResults.m_preUpdates)) {
UASSERT_OBJ(funcp->stmtsp(), funcp,
"No statements in trigger eval function, but there are pre updates");
funcp->stmtsp()->addHereThisAsNext(nodep);

View File

@ -28,12 +28,19 @@
// AstSenTree have triggered
class SenExprBuilder final {
public:
// TYPES
struct Results final {
std::vector<AstNodeStmt*> m_inits; // Initialization statements for previous values
std::vector<AstNodeStmt*> m_preUpdates; // Pre update assignments
std::vector<AstNodeStmt*> m_postUpdates; // Post update assignments
};
private:
// STATE
AstScope* const m_scopep; // The scope
std::vector<AstNodeStmt*> m_inits; // Initialization statements for previous values
std::vector<AstNodeStmt*> m_preUpdates; // Pre update assignments
std::vector<AstNodeStmt*> m_postUpdates; // Post update assignments
Results m_results; // The builder result
std::unordered_map<VNRef<AstNode>, AstVarScope*> m_prev; // The 'previous value' signals
std::unordered_map<VNRef<AstNode>, AstVarScope*> m_curr; // The 'current value' signals
@ -90,8 +97,8 @@ class SenExprBuilder final {
// Add pre update if it does not exist yet in this round
if (m_hasPreUpdate.emplace(*currp).second) {
m_preUpdates.push_back(new AstAssign{flp, new AstVarRef{flp, currp, VAccess::WRITE},
exprp->cloneTree(false)});
m_results.m_preUpdates.push_back(new AstAssign{
flp, new AstVarRef{flp, currp, VAccess::WRITE}, exprp->cloneTree(false)});
}
return new AstVarRef{flp, currp, VAccess::READ};
}
@ -109,7 +116,7 @@ class SenExprBuilder final {
// Add the initializer init
AstAssign* const initp = new AstAssign{flp, new AstVarRef{flp, prevp, VAccess::WRITE},
exprp->cloneTree(false)};
m_inits.push_back(initp);
m_results.m_inits.push_back(initp);
}
AstVarScope* const prevp = pair.first->second;
@ -128,9 +135,9 @@ class SenExprBuilder final {
if (VN_IS(exprp->dtypep()->skipRefp(), UnpackArrayDType)) {
AstCMethodHard* const cmhp = new AstCMethodHard{flp, wrPrev(), "assign", rdCurr()};
cmhp->dtypeSetVoid();
m_postUpdates.push_back(cmhp->makeStmt());
m_results.m_postUpdates.push_back(cmhp->makeStmt());
} else {
m_postUpdates.push_back(new AstAssign{flp, wrPrev(), rdCurr()});
m_results.m_postUpdates.push_back(new AstAssign{flp, wrPrev(), rdCurr()});
}
}
@ -172,7 +179,7 @@ class SenExprBuilder final {
// No need to check if the event was fired, we need the flag clear regardless
AstCMethodHard* const clearp = new AstCMethodHard{flp, currp(), "clearFired"};
clearp->dtypeSetVoid();
m_postUpdates.push_back(clearp->makeStmt());
m_results.m_postUpdates.push_back(clearp->makeStmt());
}
// Get 'fired' state
@ -215,16 +222,12 @@ public:
return {resultp, firedAtInitialization};
}
std::vector<AstNodeStmt*> getAndClearInits() { return std::move(m_inits); }
std::vector<AstNodeStmt*> getAndClearPreUpdates() {
Results getAndClearResults() {
m_curr.clear();
m_prev.clear();
m_hasPreUpdate.clear();
return std::move(m_preUpdates);
}
std::vector<AstNodeStmt*> getAndClearPostUpdates() {
m_hasPostUpdate.clear();
return std::move(m_postUpdates);
return std::move(m_results);
}
// CONSTRUCTOR

View File

@ -933,8 +933,10 @@ class TimingControlVisitor final : public VNVisitor {
UASSERT_OBJ(m_senExprBuilderp, nodep, "No SenExprBuilder for this scope");
auto* const assignp = new AstAssign{flp, new AstVarRef{flp, trigvscp, VAccess::WRITE},
m_senExprBuilderp->build(sensesp).first};
// Get the SenExprBuilder results
const SenExprBuilder::Results senResults = m_senExprBuilderp->getAndClearResults();
// Put all and inits before the trigger eval loop
for (AstNodeStmt* const stmtp : m_senExprBuilderp->getAndClearInits()) {
for (AstNodeStmt* const stmtp : senResults.m_inits) {
nodep->addHereThisAsNext(stmtp);
}
// Create the trigger eval loop, which will await the evaluation step and check the
@ -943,9 +945,7 @@ class TimingControlVisitor final : public VNVisitor {
flp, new AstLogNot{flp, new AstVarRef{flp, trigvscp, VAccess::READ}},
awaitEvalp->makeStmt()};
// Put pre updates before the trigger check and assignment
for (AstNodeStmt* const stmtp : m_senExprBuilderp->getAndClearPreUpdates()) {
loopp->addStmtsp(stmtp);
}
for (AstNodeStmt* const stmtp : senResults.m_preUpdates) loopp->addStmtsp(stmtp);
// Then the trigger check and assignment
loopp->addStmtsp(assignp);
// Let the dynamic trigger scheduler know if this trigger was set
@ -963,9 +963,7 @@ class TimingControlVisitor final : public VNVisitor {
loopp->addStmtsp(awaitPostUpdatep->makeStmt());
}
// Put the post updates at the end of the loop
for (AstNodeStmt* const stmtp : m_senExprBuilderp->getAndClearPostUpdates()) {
loopp->addStmtsp(stmtp);
}
for (AstNodeStmt* const stmtp : senResults.m_postUpdates) loopp->addStmtsp(stmtp);
// Finally, await the resumption step in 'act'
AstCAwait* const awaitResumep = awaitEvalp->cloneTree(false);
VN_AS(awaitResumep->exprp(), CMethodHard)->name("resumption");