Skip to content

Commit

Permalink
Fix dynamic NBAs with automatic vars
Browse files Browse the repository at this point in the history
Signed-off-by: Krzysztof Bieganski <[email protected]>
  • Loading branch information
kbieganski committed Nov 15, 2023
1 parent dc10118 commit df56952
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 8 deletions.
19 changes: 14 additions & 5 deletions src/V3Fork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,11 +313,8 @@ class DynScopeVisitor final : public VNVisitor {
}

static bool hasAsyncFork(AstNode* nodep) {
bool afork = false;
nodep->foreach([&](AstFork* forkp) {
if (!forkp->joinType().join()) afork = true;
});
return afork;
return nodep->exists([](AstFork* forkp) { return !forkp->joinType().join(); })
|| nodep->exists([](AstAssignDly*) { return true; });
}

void bindNodeToDynScope(AstNode* nodep, ForkDynScopeFrame* frame) {
Expand Down Expand Up @@ -415,6 +412,18 @@ class DynScopeVisitor final : public VNVisitor {
}
visit(static_cast<AstNodeStmt*>(nodep));
}
void visit(AstAssignDly* nodep) override {
if (m_procp && !VN_IS(nodep->backp(), Fork) && nodep->lhsp()->exists([](AstVarRef* refp) {
return refp->varp()->isFuncLocal();
})) {
auto* forkp = new AstFork{nodep->fileline(), "", nullptr};
forkp->joinType(VJoinType::JOIN_NONE);
nodep->replaceWith(forkp);
forkp->addStmtsp(nodep);
} else {
iterateChildren(nodep);
}
}
void visit(AstNode* nodep) override {
if (nodep->isTimingControl()) m_afterTimingControl = true;
iterateChildren(nodep);
Expand Down
3 changes: 2 additions & 1 deletion src/V3SchedTiming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ void transformForks(AstNetlist* const netlistp) {
funcp->foreach([&](AstNodeVarRef* refp) {
AstVar* const varp = refp->varp();
AstBasicDType* const dtypep = varp->dtypep()->basicp();
bool passByValue = false;
// If not a fork..join, copy. All write refs should've been handled by V3Fork
bool passByValue = !m_forkp->joinType().join();
if (!varp->isFuncLocal()) {
if (VString::startsWith(varp->name(), "__Vintra")) {
// Pass it by value to the new function, as otherwise there are issues with
Expand Down
8 changes: 6 additions & 2 deletions src/V3Timing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1029,8 +1029,12 @@ class TimingControlVisitor final : public VNVisitor {
// Special case for NBA
if (inAssignDly) {
// Put it in a fork so it doesn't block
auto* const forkp = new AstFork{flp, "", nullptr};
forkp->joinType(VJoinType::JOIN_NONE);
// Could already be the only thing directly under a fork, reuse that if possible
AstFork* forkp = !nodep->nextp() ? VN_CAST(nodep->firstAbovep(), Fork) : nullptr;
if (!forkp) {
forkp = new AstFork{flp, "", nullptr};
forkp->joinType(VJoinType::JOIN_NONE);
}
if (!m_underProcedure) {
// If it's in a function, it won't be handled by V3Delayed
// Put it behind an additional named event that gets triggered in the NBA region
Expand Down
21 changes: 21 additions & 0 deletions test_regress/t/t_assigndly_dynamic.v
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,26 @@ class nba_waiter;
endtask
endclass

class Foo;
task bar(logic a, logic b);
int x;
int y;
// bar's local vars and intravals could be overwritten by other locals
if (a) x <= `DELAY 'hDEAD;
if (b) y <= `DELAY 'hBEEF;
#2
if (x != 'hDEAD) $stop;
endtask

task qux();
int x[] = new[1];
x[0] <= `DELAY 'hBEEF; // Segfault check
endtask
endclass

module t;
nba_waiter waiter = new;
Foo foo = new;
event e;
int cnt = 0;

Expand All @@ -42,6 +60,9 @@ module t;
waiter.wait_for_nba_region;
if (cnt != 4) $stop;
if ($time != `TIME_AFTER_SECOND_WAIT) $stop;
foo.bar(1, 1);
foo.qux();
#2
$write("*-* All Finished *-*\n");
$finish;
end
Expand Down
18 changes: 18 additions & 0 deletions test_regress/t/t_fork_repeat.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2023 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

scenarios(simulator => 1);

compile(
verilator_flags2 => ["--exe --timing"],
);

ok(1);
1;
15 changes: 15 additions & 0 deletions test_regress/t/t_fork_repeat.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module repeat_lifetime_bug;
initial begin
fork
begin
repeat(5) begin
$display("iteration");
end
//for(int i=0; i<5; i++) begin
// $display("iteration");
//end
end
join_any
$finish;
end
endmodule
23 changes: 23 additions & 0 deletions test_regress/t/t_intraval_auto.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 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

scenarios(simulator => 1);

compile(
verilator_flags2 => ["--exe --main --timing"],
make_main => 0,
);

execute(
check_finished => 1,
);

ok(1);
1;
30 changes: 30 additions & 0 deletions test_regress/t/t_intraval_auto.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0

class Foo;
task bar(logic b);
int x;
if (b) x <= 'hDEAD;
#1
if (x != 'hDEAD) $stop;
endtask

task qux();
int x[] = new[1];
x[0] <= 'hBEEF; // Segfault check
endtask
endclass

module t;
Foo foo = new;

initial begin
foo.bar(1);
foo.qux();
#2 $write("*-* All Finished *-*\n");
$finish;
end
endmodule
21 changes: 21 additions & 0 deletions test_regress/t/t_static_nonstatic_error.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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

scenarios(simulator => 1);

compile(
);

execute(
check_finished => 1,
);

ok(1);
1;
18 changes: 18 additions & 0 deletions test_regress/t/t_static_nonstatic_error.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2003 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0

package my_pkg;
task tsk;
endtask
endpackage

module t;
initial begin
my_pkg::tsk();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

0 comments on commit df56952

Please sign in to comment.