mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Fix module automatic
This commit is contained in:
parent
e223228ec0
commit
192236a832
@ -62,6 +62,7 @@ class LinkParseVisitor final : public VNVisitor {
|
|||||||
int m_beginDepth = 0; // How many begin blocks above current node within current AstNodeModule
|
int m_beginDepth = 0; // How many begin blocks above current node within current AstNodeModule
|
||||||
VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime
|
VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime
|
||||||
bool m_insideLoop = false; // True if the node is inside a loop
|
bool m_insideLoop = false; // True if the node is inside a loop
|
||||||
|
bool m_lifetimeAllowed = false; // True to allow lifetime settings
|
||||||
VDouble0 m_statModules; // Number of modules seen
|
VDouble0 m_statModules; // Number of modules seen
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
@ -185,6 +186,8 @@ class LinkParseVisitor final : public VNVisitor {
|
|||||||
VL_RESTORER(m_ftaskp);
|
VL_RESTORER(m_ftaskp);
|
||||||
VL_RESTORER(m_lifetime);
|
VL_RESTORER(m_lifetime);
|
||||||
m_ftaskp = nodep;
|
m_ftaskp = nodep;
|
||||||
|
VL_RESTORER(m_lifetimeAllowed);
|
||||||
|
m_lifetimeAllowed = true;
|
||||||
if (!nodep->lifetime().isNone()) {
|
if (!nodep->lifetime().isNone()) {
|
||||||
m_lifetime = nodep->lifetime();
|
m_lifetime = nodep->lifetime();
|
||||||
} else {
|
} else {
|
||||||
@ -290,7 +293,13 @@ class LinkParseVisitor final : public VNVisitor {
|
|||||||
"loop converted to automatic");
|
"loop converted to automatic");
|
||||||
}
|
}
|
||||||
if (nodep->varType() != VVarType::PORT) {
|
if (nodep->varType() != VVarType::PORT) {
|
||||||
if (nodep->lifetime().isNone()) nodep->lifetime(m_lifetime);
|
if (nodep->lifetime().isNone()) {
|
||||||
|
if (m_lifetimeAllowed) {
|
||||||
|
nodep->lifetime(m_lifetime);
|
||||||
|
} else { // Module's always static per IEEE 1800-2023 6.21
|
||||||
|
nodep->lifetime(VLifetime::STATIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (m_ftaskp) {
|
} else if (m_ftaskp) {
|
||||||
nodep->lifetime(VLifetime::AUTOMATIC);
|
nodep->lifetime(VLifetime::AUTOMATIC);
|
||||||
} else if (nodep->lifetime()
|
} else if (nodep->lifetime()
|
||||||
@ -612,6 +621,7 @@ class LinkParseVisitor final : public VNVisitor {
|
|||||||
VL_RESTORER(m_genblkNum);
|
VL_RESTORER(m_genblkNum);
|
||||||
VL_RESTORER(m_beginDepth);
|
VL_RESTORER(m_beginDepth);
|
||||||
VL_RESTORER(m_lifetime);
|
VL_RESTORER(m_lifetime);
|
||||||
|
VL_RESTORER(m_lifetimeAllowed);
|
||||||
{
|
{
|
||||||
// Module: Create sim table for entire module and iterate
|
// Module: Create sim table for entire module and iterate
|
||||||
cleanFileline(nodep);
|
cleanFileline(nodep);
|
||||||
@ -624,6 +634,7 @@ class LinkParseVisitor final : public VNVisitor {
|
|||||||
m_beginDepth = 0;
|
m_beginDepth = 0;
|
||||||
m_valueModp = nodep;
|
m_valueModp = nodep;
|
||||||
m_lifetime = nodep->lifetime();
|
m_lifetime = nodep->lifetime();
|
||||||
|
m_lifetimeAllowed = VN_IS(nodep, Class);
|
||||||
if (m_lifetime.isNone()) {
|
if (m_lifetime.isNone()) {
|
||||||
m_lifetime = VN_IS(nodep, Class) ? VLifetime::AUTOMATIC : VLifetime::STATIC;
|
m_lifetime = VN_IS(nodep, Class) ? VLifetime::AUTOMATIC : VLifetime::STATIC;
|
||||||
}
|
}
|
||||||
@ -643,10 +654,16 @@ class LinkParseVisitor final : public VNVisitor {
|
|||||||
m_valueModp = nullptr;
|
m_valueModp = nullptr;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstNodeProcedure* nodep) override { visitIterateNoValueMod(nodep); }
|
void visit(AstNodeProcedure* nodep) override {
|
||||||
|
VL_RESTORER(m_lifetimeAllowed);
|
||||||
|
m_lifetimeAllowed = true;
|
||||||
|
visitIterateNoValueMod(nodep);
|
||||||
|
}
|
||||||
void visit(AstAlways* nodep) override {
|
void visit(AstAlways* nodep) override {
|
||||||
VL_RESTORER(m_inAlways);
|
VL_RESTORER(m_inAlways);
|
||||||
m_inAlways = true;
|
m_inAlways = true;
|
||||||
|
VL_RESTORER(m_lifetimeAllowed);
|
||||||
|
m_lifetimeAllowed = true;
|
||||||
visitIterateNoValueMod(nodep);
|
visitIterateNoValueMod(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstCover* nodep) override { visitIterateNoValueMod(nodep); }
|
void visit(AstCover* nodep) override { visitIterateNoValueMod(nodep); }
|
||||||
|
18
test_regress/t/t_mod_automatic.py
Executable file
18
test_regress/t/t_mod_automatic.py
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
47
test_regress/t/t_mod_automatic.v
Normal file
47
test_regress/t/t_mod_automatic.v
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2024 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module automatic t(/*AUTOARG*/);
|
||||||
|
|
||||||
|
task static accum_s(input integer value, output integer result);
|
||||||
|
static int acc = 1;
|
||||||
|
acc = acc + value;
|
||||||
|
result = acc;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task accum_a(input integer value, output integer result);
|
||||||
|
int acc = 1; // automatic
|
||||||
|
acc = acc + value;
|
||||||
|
result = acc;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
integer value;
|
||||||
|
|
||||||
|
reg failed = 0; // Static
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
accum_s(2, value);
|
||||||
|
$display("%d", value);
|
||||||
|
if (value !== 3) failed = 1;
|
||||||
|
|
||||||
|
accum_s(3, value);
|
||||||
|
$display("%d", value);
|
||||||
|
if (value !== 6) failed = 1;
|
||||||
|
|
||||||
|
accum_a(2, value);
|
||||||
|
$display("%d", value);
|
||||||
|
if (value !== 3) failed = 1;
|
||||||
|
|
||||||
|
accum_a(3, value);
|
||||||
|
$display("%d", value);
|
||||||
|
if (value !== 4) failed = 1;
|
||||||
|
|
||||||
|
if (failed) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
Loading…
Reference in New Issue
Block a user