Support disabling a fork from within that fork (#6314)

This commit is contained in:
Ryszard Rozak 2025-08-20 18:21:07 +02:00 committed by GitHub
parent 11667160f2
commit 3d3462b209
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 56 additions and 13 deletions

View File

@ -180,16 +180,12 @@ class LinkJumpVisitor final : public VNVisitor {
fl, new AstMethodCall{fl, queueRefp, "push_back", new AstArg{fl, "", processSelfp}}};
}
void handleDisableOnFork(AstDisable* const nodep, const std::vector<AstBegin*>& forks) {
// The support is limited only to disabling a fork from outside that fork.
// It utilizes the process::kill()` method. For each `disable` a queue of processes is
// declared. At the beginning of each fork that can be disabled, its process handle is
// pushed to the queue. `disable` statement is replaced with calling `kill()` method on
// each element of the queue.
// The support utilizes the process::kill()` method. For each `disable` a queue of
// processes is declared. At the beginning of each fork that can be disabled, its process
// handle is pushed to the queue. `disable` statement is replaced with calling `kill()`
// method on each element of the queue.
FileLine* const fl = nodep->fileline();
const std::string targetName = nodep->targetp()->name();
if (existsBlockAbove(targetName)) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling fork from within same fork");
}
if (m_ftaskp) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling fork from task / function");
}
@ -222,7 +218,15 @@ class LinkJumpVisitor final : public VNVisitor {
= new AstTaskRef{fl, VN_AS(getMemberp(processClassp, "killQueue"), Task),
new AstArg{fl, "", queueRefp}};
killQueueCall->classOrPackagep(processClassp);
nodep->addNextHere(new AstStmtExpr{fl, killQueueCall});
AstStmtExpr* const killStmtp = new AstStmtExpr{fl, killQueueCall};
nodep->addNextHere(killStmtp);
if (existsBlockAbove(targetName)) {
// process::kill doesn't kill the current process immediately, because it is in the
// running state. Since the current process has to be terminated immediately, we jump
// at the end of the fork that is being disabled
AstJumpBlock* const jumpBlockp = getJumpBlock(nodep->targetp(), false);
killStmtp->addNextHere(new AstJumpGo{fl, jumpBlockp});
}
}
static bool directlyUnderFork(const AstNode* const nodep) {
if (nodep->backp()->nextp() == nodep) return directlyUnderFork(nodep->backp());

View File

@ -1,8 +1,5 @@
%Error-UNSUPPORTED: t/t_disable.v:11:10: Unsupported: disabling fork from within same fork
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;
| ^~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(timing_loop=True, verilator_flags2=["--timing"])
test.execute()
test.passes()

View File

@ -0,0 +1,24 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
module t ( /*AUTOARG*/);
initial begin
int x = 0;
fork : fork_blk
begin
x = 1;
#2;
x = 2;
end
join_none
#1;
disable fork_blk;
#2;
if (x != 1) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule