Fix disabling nested fork..join_none
This commit is contained in:
parent
6f154fa1ba
commit
6b330ee5b5
|
|
@ -608,7 +608,7 @@ class ForkVisitor final : public VNVisitor {
|
|||
}
|
||||
if (insertBeforep == firstStmtp->nextp()) return;
|
||||
|
||||
AstNode* const delayp = firstStmtp->unlinkFrBackWithNext();
|
||||
AstNode* const delayp = firstStmtp->unlinkFrBack();
|
||||
if (insertBeforep) {
|
||||
insertBeforep->addHereThisAsNext(delayp);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -742,9 +742,19 @@ class TimingControlVisitor final : public VNVisitor {
|
|||
addDebugInfo(donep);
|
||||
beginp->addStmtsp(donep->makeStmt());
|
||||
}
|
||||
static bool hasDisableQueuePushSelfPrefix(const AstBegin* const beginp) {
|
||||
// LinkJump prepends disable-by-name registration as:
|
||||
// __VprocessQueue_*.push_back(std::process::self())
|
||||
const AstStmtExpr* const stmtExprp = VN_CAST(beginp->stmtsp(), StmtExpr);
|
||||
if (!stmtExprp) return false;
|
||||
const AstCMethodHard* const methodp = VN_CAST(stmtExprp->exprp(), CMethodHard);
|
||||
if (!methodp || methodp->name() != "push_back") return false;
|
||||
const AstVarRef* const queueRefp = VN_CAST(methodp->fromp(), VarRef);
|
||||
return queueRefp && queueRefp->name().rfind("__VprocessQueue_", 0) == 0;
|
||||
}
|
||||
// Register a callback so killing a process-backed fork branch decrements the join counter
|
||||
void addForkOnKill(AstBegin* const beginp, AstVarScope* const forkVscp) const {
|
||||
if (!beginp->needProcess()) return;
|
||||
if (!beginp->needProcess() && !hasDisableQueuePushSelfPrefix(beginp)) return;
|
||||
FileLine* const flp = beginp->fileline();
|
||||
AstCMethodHard* const onKillp = new AstCMethodHard{
|
||||
flp, new AstVarRef{flp, forkVscp, VAccess::WRITE}, VCMethod::FORK_ON_KILL};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,17 @@
|
|||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
int w = 0;
|
||||
int jf = 0;
|
||||
int ddj = 0;
|
||||
int ddja = 0;
|
||||
int ddjn = 0;
|
||||
int dj_done = 0;
|
||||
int dja_done = 0;
|
||||
int djn_done = 0;
|
||||
int race_disable = 0;
|
||||
int nd = 0;
|
||||
|
||||
task increment_x;
|
||||
x++;
|
||||
|
|
@ -73,6 +84,168 @@ module t;
|
|||
#3;
|
||||
if (y != 1) $stop;
|
||||
|
||||
// Additional regression: named-block disable with join
|
||||
fork
|
||||
begin : worker_join
|
||||
z++;
|
||||
#2;
|
||||
z++;
|
||||
end
|
||||
#1 disable worker_join;
|
||||
join
|
||||
if (z != 1) $stop;
|
||||
|
||||
// Additional regression: named-block disable with join_any
|
||||
fork
|
||||
begin : worker_join_any
|
||||
w++;
|
||||
#2;
|
||||
w++;
|
||||
end
|
||||
#1 disable worker_join_any;
|
||||
join_any
|
||||
#3;
|
||||
if (w != 1) $stop;
|
||||
|
||||
// disable fork from inside a join_any branch
|
||||
fork
|
||||
begin
|
||||
fork
|
||||
begin
|
||||
#1;
|
||||
jf = 1;
|
||||
end
|
||||
begin
|
||||
#5;
|
||||
jf = 99;
|
||||
end
|
||||
join_none
|
||||
#2;
|
||||
disable fork;
|
||||
end
|
||||
begin
|
||||
#3;
|
||||
end
|
||||
join_any
|
||||
#6;
|
||||
if (jf != 1) $stop;
|
||||
|
||||
// multiple sequential disables of the same target under join
|
||||
fork
|
||||
begin : twice_join
|
||||
#5;
|
||||
ddj = 99;
|
||||
end
|
||||
begin
|
||||
#1 disable twice_join;
|
||||
#1 disable twice_join;
|
||||
end
|
||||
join
|
||||
if (ddj != 0) $stop;
|
||||
|
||||
// multiple sequential disables of the same target under join_any
|
||||
fork
|
||||
begin : twice_join_any
|
||||
#5;
|
||||
ddja = 99;
|
||||
end
|
||||
begin
|
||||
#1 disable twice_join_any;
|
||||
#1 disable twice_join_any;
|
||||
end
|
||||
join_any
|
||||
#6;
|
||||
if (ddja != 0) $stop;
|
||||
|
||||
// multiple sequential disables of the same target under join_none
|
||||
begin
|
||||
fork
|
||||
begin : twice_join_none
|
||||
#5;
|
||||
ddjn = 99;
|
||||
end
|
||||
join_none
|
||||
#1 disable twice_join_none;
|
||||
#1 disable twice_join_none;
|
||||
#6;
|
||||
end
|
||||
if (ddjn != 0) $stop;
|
||||
|
||||
// disable after target is already finished (join)
|
||||
fork
|
||||
begin : done_join
|
||||
#1;
|
||||
dj_done = 1;
|
||||
end
|
||||
join
|
||||
disable done_join;
|
||||
if (dj_done != 1) $stop;
|
||||
|
||||
// disable after target is already finished (join_any)
|
||||
fork
|
||||
begin : done_join_any
|
||||
#1;
|
||||
dja_done = 1;
|
||||
end
|
||||
#2;
|
||||
join_any
|
||||
#2;
|
||||
disable done_join_any;
|
||||
if (dja_done != 1) $stop;
|
||||
|
||||
// disable after target is already finished (join_none)
|
||||
begin
|
||||
fork
|
||||
begin : done_join_none
|
||||
#1;
|
||||
djn_done = 1;
|
||||
end
|
||||
join_none
|
||||
#2;
|
||||
disable done_join_none;
|
||||
#1;
|
||||
end
|
||||
if (djn_done != 1) $stop;
|
||||
|
||||
// competing disables in the same time slot targeting the same block
|
||||
fork
|
||||
begin : race_target
|
||||
#5;
|
||||
race_disable = 99;
|
||||
end
|
||||
#1 disable race_target;
|
||||
#1 disable race_target;
|
||||
join
|
||||
if (race_disable != 0) $stop;
|
||||
|
||||
// nested descendants are disabled and outer join resumes
|
||||
begin : nested_disable
|
||||
fork
|
||||
begin
|
||||
fork
|
||||
begin
|
||||
#1;
|
||||
nd += 1;
|
||||
end
|
||||
begin
|
||||
#3;
|
||||
nd += 10;
|
||||
end
|
||||
join_none
|
||||
#5;
|
||||
nd += 100;
|
||||
end
|
||||
begin
|
||||
#2;
|
||||
disable nested_disable;
|
||||
end
|
||||
join_none
|
||||
#6;
|
||||
nd += 1000;
|
||||
end
|
||||
#8;
|
||||
if (nd != 1) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue