Fix reevaluation of method calls in wait conditions (#8391)

This commit is contained in:
Jesús Alberto López Soto
2026-09-18 15:41:01 -04:00
committed by GitHub
parent 830cb633e5
commit 724a42e31d
4 changed files with 110 additions and 0 deletions
+1
View File
@@ -148,6 +148,7 @@ jeffrey.song
Jens Yuechao Liu
Jeremy Bennett
Jesse Taube
Jesús Alberto López Soto
Jevin Sweval
Jiacheng Qian
Jiamin Zhu
+11
View File
@@ -229,6 +229,17 @@ class LiftExprVisitor final : public VNVisitor {
}
// VISITORS - statements
void visit(AstWait* nodep) override {
if (nodep->user1SetOnce()) return;
VL_RESTORER(m_doNotLiftp);
m_doNotLiftp = nullptr;
// Keep lifted statements inside the repeatedly evaluated condition.
if (AstNode* const newStmtps = lift(nodep->condp())) {
AstNodeExpr* const condp = nodep->condp()->unlinkFrBack();
nodep->condp(new AstExprStmt{nodep->fileline(), newStmtps, condp});
}
iterateAndNextNull(nodep->stmtsp());
}
void visit(AstNodeStmt* nodep) override {
if (nodep->user1SetOnce()) return;
VL_RESTORER(m_doNotLiftp);
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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()
+80
View File
@@ -0,0 +1,80 @@
// DESCRIPTION: Verilator: Reevaluate function and method calls in wait conditions
//
// 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
class State;
int value;
function bit ready();
return value == 3;
endfunction
endclass
module t;
State state;
process child;
process killed;
bit completed;
bit kill_seen;
initial begin
state = new;
fork
begin
fork
begin
child = process::self();
#5;
state.value = 3;
#3;
end
begin
#20;
`checkd(completed, 1)
end
join
end
begin
#1;
wait (state.ready()) begin
`checkd($time, 5)
child.await();
`checkd($time, 8)
`checkd(child.status(), process::FINISHED)
completed = 1;
end
end
join
fork
begin
killed = process::self();
#100;
`stop;
end
begin
#2;
killed.kill();
end
begin
#1;
killed.await();
`checkd($time, 22)
`checkd(killed.status(), process::KILLED)
kill_seen = 1;
end
join
`checkd(kill_seen, 1)
$write("*-* All Finished *-*\n");
$finish;
end
initial begin
#150;
`stop;
end
endmodule