Skip to content

Commit

Permalink
Support #0
Browse files Browse the repository at this point in the history
Signed-off-by: Krzysztof Bieganski <[email protected]>
  • Loading branch information
kbieganski committed Oct 25, 2023
1 parent cf6e362 commit 600b720
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 11 deletions.
6 changes: 6 additions & 0 deletions src/V3AstNodeOther.h
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,8 @@ class AstNetlist final : public AstNode {
AstVar* m_delaySchedulerp = nullptr; // The delay scheduler variable
AstVarScope* m_nbaEventp = nullptr; // The NBA event variable
AstVarScope* m_nbaEventTriggerp = nullptr; // If set to 1, the NBA event should get triggered
AstVarScope* m_inactiveEventp = nullptr; // The Inactive event variable
AstVarScope* m_inactiveEventTriggerp = nullptr; // If set to 1, the Inactive event should get triggered
AstTopScope* m_topScopep = nullptr; // The singleton AstTopScope under the top module
VTimescale m_timeunit; // Global time unit
VTimescale m_timeprecision; // Global time precision
Expand Down Expand Up @@ -1230,6 +1232,10 @@ class AstNetlist final : public AstNode {
void nbaEventp(AstVarScope* const varScopep) { m_nbaEventp = varScopep; }
AstVarScope* nbaEventTriggerp() const { return m_nbaEventTriggerp; }
void nbaEventTriggerp(AstVarScope* const varScopep) { m_nbaEventTriggerp = varScopep; }
AstVarScope* inactiveEventp() const { return m_inactiveEventp; }
void inactiveEventp(AstVarScope* const varScopep) { m_inactiveEventp = varScopep; }
AstVarScope* inactiveEventTriggerp() const { return m_inactiveEventTriggerp; }
void inactiveEventTriggerp(AstVarScope* const varScopep) { m_inactiveEventTriggerp = varScopep; }
void stdPackagep(AstPackage* const packagep) { m_stdPackagep = packagep; }
AstPackage* stdPackagep() const { return m_stdPackagep; }
AstTopScope* topScopep() const { return m_topScopep; }
Expand Down
22 changes: 20 additions & 2 deletions src/V3Sched.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ struct EvalLoop {
AstVarScope* continuep = nullptr;
// The loop itself and statements around it
AstNodeStmt* stmtsp = nullptr;
AstNodeIf* ifp = nullptr;
};

//============================================================================
Expand Down Expand Up @@ -653,6 +654,7 @@ EvalLoop makeEvalLoop(AstNetlist* netlistp, const string& tag, const string& nam
AstNodeStmt* nodep = nullptr;
if (v3Global.opt.profExec()) nodep = profExecSectionPush(flp, "loop " + tag);
nodep = AstNode::addNext(nodep, setVar(counterp, 0));
AstIf* ifp;
nodep->addNext(buildLoop(netlistp, continuep, [&](AstWhile* loopp) {
// Compute triggers
loopp->addStmtsp(computeTriggers());
Expand All @@ -661,7 +663,7 @@ EvalLoop makeEvalLoop(AstNetlist* netlistp, const string& tag, const string& nam
AstVarRef* const refp = new AstVarRef{flp, trigVscp, VAccess::READ};
AstCMethodHard* const callp = new AstCMethodHard{flp, refp, "any"};
callp->dtypeSetBit();
AstIf* const ifp = new AstIf{flp, callp};
ifp = new AstIf{flp, callp};
loopp->addStmtsp(ifp);
ifp->addThensp(setVar(continuep, 1));

Expand Down Expand Up @@ -707,7 +709,7 @@ EvalLoop makeEvalLoop(AstNetlist* netlistp, const string& tag, const string& nam

if (v3Global.opt.profExec()) nodep->addNext(profExecSectionPop(flp));

return {counterp, continuep, nodep};
return {counterp, continuep, nodep, ifp};
}

//============================================================================
Expand Down Expand Up @@ -953,6 +955,22 @@ void createEval(AstNetlist* netlistp, //
return resultp;
});

// If the Inactive event exists, trigger it in 'nba'
if (netlistp->inactiveEventp()) {
UASSERT(netlistp->inactiveEventTriggerp(), "NBA event trigger var should exist");
AstIf* const ifp
= new AstIf{flp, new AstVarRef{flp, netlistp->inactiveEventTriggerp(), VAccess::READ}};
ifp->addThensp(setVar(activeEvalLoop.continuep, 1));
ifp->addThensp(setVar(netlistp->inactiveEventTriggerp(), 0));
AstCMethodHard* const firep = new AstCMethodHard{
flp, new AstVarRef{flp, netlistp->inactiveEventp(), VAccess::WRITE}, "fire"};
firep->dtypeSetVoid();
ifp->addThensp(firep->makeStmt());
activeEvalLoop.ifp->addElsesp(ifp);
netlistp->inactiveEventp(nullptr);
netlistp->inactiveEventTriggerp(nullptr);
}

// Create the NBA eval loop. This uses the Active eval loop in the trigger section.
const auto& nbaEvalLoop = makeEvalLoop(
netlistp, "nba", "NBA", nbaKit.m_vscp, nbaKit.m_dumpp,
Expand Down
37 changes: 35 additions & 2 deletions src/V3Timing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,33 @@ class TimingControlVisitor final : public VNVisitor {
new AstVarRef{flp, m_netlistp->nbaEventTriggerp(), VAccess::WRITE},
new AstConst{flp, AstConst::BitTrue{}}};
}
// Creates the event variable to trigger in NBA region
AstEventControl* createInactiveEventControl(FileLine* flp) {
if (!m_netlistp->inactiveEventp()) {
auto* const inactiveEventDtp = new AstBasicDType{
m_scopeTopp->fileline(), VBasicDTypeKwd::EVENT, VSigning::UNSIGNED};
m_netlistp->typeTablep()->addTypesp(inactiveEventDtp);
m_netlistp->inactiveEventp(
m_scopeTopp->createTemp("__VinactiveEvent", inactiveEventDtp));
v3Global.setHasEvents();
}
return new AstEventControl{
flp,
new AstSenTree{flp, new AstSenItem{flp, VEdgeType::ET_EVENT,
new AstVarRef{flp, m_netlistp->inactiveEventp(),
VAccess::READ}}},
nullptr};
}
// Creates the variable that, if set, causes the NBA event to be triggered
AstAssign* createInactiveEventTriggerAssignment(FileLine* flp) {
if (!m_netlistp->inactiveEventTriggerp()) {
m_netlistp->inactiveEventTriggerp(
m_scopeTopp->createTemp("__VinactiveEventTrigger", 1));
}
return new AstAssign{
flp, new AstVarRef{flp, m_netlistp->inactiveEventTriggerp(), VAccess::WRITE},
new AstConst{flp, AstConst::BitTrue{}}};
}
// Returns true if we are under a class or the given tree has any references to locals. These
// are cases where static, globally-evaluated triggers are not suitable.
bool needDynamicTrigger(AstNode* const nodep) const {
Expand Down Expand Up @@ -877,8 +904,14 @@ class TimingControlVisitor final : public VNVisitor {
AstNodeExpr* valuep = V3Const::constifyEdit(nodep->lhsp()->unlinkFrBack());
auto* const constp = VN_CAST(valuep, Const);
if (constp && constp->isZero()) {
nodep->v3warn(ZERODLY, "Unsupported: #0 delays do not schedule process resumption in "
"the Inactive region");
AstEventControl* const eventControlp = createInactiveEventControl(flp);
if (AstNode* const stmtsp = nodep->stmtsp()) {
eventControlp->addStmtsp(stmtsp->unlinkFrBackWithNext());
}
nodep->addNextHere(eventControlp);
nodep->replaceWith(createInactiveEventTriggerAssignment(flp));
VL_DO_DANGLING(nodep->deleteTree(), nodep);
return;
} else {
// Scale the delay
if (valuep->dtypep()->isDouble()) {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0

scenarios(linter => 1);
scenarios(simulator => 1);

lint(
verilator_flags2 => ["--timing"],
fails => 1,
expect_filename => $Self->{golden_filename},
compile(
verilator_flags2 => ["--exe --main --timing"],
make_main => 0,
);

execute(
check_finished => 1,
);

ok(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ module t;
logic v = 0;
initial #1 begin
fork
#0 if (v) $finish;
else $stop;
#0 if (v) begin
$write("*-* All Finished *-*\n");
$finish;
end else $stop;
join_none
->e;
end
Expand Down

0 comments on commit 600b720

Please sign in to comment.