Error on static variable initializers using automatic variables in procedures (#5296)
This commit is contained in:
parent
37a4002098
commit
99c619a4c9
|
|
@ -37,6 +37,8 @@ class LinkLValueVisitor final : public VNVisitor {
|
|||
bool m_setStrengthSpecified = false; // Set that var has assignment with strength specified.
|
||||
bool m_setForcedByCode = false; // Set that var is the target of an AstAssignForce/AstRelease
|
||||
bool m_setIfRand = false; // Update VarRefs if var declared as rand
|
||||
bool m_inInitialStatic = false; // Set if inside AstInitialStatic
|
||||
bool m_inFunc = false; // Set if inside AstNodeFTask
|
||||
VAccess m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
||||
|
||||
// VISITs
|
||||
|
|
@ -98,6 +100,35 @@ class LinkLValueVisitor final : public VNVisitor {
|
|||
m_setStrengthSpecified = false;
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
}
|
||||
|
||||
if (m_inInitialStatic && m_inFunc) {
|
||||
const bool rhsHasIO = nodep->rhsp()->exists([](const AstNodeVarRef* const refp) {
|
||||
// Exclude module I/O referenced from a function/task.
|
||||
return refp->varp() && refp->varp()->isIO()
|
||||
&& refp->varp()->lifetime() != VLifetime::NONE;
|
||||
});
|
||||
if (rhsHasIO) {
|
||||
nodep->rhsp()->v3warn(E_UNSUPPORTED,
|
||||
"Static variable initializer\n"
|
||||
<< nodep->rhsp()->warnMore()
|
||||
<< "is dependent on function/task I/O variable");
|
||||
} else {
|
||||
const bool rhsHasAutomatic
|
||||
= nodep->rhsp()->exists([](const AstNodeVarRef* const refp) {
|
||||
return refp->varp() && refp->varp()->lifetime() == VLifetime::AUTOMATIC;
|
||||
});
|
||||
if (rhsHasAutomatic) {
|
||||
nodep->rhsp()->v3error("Static variable initializer\n"
|
||||
<< nodep->rhsp()->warnMore()
|
||||
<< "is dependent on automatic variable");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void visit(AstInitialStatic* nodep) override {
|
||||
VL_RESTORER(m_inInitialStatic);
|
||||
m_inInitialStatic = true;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstRelease* nodep) override {
|
||||
VL_RESTORER(m_setRefLvalue);
|
||||
|
|
@ -328,6 +359,11 @@ class LinkLValueVisitor final : public VNVisitor {
|
|||
m_setIfRand = true;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstNodeFTask* nodep) override {
|
||||
VL_RESTORER(m_inFunc);
|
||||
m_inFunc = true;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:101:17: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
101 | logic tmp = in;
|
||||
| ^~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:106:17: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
106 | logic tmp = in;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:111:24: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
111 | static logic tmp = in;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:116:17: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
116 | logic tmp = out;
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:121:20: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
121 | logic tmp = in + 1;
|
||||
| ^
|
||||
%Error: t/t_var_static_assign_decl_bad.v:126:26: Static variable initializer
|
||||
: is dependent on automatic variable
|
||||
126 | static int foo = tmp + 1;
|
||||
| ^
|
||||
%Error: t/t_var_static_assign_decl_bad.v:132:26: Static variable initializer
|
||||
: is dependent on automatic variable
|
||||
132 | static int foo = tmp + 1;
|
||||
| ^
|
||||
%Error: t/t_var_static_assign_decl_bad.v:138:29: Static variable initializer
|
||||
: is dependent on automatic variable
|
||||
138 | static logic func_var = loc;
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:9:15: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
9 | logic tmp = in;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:14:15: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
14 | logic tmp = in;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:20:17: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
20 | logic tmp = in;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:25:17: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
25 | logic tmp = in;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:32:17: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
32 | logic tmp = in;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:37:17: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
37 | logic tmp = in;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:44:17: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
44 | logic tmp = in;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:49:17: Static variable initializer
|
||||
: is dependent on function/task I/O variable
|
||||
49 | logic tmp = in;
|
||||
| ^~
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# 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
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
lint(
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Antmicro.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
function static func_stat;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endfunction
|
||||
|
||||
task static task_stat;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endtask
|
||||
|
||||
package pkg;
|
||||
function static func_stat;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endfunction
|
||||
|
||||
task static task_stat;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endtask
|
||||
endpackage
|
||||
|
||||
interface iface;
|
||||
function static func_stat;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endfunction
|
||||
|
||||
task static task_stat;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endtask
|
||||
endinterface
|
||||
|
||||
program prog;
|
||||
function static func_stat;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endfunction
|
||||
|
||||
task static task_stat;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endtask
|
||||
endprogram
|
||||
|
||||
module no_warn#(PARAM = 1)(input in, input clk);
|
||||
typedef enum {A, B} enum_t;
|
||||
|
||||
// Do not warn on variables under modules.
|
||||
logic tmp = in;
|
||||
|
||||
// Do not warn on assignment with module var.
|
||||
function static func;
|
||||
static logic func_var = tmp;
|
||||
endfunction
|
||||
|
||||
// Do not warn on constant assignments.
|
||||
function static func_param;
|
||||
static logic func_var = PARAM;
|
||||
static logic func_enum = A;
|
||||
endfunction
|
||||
|
||||
// Do not warn on assignment referencing module I/O.
|
||||
function static func_module_input;
|
||||
logic tmp = in;
|
||||
endfunction
|
||||
|
||||
// Do not warn on automatic assignment.
|
||||
function automatic func_auto;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endfunction
|
||||
|
||||
// Do not warn on assignment separate from declaration.
|
||||
function static func_decl_and_assign;
|
||||
input logic in;
|
||||
logic tmp;
|
||||
tmp = in;
|
||||
endfunction
|
||||
|
||||
// Do not warn on variables under blocks.
|
||||
initial begin
|
||||
logic init_tmp = in;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
logic always_tmp = in;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module t(input clk);
|
||||
function static func_stat;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endfunction
|
||||
|
||||
task static task_stat;
|
||||
input logic in;
|
||||
logic tmp = in;
|
||||
endtask
|
||||
|
||||
function automatic func_auto_with_static;
|
||||
input logic in;
|
||||
static logic tmp = in;
|
||||
endfunction
|
||||
|
||||
function static func_assign_out;
|
||||
output logic out;
|
||||
logic tmp = out;
|
||||
endfunction
|
||||
|
||||
function static func_assign_expr;
|
||||
input logic in;
|
||||
logic tmp = in + 1;
|
||||
endfunction
|
||||
|
||||
function static int func_assign_static_in_to_auto(input int i);
|
||||
automatic int tmp = i;
|
||||
static int foo = tmp + 1;
|
||||
return foo;
|
||||
endfunction
|
||||
|
||||
function static int func_assign_auto_to_static();
|
||||
automatic int tmp = 0;
|
||||
static int foo = tmp + 1;
|
||||
return foo;
|
||||
endfunction
|
||||
|
||||
function static func_local;
|
||||
automatic logic loc;
|
||||
static logic func_var = loc;
|
||||
endfunction
|
||||
|
||||
iface iface();
|
||||
prog prog;
|
||||
|
||||
logic in;
|
||||
no_warn no_warn(.in(in), .clk(clk));
|
||||
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue