Fix disable fork and wait fork affecting pending NBA updates (#8483)

This commit is contained in:
Marco Bartoli
2026-09-25 16:35:51 -04:00
committed by GitHub
parent 8b663f9c84
commit 4e29ecbf44
3 changed files with 84 additions and 0 deletions
+5
View File
@@ -88,6 +88,7 @@ enum NodeFlag : uint8_t {
T_FORCES_PROC = 1 << 3, // Forces VlProcess allocation
T_NEEDS_PROC = 1 << 4, // Needs access to VlProcess if it's allocated
T_HAS_PROC = 1 << 5, // Has VlProcess argument in the signature
T_NBA_UPDATE = 1 << 6, // Fork branch of a pending NBA update, which is not a subprocess
};
enum ForkType : uint8_t {
@@ -1222,6 +1223,7 @@ class TimingControlVisitor final : public VNVisitor {
AstBegin* beginp = VN_CAST(controlp, Begin);
if (!beginp) beginp = new AstBegin{nodep->fileline(), "", controlp, false};
forkp->addForksp(beginp);
addFlags(beginp, T_NBA_UPDATE);
controlp = forkp;
}
UASSERT_OBJ(nodep, controlp, "Assignment should have timing control");
@@ -1438,6 +1440,9 @@ class TimingControlVisitor final : public VNVisitor {
VL_RESTORER(m_procp);
VL_RESTORER(m_hasProcess);
m_hasProcess |= hasFlags(nodep, T_HAS_PROC);
// A pending NBA update is not a subprocess of the process that scheduled it, so it is
// unaffected by 'disable fork' and 'wait fork' (IEEE 1800-2023 9.6.1, 9.6.3)
if (hasFlags(nodep, T_NBA_UPDATE)) m_hasProcess = false;
m_procp = nodep;
if (m_hasProcess) nodep->setNeedProcess();
iterateChildren(nodep);
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Pending NBA updates are not subprocesses for disable/wait fork
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=["--binary"])
test.execute()
test.passes()
+61
View File
@@ -0,0 +1,61 @@
// DESCRIPTION: Verilator: Pending NBA updates are not subprocesses for disable/wait fork
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`define stop $stop
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
// verilog_format: on
interface bus_if;
int data;
endinterface
class Cls;
virtual bus_if vif;
task set(int v);
vif.data <= v;
endtask
endclass
module t;
bit clk;
int dly_value;
int wait_value;
bit [1:0] drive_value;
bus_if bus ();
Cls obj = new;
always #5 clk = ~clk;
default clocking cb @(posedge clk);
output drive_value;
endclocking
// 'disable fork' does not cancel pending updates (IEEE 1800-2023 9.6.3)
initial begin
obj.vif = bus;
dly_value <= #2 1;
obj.set(2);
cb.drive_value <= ##1 3;
disable fork;
#20;
`checkd(dly_value, 1)
`checkd(bus.data, 2)
`checkd(drive_value, 3)
end
// 'wait fork' does not wait for pending updates (IEEE 1800-2023 9.6.1)
initial begin
#30;
wait_value <= #5 4;
wait fork;
`checkd($time, 30)
#10;
`checkd(wait_value, 4)
$write("*-* All Finished *-*\n");
$finish;
end
endmodule