parent
b2093b513a
commit
96bffd49aa
|
|
@ -737,16 +737,14 @@ const TriggerKit createTriggers(AstNetlist* netlistp, AstCFunc* const initFuncp,
|
||||||
map[senTreep] = trigpSenp;
|
map[senTreep] = trigpSenp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the SenExprBuilder results
|
||||||
|
const SenExprBuilder::Results senResults = senExprBuilder.getAndClearResults();
|
||||||
|
|
||||||
// Add the init and update statements
|
// Add the init and update statements
|
||||||
for (AstNodeStmt* const nodep : senExprBuilder.getAndClearInits()) {
|
for (AstNodeStmt* const nodep : senResults.m_inits) initFuncp->addStmtsp(nodep);
|
||||||
initFuncp->addStmtsp(nodep);
|
for (AstNodeStmt* const nodep : senResults.m_postUpdates) funcp->addStmtsp(nodep);
|
||||||
}
|
if (!senResults.m_preUpdates.empty()) {
|
||||||
for (AstNodeStmt* const nodep : senExprBuilder.getAndClearPostUpdates()) {
|
for (AstNodeStmt* const nodep : vlstd::reverse_view(senResults.m_preUpdates)) {
|
||||||
funcp->addStmtsp(nodep);
|
|
||||||
}
|
|
||||||
const auto& preUpdates = senExprBuilder.getAndClearPreUpdates();
|
|
||||||
if (!preUpdates.empty()) {
|
|
||||||
for (AstNodeStmt* const nodep : vlstd::reverse_view(preUpdates)) {
|
|
||||||
UASSERT_OBJ(funcp->stmtsp(), funcp,
|
UASSERT_OBJ(funcp->stmtsp(), funcp,
|
||||||
"No statements in trigger eval function, but there are pre updates");
|
"No statements in trigger eval function, but there are pre updates");
|
||||||
funcp->stmtsp()->addHereThisAsNext(nodep);
|
funcp->stmtsp()->addHereThisAsNext(nodep);
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,19 @@
|
||||||
// AstSenTree have triggered
|
// AstSenTree have triggered
|
||||||
|
|
||||||
class SenExprBuilder final {
|
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
|
// STATE
|
||||||
AstScope* const m_scopep; // The scope
|
AstScope* const m_scopep; // The scope
|
||||||
|
|
||||||
std::vector<AstNodeStmt*> m_inits; // Initialization statements for previous values
|
Results m_results; // The builder result
|
||||||
std::vector<AstNodeStmt*> m_preUpdates; // Pre update assignments
|
|
||||||
std::vector<AstNodeStmt*> m_postUpdates; // Post update assignments
|
|
||||||
|
|
||||||
std::unordered_map<VNRef<AstNode>, AstVarScope*> m_prev; // The 'previous value' signals
|
std::unordered_map<VNRef<AstNode>, AstVarScope*> m_prev; // The 'previous value' signals
|
||||||
std::unordered_map<VNRef<AstNode>, AstVarScope*> m_curr; // The 'current 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
|
// Add pre update if it does not exist yet in this round
|
||||||
if (m_hasPreUpdate.emplace(*currp).second) {
|
if (m_hasPreUpdate.emplace(*currp).second) {
|
||||||
m_preUpdates.push_back(new AstAssign{flp, new AstVarRef{flp, currp, VAccess::WRITE},
|
m_results.m_preUpdates.push_back(new AstAssign{
|
||||||
exprp->cloneTree(false)});
|
flp, new AstVarRef{flp, currp, VAccess::WRITE}, exprp->cloneTree(false)});
|
||||||
}
|
}
|
||||||
return new AstVarRef{flp, currp, VAccess::READ};
|
return new AstVarRef{flp, currp, VAccess::READ};
|
||||||
}
|
}
|
||||||
|
|
@ -109,7 +116,7 @@ class SenExprBuilder final {
|
||||||
// Add the initializer init
|
// Add the initializer init
|
||||||
AstAssign* const initp = new AstAssign{flp, new AstVarRef{flp, prevp, VAccess::WRITE},
|
AstAssign* const initp = new AstAssign{flp, new AstVarRef{flp, prevp, VAccess::WRITE},
|
||||||
exprp->cloneTree(false)};
|
exprp->cloneTree(false)};
|
||||||
m_inits.push_back(initp);
|
m_results.m_inits.push_back(initp);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstVarScope* const prevp = pair.first->second;
|
AstVarScope* const prevp = pair.first->second;
|
||||||
|
|
@ -128,9 +135,9 @@ class SenExprBuilder final {
|
||||||
if (VN_IS(exprp->dtypep()->skipRefp(), UnpackArrayDType)) {
|
if (VN_IS(exprp->dtypep()->skipRefp(), UnpackArrayDType)) {
|
||||||
AstCMethodHard* const cmhp = new AstCMethodHard{flp, wrPrev(), "assign", rdCurr()};
|
AstCMethodHard* const cmhp = new AstCMethodHard{flp, wrPrev(), "assign", rdCurr()};
|
||||||
cmhp->dtypeSetVoid();
|
cmhp->dtypeSetVoid();
|
||||||
m_postUpdates.push_back(cmhp->makeStmt());
|
m_results.m_postUpdates.push_back(cmhp->makeStmt());
|
||||||
} else {
|
} 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
|
// No need to check if the event was fired, we need the flag clear regardless
|
||||||
AstCMethodHard* const clearp = new AstCMethodHard{flp, currp(), "clearFired"};
|
AstCMethodHard* const clearp = new AstCMethodHard{flp, currp(), "clearFired"};
|
||||||
clearp->dtypeSetVoid();
|
clearp->dtypeSetVoid();
|
||||||
m_postUpdates.push_back(clearp->makeStmt());
|
m_results.m_postUpdates.push_back(clearp->makeStmt());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'fired' state
|
// Get 'fired' state
|
||||||
|
|
@ -215,16 +222,12 @@ public:
|
||||||
return {resultp, firedAtInitialization};
|
return {resultp, firedAtInitialization};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AstNodeStmt*> getAndClearInits() { return std::move(m_inits); }
|
Results getAndClearResults() {
|
||||||
|
m_curr.clear();
|
||||||
std::vector<AstNodeStmt*> getAndClearPreUpdates() {
|
m_prev.clear();
|
||||||
m_hasPreUpdate.clear();
|
m_hasPreUpdate.clear();
|
||||||
return std::move(m_preUpdates);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<AstNodeStmt*> getAndClearPostUpdates() {
|
|
||||||
m_hasPostUpdate.clear();
|
m_hasPostUpdate.clear();
|
||||||
return std::move(m_postUpdates);
|
return std::move(m_results);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CONSTRUCTOR
|
// CONSTRUCTOR
|
||||||
|
|
|
||||||
|
|
@ -933,8 +933,10 @@ class TimingControlVisitor final : public VNVisitor {
|
||||||
UASSERT_OBJ(m_senExprBuilderp, nodep, "No SenExprBuilder for this scope");
|
UASSERT_OBJ(m_senExprBuilderp, nodep, "No SenExprBuilder for this scope");
|
||||||
auto* const assignp = new AstAssign{flp, new AstVarRef{flp, trigvscp, VAccess::WRITE},
|
auto* const assignp = new AstAssign{flp, new AstVarRef{flp, trigvscp, VAccess::WRITE},
|
||||||
m_senExprBuilderp->build(sensesp).first};
|
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
|
// 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);
|
nodep->addHereThisAsNext(stmtp);
|
||||||
}
|
}
|
||||||
// Create the trigger eval loop, which will await the evaluation step and check the
|
// 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}},
|
flp, new AstLogNot{flp, new AstVarRef{flp, trigvscp, VAccess::READ}},
|
||||||
awaitEvalp->makeStmt()};
|
awaitEvalp->makeStmt()};
|
||||||
// Put pre updates before the trigger check and assignment
|
// Put pre updates before the trigger check and assignment
|
||||||
for (AstNodeStmt* const stmtp : m_senExprBuilderp->getAndClearPreUpdates()) {
|
for (AstNodeStmt* const stmtp : senResults.m_preUpdates) loopp->addStmtsp(stmtp);
|
||||||
loopp->addStmtsp(stmtp);
|
|
||||||
}
|
|
||||||
// Then the trigger check and assignment
|
// Then the trigger check and assignment
|
||||||
loopp->addStmtsp(assignp);
|
loopp->addStmtsp(assignp);
|
||||||
// Let the dynamic trigger scheduler know if this trigger was set
|
// Let the dynamic trigger scheduler know if this trigger was set
|
||||||
|
|
@ -963,9 +963,7 @@ class TimingControlVisitor final : public VNVisitor {
|
||||||
loopp->addStmtsp(awaitPostUpdatep->makeStmt());
|
loopp->addStmtsp(awaitPostUpdatep->makeStmt());
|
||||||
}
|
}
|
||||||
// Put the post updates at the end of the loop
|
// Put the post updates at the end of the loop
|
||||||
for (AstNodeStmt* const stmtp : m_senExprBuilderp->getAndClearPostUpdates()) {
|
for (AstNodeStmt* const stmtp : senResults.m_postUpdates) loopp->addStmtsp(stmtp);
|
||||||
loopp->addStmtsp(stmtp);
|
|
||||||
}
|
|
||||||
// Finally, await the resumption step in 'act'
|
// Finally, await the resumption step in 'act'
|
||||||
AstCAwait* const awaitResumep = awaitEvalp->cloneTree(false);
|
AstCAwait* const awaitResumep = awaitEvalp->cloneTree(false);
|
||||||
VN_AS(awaitResumep->exprp(), CMethodHard)->name("resumption");
|
VN_AS(awaitResumep->exprp(), CMethodHard)->name("resumption");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue