Skip to content

Commit

Permalink
Limit forked NBAs
Browse files Browse the repository at this point in the history
Signed-off-by: Krzysztof Bieganski <[email protected]>
  • Loading branch information
kbieganski committed Nov 14, 2023
1 parent 72f94c4 commit 3f14daa
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 20 deletions.
11 changes: 2 additions & 9 deletions src/V3SchedTiming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,23 +287,17 @@ void transformForks(AstNetlist* const netlistp) {
const VNUser2InUse user2InUse; // AstVarScope -> AstVarScope: var to remap to
funcp->foreach([&](AstNodeVarRef* refp) {
AstVar* const varp = refp->varp();
AstBasicDType* const dtypep = varp->dtypep()->basicp();
bool passByValue = false;
if (!varp->isFuncLocal()) {
if (VString::startsWith(varp->name(), "__Vintra")) {
// Pass it by value to the new function, as otherwise there are issues with
// -flocalize (see t_timing_intra_assign)
passByValue = true;
} else {
// Not func local. Its lifetime is longer than the forked process. Skip
return;
}
} else if (!varp->user1()) {
// Not declared before the fork. It cannot outlive the forked process
return;
} else if (dtypep && dtypep->isForkSync()) {
// We can just pass it by value to the new function
passByValue = true;
}
// Remap the reference
AstVarScope* const vscp = refp->varScopep();
Expand All @@ -312,14 +306,13 @@ void transformForks(AstNetlist* const netlistp) {
AstVar* const newvarp
= new AstVar{varp->fileline(), VVarType::BLOCKTEMP, varp->name(), varp};
newvarp->funcLocal(true);
newvarp->direction(passByValue ? VDirection::INPUT : VDirection::REF);
newvarp->direction(VDirection::INPUT);
funcp->addArgsp(newvarp);
AstVarScope* const newvscp
= new AstVarScope{newvarp->fileline(), funcp->scopep(), newvarp};
funcp->scopep()->addVarsp(newvscp);
vscp->user2p(newvscp);
callp->addArgsp(new AstVarRef{
refp->fileline(), vscp, passByValue ? VAccess::READ : VAccess::READWRITE});
callp->addArgsp(new AstVarRef{refp->fileline(), vscp, VAccess::READ});
}
AstVarScope* const newvscp = VN_AS(vscp->user2p(), VarScope);
refp->varScopep(newvscp);
Expand Down
33 changes: 23 additions & 10 deletions src/V3Timing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,7 @@ class TimingControlVisitor final : public VNVisitor {
void visit(AstNodeAssign* nodep) override {
// Only process once to avoid infinite loops (due to the net delay)
if (nodep->user1SetOnce()) return;
bool directlyUnderFork = VN_IS(nodep->backp(), Fork) && !nodep->nextp();
FileLine* const flp = nodep->fileline();
AstNode* controlp = factorOutTimingControl(nodep);
const bool inAssignDly = VN_IS(nodep, AssignDly);
Expand All @@ -1027,16 +1028,28 @@ class TimingControlVisitor final : public VNVisitor {
// do that. These intra-assignment vars will later be passed to forked processes by value.
AstNode* insertBeforep = m_underProcedure ? nullptr : controlp;
// Special case for NBA
if (inAssignDly && !m_underProcedure) {
// If it's in a function, it won't be handled by V3Delayed
// Put it behind an additional named event that gets triggered in the NBA region
AstEventControl* const nbaEventControlp = createNbaEventControl(flp);
AstAssign* const trigAssignp = createNbaEventTriggerAssignment(flp);
nodep->replaceWith(trigAssignp);
trigAssignp->addNextHere(nbaEventControlp);
nbaEventControlp->addStmtsp(nodep);
insertBeforep = controlp;
if (!controlp) controlp = nbaEventControlp;
if (inAssignDly) {
// Put it in a fork so it doesn't block
AstFork* forkp = nullptr;
if (!directlyUnderFork) {
forkp = new AstFork{flp, "", nullptr};
forkp->joinType(VJoinType::JOIN_NONE);
}
if (!m_underProcedure) {
// If it's in a function, it won't be handled by V3Delayed
// Put it behind an additional named event that gets triggered in the NBA region
AstEventControl* const nbaEventControlp = createNbaEventControl(flp);
AstAssign* const trigAssignp = createNbaEventTriggerAssignment(flp);
nodep->replaceWith(trigAssignp);
trigAssignp->addNextHere(nbaEventControlp);
nbaEventControlp->addStmtsp(nodep);
if (forkp) insertBeforep = forkp;
if (!controlp) controlp = nbaEventControlp;
}
if (forkp) {
controlp->replaceWith(forkp);
forkp->addStmtsp(controlp);
}
}
UASSERT_OBJ(nodep, controlp, "Assignment should have timing control");
addCLocalScope(flp, insertBeforep);
Expand Down
4 changes: 3 additions & 1 deletion src/V3Width.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4776,7 +4776,9 @@ class WidthVisitor final : public VNVisitor {
}
if (nodep->fileline()->timingOn() && v3Global.opt.timing().isSetTrue()
&& (m_ftaskp || nodep->timingControlp()) && VN_IS(nodep, AssignDly)
&& !VN_IS(nodep->backp(), Fork)) {
&& !VN_IS(nodep->backp(), Fork) && nodep->lhsp()->exists([](AstVarRef* refp) {
return refp->varp()->isFuncLocal();
})) {
auto* forkp = new AstFork{nodep->fileline(), "", nullptr};
forkp->joinType(VJoinType::JOIN_NONE);
nodep->replaceWith(forkp);
Expand Down

0 comments on commit 3f14daa

Please sign in to comment.