Fix variable lifetimes in extern methods (#4414)

This commit is contained in:
Krzysztof Boroński 2023-08-11 16:52:59 +02:00 committed by GitHub
parent 2d9bc73709
commit 8d512c3187
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 2 deletions

View File

@ -296,8 +296,16 @@ private:
nodep->v3warn(STATICVAR, "Static variable with assignment declaration declared in a "
"loop converted to automatic");
}
if (m_ftaskp && m_ftaskp->classMethod() && nodep->lifetime().isNone()) {
nodep->lifetime(VLifetime::AUTOMATIC);
if (m_ftaskp) {
bool classMethod = m_ftaskp->classMethod();
if (!classMethod) {
AstClassOrPackageRef* const pkgrefp
= VN_CAST(m_ftaskp->classOrPackagep(), ClassOrPackageRef);
if (pkgrefp && VN_IS(pkgrefp->classOrPackagep(), Class)) classMethod = true;
}
if (classMethod && nodep->lifetime().isNone()) {
nodep->lifetime(VLifetime::AUTOMATIC);
}
}
if (nodep->lifetime().isNone() && nodep->varType() != VVarType::PORT) {
nodep->lifetime(m_lifetime);

View File

@ -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 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 --main --timing"],
make_main => 0,
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,35 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
class Foo;
int m_v;
function new(int v);
m_v = v;
endfunction
extern task add_in_fork_delayed(int delay, Foo arg);
endclass
task automatic Foo::add_in_fork_delayed(int delay, Foo arg);
fork
#delay m_v = m_v + arg.m_v;
join_none
endtask
module t();
initial begin
Foo foo1, foo2;
foo1 = new(1);
foo2 = new(2);
foo1.add_in_fork_delayed(10, foo2);
#20;
if (foo1.m_v != 3)
$stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule