mirror of
https://github.com/verilator/verilator.git
synced 2025-01-06 06:37:45 +00:00
parent
75a44e5aa9
commit
6012ec8eb7
@ -170,22 +170,25 @@ AstNodeStmt* profExecSectionPop(FileLine* flp) {
|
|||||||
struct EvalLoop {
|
struct EvalLoop {
|
||||||
// Flag set to true during the first iteration of the loop
|
// Flag set to true during the first iteration of the loop
|
||||||
AstVarScope* firstIterp;
|
AstVarScope* firstIterp;
|
||||||
// The loop continuation flag (set to true to loop again)
|
|
||||||
AstVarScope* continuep = nullptr;
|
|
||||||
// The loop itself and statements around it
|
// The loop itself and statements around it
|
||||||
AstNodeStmt* stmtsp = nullptr;
|
AstNodeStmt* stmtsp = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create an eval loop with all the trimmings.
|
// Create an eval loop with all the trimmings.
|
||||||
EvalLoop createEvalLoop(AstNetlist* netlistp, //
|
EvalLoop createEvalLoop(
|
||||||
const std::string& tag, // Tag for current phase
|
AstNetlist* netlistp, //
|
||||||
const string& name, // Name of current phase
|
const std::string& tag, // Tag for current phase
|
||||||
bool slow, // Should create slow functions
|
const string& name, // Name of current phase
|
||||||
AstVarScope* trigp, // The trigger vector
|
bool slow, // Should create slow functions
|
||||||
AstCFunc* dumpFuncp, // Trigger dump function for debugging only
|
AstVarScope* trigp, // The trigger vector
|
||||||
AstNodeStmt* innerp, // The inner loop, if any
|
AstCFunc* dumpFuncp, // Trigger dump function for debugging only
|
||||||
AstNodeStmt* phasePrepp, // Prep statements run before checking triggers
|
AstNodeStmt* innerp, // The inner loop, if any
|
||||||
AstNodeStmt* phaseWorkp // The work to do if anything triggered
|
AstNodeStmt* phasePrepp, // Prep statements run before checking triggers
|
||||||
|
AstNodeStmt* phaseWorkp, // The work to do if anything triggered
|
||||||
|
// Extra statements to run after the work, even if no triggers fired. This function is
|
||||||
|
// passed a variable, which must be set to true if we must continue and loop again,
|
||||||
|
// and must be unmodified otherwise.
|
||||||
|
std::function<AstNodeStmt*(AstVarScope*)> phaseExtra = [](AstVarScope*) { return nullptr; } //
|
||||||
) {
|
) {
|
||||||
const std::string varPrefix = "__V" + tag;
|
const std::string varPrefix = "__V" + tag;
|
||||||
AstScope* const scopeTopp = netlistp->topScopep()->scopep();
|
AstScope* const scopeTopp = netlistp->topScopep()->scopep();
|
||||||
@ -213,6 +216,9 @@ EvalLoop createEvalLoop(AstNetlist* netlistp, //
|
|||||||
ifp->addThensp(phaseWorkp);
|
ifp->addThensp(phaseWorkp);
|
||||||
phaseFuncp->addStmtsp(ifp);
|
phaseFuncp->addStmtsp(ifp);
|
||||||
|
|
||||||
|
// Construct the extra statements
|
||||||
|
if (AstNodeStmt* const extrap = phaseExtra(executeFlagp)) phaseFuncp->addStmtsp(extrap);
|
||||||
|
|
||||||
// The function returns ture iff it did run the work
|
// The function returns ture iff it did run the work
|
||||||
phaseFuncp->rtnType("bool");
|
phaseFuncp->rtnType("bool");
|
||||||
phaseFuncp->addStmtsp(
|
phaseFuncp->addStmtsp(
|
||||||
@ -272,7 +278,7 @@ EvalLoop createEvalLoop(AstNetlist* netlistp, //
|
|||||||
// Prof-exec section pop
|
// Prof-exec section pop
|
||||||
if (v3Global.opt.profExec()) stmtps->addNext(profExecSectionPop(flp));
|
if (v3Global.opt.profExec()) stmtps->addNext(profExecSectionPop(flp));
|
||||||
|
|
||||||
return {firstIterFlagp, continueFlagp, stmtps};
|
return {firstIterFlagp, stmtps};
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
@ -1011,25 +1017,27 @@ void createEval(AstNetlist* netlistp, //
|
|||||||
workp->addNext(createTriggerClearCall(flp, nbaKit.m_vscp));
|
workp->addNext(createTriggerClearCall(flp, nbaKit.m_vscp));
|
||||||
//
|
//
|
||||||
return workp;
|
return workp;
|
||||||
}());
|
}(),
|
||||||
|
// Extra work (not conditional on having had a fired trigger)
|
||||||
|
[&](AstVarScope* continuep) -> AstNodeStmt* {
|
||||||
|
// Check if any dynamic NBAs are pending, if there are any in the design
|
||||||
|
if (!netlistp->nbaEventp()) return nullptr;
|
||||||
|
AstVarScope* const nbaEventp = netlistp->nbaEventp();
|
||||||
|
AstVarScope* const nbaEventTriggerp = netlistp->nbaEventTriggerp();
|
||||||
|
UASSERT(nbaEventTriggerp, "NBA event trigger var should exist");
|
||||||
|
netlistp->nbaEventp(nullptr);
|
||||||
|
netlistp->nbaEventTriggerp(nullptr);
|
||||||
|
|
||||||
// If the NBA event exists, trigger it in 'nba'
|
// If a dynamic NBA is pending, clear the pending flag and fire the commit event
|
||||||
if (AstVarScope* const nbaEventp = netlistp->nbaEventp()) {
|
AstIf* const ifp = new AstIf{flp, new AstVarRef{flp, nbaEventTriggerp, VAccess::READ}};
|
||||||
AstVarScope* const nbaEventTriggerp = netlistp->nbaEventTriggerp();
|
ifp->addThensp(setVar(continuep, 1));
|
||||||
UASSERT(nbaEventTriggerp, "NBA event trigger var should exist");
|
ifp->addThensp(setVar(nbaEventTriggerp, 0));
|
||||||
netlistp->nbaEventp(nullptr);
|
AstCMethodHard* const firep
|
||||||
netlistp->nbaEventTriggerp(nullptr);
|
= new AstCMethodHard{flp, new AstVarRef{flp, nbaEventp, VAccess::WRITE}, "fire"};
|
||||||
|
firep->dtypeSetVoid();
|
||||||
AstIf* const ifp = new AstIf{flp, new AstVarRef{flp, nbaEventTriggerp, VAccess::READ}};
|
ifp->addThensp(firep->makeStmt());
|
||||||
ifp->addThensp(setVar(topLoop.continuep, 1));
|
return ifp;
|
||||||
ifp->addThensp(setVar(nbaEventTriggerp, 0));
|
});
|
||||||
AstCMethodHard* const firep
|
|
||||||
= new AstCMethodHard{flp, new AstVarRef{flp, nbaEventp, VAccess::WRITE}, "fire"};
|
|
||||||
firep->dtypeSetVoid();
|
|
||||||
ifp->addThensp(firep->makeStmt());
|
|
||||||
// actLoop.stmtsp happens to be the head of the loop body inside the NBA loop...
|
|
||||||
actLoop.stmtsp->addNext(ifp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!obsKit.empty()) {
|
if (!obsKit.empty()) {
|
||||||
// Create the Observed eval loop, which becomes the top level loop.
|
// Create the Observed eval loop, which becomes the top level loop.
|
||||||
|
Loading…
Reference in New Issue
Block a user