Fix $finish inside fork blocks (#6555)
Signed-off-by: Bartłomiej Chmiel <bchmiel@antmicro.com>
This commit is contained in:
parent
61c64e4a3b
commit
9bd30baba4
|
|
@ -619,6 +619,20 @@ public:
|
||||||
int instrCount() const override { return 0; } // Rarely executes
|
int instrCount() const override { return 0; } // Rarely executes
|
||||||
bool sameNode(const AstNode* samep) const override { return fileline() == samep->fileline(); }
|
bool sameNode(const AstNode* samep) const override { return fileline() == samep->fileline(); }
|
||||||
};
|
};
|
||||||
|
class AstFinishFork final : public AstNodeStmt {
|
||||||
|
// $finish in fork
|
||||||
|
public:
|
||||||
|
explicit AstFinishFork(FileLine* fl)
|
||||||
|
: ASTGEN_SUPER_FinishFork(fl) {}
|
||||||
|
ASTGEN_MEMBERS_AstFinishFork;
|
||||||
|
bool isGateOptimizable() const override { return false; }
|
||||||
|
bool isPredictOptimizable() const override { return false; }
|
||||||
|
bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering
|
||||||
|
bool isOutputter() override { return true; } // SPECIAL: $display makes output
|
||||||
|
bool isUnlikely() const override { return true; }
|
||||||
|
int instrCount() const override { return 0; } // Rarely executes
|
||||||
|
bool sameNode(const AstNode* samep) const override { return fileline() == samep->fileline(); }
|
||||||
|
};
|
||||||
class AstFireEvent final : public AstNodeStmt {
|
class AstFireEvent final : public AstNodeStmt {
|
||||||
// '-> _' and '->> _' event trigger statements
|
// '-> _' and '->> _' event trigger statements
|
||||||
// @astgen op1 := operandp : AstNodeExpr
|
// @astgen op1 := operandp : AstNodeExpr
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ class CfgBuilder final : public VNVisitorConst {
|
||||||
void visit(AstComment*) override {} // ignore entirely
|
void visit(AstComment*) override {} // ignore entirely
|
||||||
void visit(AstDisplay* nodep) override { simpleStatement(nodep); }
|
void visit(AstDisplay* nodep) override { simpleStatement(nodep); }
|
||||||
void visit(AstFinish* nodep) override { simpleStatement(nodep); }
|
void visit(AstFinish* nodep) override { simpleStatement(nodep); }
|
||||||
|
void visit(AstFinishFork* nodep) override { simpleStatement(nodep); }
|
||||||
void visit(AstStmtExpr* nodep) override { simpleStatement(nodep); }
|
void visit(AstStmtExpr* nodep) override { simpleStatement(nodep); }
|
||||||
void visit(AstStop* nodep) override { simpleStatement(nodep); }
|
void visit(AstStop* nodep) override { simpleStatement(nodep); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,7 @@ class CfgLiveVariables final : VNVisitorConst {
|
||||||
void visit(AstAssignW* nodep) override { single(nodep); }
|
void visit(AstAssignW* nodep) override { single(nodep); }
|
||||||
void visit(AstDisplay* nodep) override { single(nodep); }
|
void visit(AstDisplay* nodep) override { single(nodep); }
|
||||||
void visit(AstFinish* nodep) override { single(nodep); }
|
void visit(AstFinish* nodep) override { single(nodep); }
|
||||||
|
void visit(AstFinishFork* nodep) override { single(nodep); }
|
||||||
void visit(AstStmtExpr* nodep) override { single(nodep); }
|
void visit(AstStmtExpr* nodep) override { single(nodep); }
|
||||||
void visit(AstStop* nodep) override { single(nodep); }
|
void visit(AstStop* nodep) override { single(nodep); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1253,6 +1253,18 @@ public:
|
||||||
puts(cvtToStr(nodep->fileline()->lineno()));
|
puts(cvtToStr(nodep->fileline()->lineno()));
|
||||||
puts(", \"\");\n");
|
puts(", \"\");\n");
|
||||||
}
|
}
|
||||||
|
void visit(AstFinishFork* nodep) override {
|
||||||
|
putns(nodep, "VL_FINISH_MT(");
|
||||||
|
putsQuoted(protect(nodep->fileline()->filename()));
|
||||||
|
puts(", ");
|
||||||
|
puts(cvtToStr(nodep->fileline()->lineno()));
|
||||||
|
puts(", \"\");\n");
|
||||||
|
if (m_cfuncp->isCoroutine()) {
|
||||||
|
putns(nodep, "co_return;\n");
|
||||||
|
} else {
|
||||||
|
putns(nodep, "return;\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
void visit(AstPrintTimeScale* nodep) override {
|
void visit(AstPrintTimeScale* nodep) override {
|
||||||
putns(nodep, "VL_PRINTTIMESCALE(");
|
putns(nodep, "VL_PRINTTIMESCALE(");
|
||||||
putsQuoted(protect(nodep->prettyName()));
|
putsQuoted(protect(nodep->prettyName()));
|
||||||
|
|
|
||||||
|
|
@ -556,6 +556,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
}
|
}
|
||||||
void visit(AstFinish* nodep) override { putfs(nodep, "$finish;\n"); }
|
void visit(AstFinish* nodep) override { putfs(nodep, "$finish;\n"); }
|
||||||
|
void visit(AstFinishFork* nodep) override { putfs(nodep, "$finish;\n"); }
|
||||||
void visit(AstStmtExpr* nodep) override {
|
void visit(AstStmtExpr* nodep) override {
|
||||||
iterateConst(nodep->exprp());
|
iterateConst(nodep->exprp());
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
|
|
|
||||||
|
|
@ -441,7 +441,10 @@ class LinkJumpVisitor final : public VNVisitor {
|
||||||
void visit(AstFinish* nodep) override {
|
void visit(AstFinish* nodep) override {
|
||||||
if (nodep->user1SetOnce()) return; // Process once
|
if (nodep->user1SetOnce()) return; // Process once
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
if (m_loopp) {
|
if (m_inFork) {
|
||||||
|
nodep->replaceWith(new AstFinishFork{nodep->fileline()});
|
||||||
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
|
} else if (m_loopp) {
|
||||||
// Jump to the end of the loop (post-finish)
|
// Jump to the end of the loop (post-finish)
|
||||||
AstJumpBlock* const blockp = getJumpBlock(m_loopp, false);
|
AstJumpBlock* const blockp = getJumpBlock(m_loopp, false);
|
||||||
nodep->addNextHere(new AstJumpGo{nodep->fileline(), blockp});
|
nodep->addNextHere(new AstJumpGo{nodep->fileline(), blockp});
|
||||||
|
|
|
||||||
|
|
@ -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=["--timing"])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -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 Antmicro.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t;
|
||||||
|
initial begin
|
||||||
|
forever begin
|
||||||
|
fork
|
||||||
|
begin
|
||||||
|
assert ($c(1)) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
wait ($c(1));
|
||||||
|
end
|
||||||
|
join_any
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue