mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Fix reevaluation of method calls in wait conditions (#8391)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Executable
+18
@@ -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()
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user