Error on static variable initializers using automatic variables in procedures (#5296)

This commit is contained in:
Bartłomiej Chmiel 2024-08-05 09:39:43 +02:00 committed by GitHub
parent 37a4002098
commit 99c619a4c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 272 additions and 0 deletions

View File

@ -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); }

View File

@ -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

View File

@ -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;

View File

@ -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