Fix loop exits on $finish

This commit is contained in:
Wilson Snyder 2025-10-06 19:19:15 -04:00
parent 5229ce8660
commit 717667034b
3 changed files with 50 additions and 1 deletions

View File

@ -45,7 +45,8 @@ VL_DEFINE_DEBUG_FUNCTIONS;
class LinkJumpVisitor final : public VNVisitor {
// NODE STATE
// AstNode::user1() -> AstJumpBlock*, for body of this loop
// AstBegin/etc::user1() -> AstJumpBlock*, for body of this loop
// AstFinish::user1() -> bool, processed
// AstNode::user2() -> AstJumpBlock*, for this block
// AstNodeBlock::user3() -> bool, true if contains a fork
const VNUser1InUse m_user1InUse;
@ -437,6 +438,15 @@ class LinkJumpVisitor final : public VNVisitor {
nodep->unlinkFrBack();
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void visit(AstFinish* nodep) override {
if (nodep->user1SetOnce()) return; // Process once
iterateChildren(nodep);
if (m_loopp) {
// Jump to the end of the loop (post-finish)
AstJumpBlock* const blockp = getJumpBlock(m_loopp, false);
nodep->addNextHere(new AstJumpGo{nodep->fileline(), blockp});
}
}
void visit(AstVarRef* nodep) override {
if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true);
}

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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(verilator_flags2=['--binary'])
test.execute()
test.passes()

View File

@ -0,0 +1,21 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t;
int loops;
initial begin
#1;
// verilator lint_off INFINITELOOP
while (1'b1) begin
$write("*-* All Finished *-*\n");
$finish; // Infinite loop, but for this finish
if (++loops > 100) $stop;
end
end
endmodule