Fix fork scheduling semantics (#6730)

Signed-off-by: Artur Bieniek <[email protected]>
This commit is contained in:
Artur Bieniek
2025-11-26 15:52:53 +03:00
committed by GitHub
parent f4654a451b
commit 2c5ff3f63f
26 changed files with 401 additions and 63 deletions
+27 -9
View File
@@ -469,6 +469,7 @@ class TimingControlVisitor final : public VNVisitor {
AstScope* m_scopep = nullptr; // Current scope
AstActive* m_activep = nullptr; // Current active
AstNode* m_procp = nullptr; // NodeProcedure/CFunc/Begin we're under
bool m_hasProcess = false; // True if current scope has a VlProcess handle available
int m_forkCnt = 0; // Number of forks inside a module
bool m_underJumpBlock = false; // True if we are inside of a jump-block
bool m_underProcedure = false; // True if we are under an always or initial
@@ -654,26 +655,34 @@ class TimingControlVisitor final : public VNVisitor {
}
// Adds debug info to a hardcoded method call
void addDebugInfo(AstCMethodHard* const methodp) const {
if (v3Global.opt.protectIds()) return;
FileLine* const flp = methodp->fileline();
AstCExpr* const ap = new AstCExpr{flp, '"' + flp->filenameEsc() + '"'};
const bool protectIds = v3Global.opt.protectIds();
AstCExpr* const ap
= new AstCExpr{flp, protectIds ? "VL_UNKNOWN" : '"' + flp->filenameEsc() + '"'};
ap->dtypeSetString();
methodp->addPinsp(ap);
AstCExpr* const bp = new AstCExpr{flp, cvtToStr(flp->lineno())};
AstCExpr* const bp = new AstCExpr{flp, protectIds ? "0" : cvtToStr(flp->lineno())};
bp->dtypeSetString();
methodp->addPinsp(bp);
}
// Adds debug info to a trigSched.trigger() call
void addEventDebugInfo(AstCMethodHard* const methodp, AstSenTree* const sentreep) const {
if (v3Global.opt.protectIds()) return;
if (v3Global.opt.protectIds()) {
FileLine* const flp = sentreep->fileline();
AstCExpr* const descp = new AstCExpr{flp, "VL_UNKNOWN"};
descp->dtypeSetString();
methodp->addPinsp(descp);
addDebugInfo(methodp);
return;
}
methodp->addPinsp(createEventDescription(sentreep));
addDebugInfo(methodp);
}
// Adds process pointer to a hardcoded method call
void addProcessInfo(AstCMethodHard* const methodp) const {
FileLine* const flp = methodp->fileline();
AstCExpr* const ap = new AstCExpr{
flp, m_procp && (hasFlags(m_procp, T_HAS_PROC)) ? "vlProcess" : "nullptr"};
AstCExpr* const ap
= new AstCExpr{flp, (m_procp && m_hasProcess) ? "vlProcess" : "nullptr"};
methodp->addPinsp(ap);
}
// Creates the fork handle type and returns it
@@ -779,7 +788,9 @@ class TimingControlVisitor final : public VNVisitor {
}
void visit(AstNodeProcedure* nodep) override {
VL_RESTORER(m_procp);
VL_RESTORER(m_hasProcess);
m_procp = nodep;
m_hasProcess = hasFlags(nodep, T_HAS_PROC);
VL_RESTORER(m_underProcedure);
m_underProcedure = true;
iterateChildren(nodep);
@@ -801,7 +812,9 @@ class TimingControlVisitor final : public VNVisitor {
void visit(AstAlways* nodep) override {
if (nodep->user1SetOnce()) return;
VL_RESTORER(m_procp);
VL_RESTORER(m_hasProcess);
m_procp = nodep;
m_hasProcess = hasFlags(nodep, T_HAS_PROC);
VL_RESTORER(m_underProcedure);
m_underProcedure = true;
// Workaround for killing `always` processes (doing that is pretty much UB)
@@ -829,7 +842,9 @@ class TimingControlVisitor final : public VNVisitor {
}
void visit(AstCFunc* nodep) override {
VL_RESTORER(m_procp);
VL_RESTORER(m_hasProcess);
m_procp = nodep;
m_hasProcess = hasFlags(nodep, T_HAS_PROC);
iterateChildren(nodep);
if (hasFlags(nodep, T_HAS_PROC)) nodep->setNeedProcess();
if (!(hasFlags(nodep, T_SUSPENDEE))) return;
@@ -862,6 +877,7 @@ class TimingControlVisitor final : public VNVisitor {
}
}
void visit(AstNodeCCall* nodep) override {
if (nodep->funcp()->needProcess()) m_hasProcess = true;
if (hasFlags(nodep->funcp(), T_SUSPENDEE) && !nodep->user1SetOnce()) { // If suspendable
VNRelinker relinker;
nodep->unlinkFrBack(&relinker);
@@ -1165,12 +1181,12 @@ class TimingControlVisitor final : public VNVisitor {
forkp->unlinkFrBack()});
}
void visit(AstDisableFork* nodep) override {
if (hasFlags(m_procp, T_HAS_PROC)) return;
if (m_hasProcess) return;
// never reached by any process; remove to avoid compilation error
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
void visit(AstWaitFork* nodep) override {
if (hasFlags(m_procp, T_HAS_PROC)) {
if (m_hasProcess) {
FileLine* const flp = nodep->fileline();
AstCExpr* const exprp = new AstCExpr{flp, "vlProcess->completedFork()", 1};
AstWait* const waitp = new AstWait{flp, exprp, nullptr};
@@ -1233,8 +1249,10 @@ class TimingControlVisitor final : public VNVisitor {
}
void visit(AstBegin* nodep) override {
VL_RESTORER(m_procp);
VL_RESTORER(m_hasProcess);
m_hasProcess |= hasFlags(nodep, T_HAS_PROC);
m_procp = nodep;
if (hasFlags(nodep, T_HAS_PROC)) nodep->setNeedProcess();
if (m_hasProcess) nodep->setNeedProcess();
iterateChildren(nodep);
}
void visit(AstFork* nodep) override {