diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index e76311dab..87a58bb99 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -46,8 +46,10 @@ class LinkJumpVisitor final : public VNVisitor { // NODE STATE // AstNode::user1() -> AstJumpLabel*, for this block if endOfIter // AstNode::user2() -> AstJumpLabel*, for this block if !endOfIter + // AstNodeBlock::user3() -> bool, true if contains a fork const VNUser1InUse m_user1InUse; const VNUser2InUse m_user2InUse; + const VNUser3InUse m_user3InUse; // STATE AstNodeModule* m_modp = nullptr; // Current module @@ -178,7 +180,16 @@ class LinkJumpVisitor final : public VNVisitor { VL_RESTORER(m_unrollFull); m_blockStack.push_back(nodep); { - m_inFork = m_inFork || VN_IS(nodep, Fork); + if (VN_IS(nodep, Fork)) { + m_inFork = true; // And remains set for children + // Mark all upper blocks also, can stop once see + // one set to avoid O(n^2) + for (auto itr : vlstd::reverse_view(m_blockStack)) { + if (itr->user3()) break; + itr->user3(true); + } + } + nodep->user3(m_inFork); iterateChildren(nodep); } m_blockStack.pop_back(); @@ -340,9 +351,13 @@ class LinkJumpVisitor final : public VNVisitor { nodep->v3warn(E_UNSUPPORTED, "disable isn't underneath a begin with name: " << nodep->prettyNameQ()); } else if (AstBegin* const beginp = VN_CAST(blockp, Begin)) { - // Jump to the end of the named block - AstJumpLabel* const labelp = findAddLabel(beginp, false); - nodep->addNextHere(new AstJumpGo{nodep->fileline(), labelp}); + if (beginp->user3()) { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling block that contains a fork"); + } else { + // Jump to the end of the named block + AstJumpLabel* const labelp = findAddLabel(beginp, false); + nodep->addNextHere(new AstJumpGo{nodep->fileline(), labelp}); + } } else { nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling fork by name"); } diff --git a/test_regress/t/t_disable.out b/test_regress/t/t_disable.out index d59e8bc0f..6a0001088 100644 --- a/test_regress/t/t_disable.out +++ b/test_regress/t/t_disable.out @@ -2,4 +2,7 @@ 11 | disable foo; | ^~~~~~~ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_disable.v:17:13: Unsupported: disabling block that contains a fork + 17 | disable forked; + | ^~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_disable.v b/test_regress/t/t_disable.v index 78cdb2f21..ebfd707a1 100644 --- a/test_regress/t/t_disable.v +++ b/test_regress/t/t_disable.v @@ -12,6 +12,13 @@ module t(/*AUTOARG*/); #1 $stop; join_none #2; + begin : forked + fork + disable forked; + #1 $stop; + join_none + end + #2; $write("*-* All Finished *-*\n"); $finish; end