Merge c66d4729c2 into 56ed47ee7c
This commit is contained in:
commit
718c19b660
|
|
@ -298,12 +298,39 @@ class BeginVisitor final : public VNVisitor {
|
|||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
void visit(AstVar* nodep) override {
|
||||
if (nodep->user1SetOnce()) { return; }
|
||||
// If static variable, move it outside a function.
|
||||
if (nodep->lifetime().isStatic() && m_ftaskp) {
|
||||
const std::string newName
|
||||
= m_ftaskp->name() + "__Vstatic__" + dot(m_unnamedScope, nodep->name());
|
||||
if (nodep->isIO()) {
|
||||
if (nodep->direction().isRef()) {
|
||||
nodep->v3error(
|
||||
"It is illegal to use argument passing by reference for subroutines with "
|
||||
"a lifetime of static (IEEE 1800-2023 13.5.2)");
|
||||
}
|
||||
// Create a port that is used for passing value between argument and static
|
||||
// variable
|
||||
AstVar* const portp = nodep->cloneTreePure(false);
|
||||
nodep->replaceWith(portp);
|
||||
|
||||
if (nodep->isInput() || nodep->isInout()) {
|
||||
AstAssign* const initAssignp = new AstAssign{
|
||||
nodep->fileline(), new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE},
|
||||
new AstVarRef{portp->fileline(), portp, VAccess::READ}};
|
||||
portp->addNextHere(initAssignp);
|
||||
}
|
||||
|
||||
if (nodep->isWritable()) {
|
||||
AstAssign* const endAssignp = new AstAssign{
|
||||
nodep->fileline(), new AstVarRef{portp->fileline(), portp, VAccess::WRITE},
|
||||
new AstVarRef{nodep->fileline(), nodep, VAccess::READ}};
|
||||
m_ftaskp->addStmtsp(endAssignp);
|
||||
}
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
nodep->name(newName);
|
||||
nodep->unlinkFrBack();
|
||||
m_ftaskp->addHereThisAsNext(nodep);
|
||||
nodep->funcLocal(false);
|
||||
} else if (m_unnamedScope != "") {
|
||||
|
|
|
|||
|
|
@ -443,20 +443,11 @@ class DynScopeVisitor final : public VNVisitor {
|
|||
if (!isEvent && m_afterTimingControl && nodep->varp()->isWritable()
|
||||
&& nodep->access().isWriteOrRW()) {
|
||||
// The output variable may not exist after a delay, so we can't just write to it
|
||||
if (m_inFunc) {
|
||||
nodep->v3error(
|
||||
"Writing to an "
|
||||
<< nodep->varp()->verilogKwd()
|
||||
<< " variable of a function after a timing control is not allowed");
|
||||
} else {
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Writing to a captured "
|
||||
<< nodep->varp()->verilogKwd()
|
||||
<< " variable in a "
|
||||
<< (VN_IS(nodep->backp(), AssignDly)
|
||||
? "non-blocking assignment"
|
||||
: "fork")
|
||||
<< " after a timing control");
|
||||
}
|
||||
nodep->v3error(
|
||||
"Writing to an "
|
||||
<< nodep->varp()->verilogKwd() << " automatic variable of a "
|
||||
<< (m_inFunc ? "function" : "task")
|
||||
<< " after a timing control is not allowed (IEEE 1800-2023 13.2.2)");
|
||||
}
|
||||
if (!framep->instance().initialized()) framep->createInstancePrototype();
|
||||
framep->captureVarInsert(nodep->varp());
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
int m_randSequenceNum = 0; // RandSequence uniqify number
|
||||
VLifetime m_lifetime = VLifetime::STATIC_IMPLICIT; // Propagating lifetime
|
||||
bool m_lifetimeAllowed = false; // True to allow lifetime settings
|
||||
bool m_hasTimingControl = false; // If current task has timing control
|
||||
bool m_moduleWithGenericIface = false; // If current module contains generic interface
|
||||
std::set<AstVar*> m_portDups; // Non-ANSI port datatype duplicating input/output decls
|
||||
|
||||
|
|
@ -248,6 +249,9 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_lifetime);
|
||||
VL_RESTORER(m_lifetimeAllowed);
|
||||
m_lifetimeAllowed = true;
|
||||
VL_RESTORER(m_hasTimingControl);
|
||||
m_hasTimingControl
|
||||
= nodep->exists([](const AstNode* const nodep) { return nodep->isTimingControl(); });
|
||||
if (!nodep->lifetime().isNone()) {
|
||||
m_lifetime = nodep->lifetime().makeImplicit();
|
||||
} else {
|
||||
|
|
@ -382,7 +386,15 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
} else if (m_ftaskp) {
|
||||
if (!nodep->lifetime().isAutomatic()) nodep->lifetime(VLifetime::AUTOMATIC_IMPLICIT);
|
||||
// Variables in static tasks with timing control can be used after the task has ended
|
||||
// with use of join..fork_none, so they need to be static
|
||||
if (m_ftaskp->lifetime().isStatic() && m_hasTimingControl) {
|
||||
nodep->v3warn(IMPLICITSTATIC, "Variable's lifetime implicitly set to static "
|
||||
"because in static task with timing control.");
|
||||
nodep->lifetime(VLifetime::STATIC_IMPLICIT);
|
||||
} else {
|
||||
nodep->lifetime(VLifetime::AUTOMATIC_IMPLICIT);
|
||||
}
|
||||
} else if (nodep->lifetime().isNone()) {
|
||||
// lifetime shouldn't be unknown, set static if none
|
||||
nodep->lifetime(VLifetime::STATIC_IMPLICIT);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=['--binary'])
|
||||
test.compile(verilator_flags2=['--binary', '-Wno-IMPLICITSTATIC'])
|
||||
|
||||
test.execute()
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=['--binary --trace-fst'])
|
||||
test.compile(verilator_flags2=['--binary --trace-fst', '-Wno-IMPLICITSTATIC'])
|
||||
|
||||
test.execute()
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=["--binary -Wno-INITIALDLY"])
|
||||
test.compile(verilator_flags2=["--binary -Wno-INITIALDLY", '-Wno-IMPLICITSTATIC'])
|
||||
|
||||
test.execute()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
%Error-UNSUPPORTED: t/t_fork_dynscope_unsup.v:17:7: Unsupported: Writing to a captured inout variable in a fork after a timing control
|
||||
: ... note: In instance 't'
|
||||
17 | p = #1 1;
|
||||
| ^
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_fork_dynscope_unsup.v:22:5: Unsupported: Writing to a captured output variable in a non-blocking assignment after a timing control
|
||||
: ... note: In instance 't'
|
||||
22 | q <= #1 1;
|
||||
| ^
|
||||
%Error: Exiting due to
|
||||
|
|
@ -11,7 +11,7 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
test.compile(verilator_flags2=["--binary", '-Wno-IMPLICITSTATIC'])
|
||||
|
||||
test.execute()
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||
test.compile(verilator_flags2=["--binary", "-Wno-IMPLICITSTATIC"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
module t;
|
||||
int x1, x2, x3, x4, x5, x6, x7;
|
||||
|
||||
initial begin
|
||||
x1 = -1;
|
||||
x2 = -1;
|
||||
x3 = -1;
|
||||
x4 = -1;
|
||||
|
||||
#1;
|
||||
t1(x1);
|
||||
t2(x2);
|
||||
t3(x3);
|
||||
t4(x4);
|
||||
`checkd(x1, 0)
|
||||
`checkd(x2, -1)
|
||||
`checkd(x3, 1)
|
||||
`checkd(x4, 2)
|
||||
|
||||
#10 t1(x1);
|
||||
t2(x2);
|
||||
t3(x3);
|
||||
t4(x4);
|
||||
`checkd(x1, 1)
|
||||
`checkd(x2, -1)
|
||||
`checkd(x3, 1)
|
||||
`checkd(x4, 2)
|
||||
|
||||
`checkd(x5, 3)
|
||||
`checkd(x6, 0)
|
||||
`checkd(x7, 4)
|
||||
|
||||
#5;
|
||||
`checkd(x1, 1)
|
||||
`checkd(x2, -1)
|
||||
`checkd(x3, 1)
|
||||
`checkd(x4, 2)
|
||||
`checkd(x5, 3)
|
||||
`checkd(x6, 0)
|
||||
`checkd(x7, 4)
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
always #1 t5(x5);
|
||||
always #1 t6(x6);
|
||||
always #1 t7(x7);
|
||||
|
||||
task t1(output int x);
|
||||
fork
|
||||
x = #1 1;
|
||||
join_none
|
||||
if ($time < 10) begin
|
||||
`checkd(x, 0)
|
||||
end
|
||||
else begin
|
||||
`checkd(x, 1)
|
||||
end
|
||||
endtask
|
||||
|
||||
task t2(inout int x);
|
||||
fork
|
||||
x = #1 2;
|
||||
join_none
|
||||
`checkd(x, -1)
|
||||
endtask
|
||||
|
||||
task t3(output int x);
|
||||
if ($time < 10) begin
|
||||
`checkd(x, 0)
|
||||
end
|
||||
else begin
|
||||
`checkd(x, 1)
|
||||
end
|
||||
fork
|
||||
x = #1 1;
|
||||
join_none
|
||||
#2 `checkd(x, 1);
|
||||
endtask
|
||||
|
||||
task t4(inout int x);
|
||||
if ($time < 10) begin
|
||||
`checkd(x, -1)
|
||||
end
|
||||
else begin
|
||||
`checkd(x, 2)
|
||||
end
|
||||
fork
|
||||
x = #1 2;
|
||||
join_none
|
||||
#2 `checkd(x, 2);
|
||||
endtask
|
||||
|
||||
task t5(output int x);
|
||||
x <= #1 3;
|
||||
endtask
|
||||
|
||||
task t6(inout int x);
|
||||
x <= #1 4;
|
||||
endtask
|
||||
|
||||
task static t7(inout int x);
|
||||
int y = 0;
|
||||
x <= #1 4;
|
||||
#2 y = x;
|
||||
`checkd(x, 4)
|
||||
endtask
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
%Warning-IMPLICITSTATIC: t/t_fork_write_after_timing_bad.v:12:19: Variable's lifetime implicitly set to static because in static task with timing control.
|
||||
12 | task t1(ref int x);
|
||||
| ^
|
||||
... For warning description see https://verilator.org/warn/IMPLICITSTATIC?v=latest
|
||||
... Use "/* verilator lint_off IMPLICITSTATIC */" and lint_on around source to disable this message.
|
||||
%Error: t/t_fork_write_after_timing_bad.v:12:19: It is illegal to use argument passing by reference for subroutines with a lifetime of static (IEEE 1800-2023 13.5.2)
|
||||
: ... note: In instance 't'
|
||||
12 | task t1(ref int x);
|
||||
| ^
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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-FileCopyrightText: 2024 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.lint(verilator_flags2=["--timing"], fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -1,24 +1,17 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2024 Antmicro
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t;
|
||||
bit p = 0, q = 0;
|
||||
|
||||
int x1;
|
||||
initial begin
|
||||
t1(p);
|
||||
t2(q);
|
||||
t1(x1);
|
||||
$finish;
|
||||
end
|
||||
|
||||
task t1(inout p);
|
||||
task t1(ref int x);
|
||||
fork
|
||||
p = #1 1;
|
||||
x = #1 2;
|
||||
join_none
|
||||
endtask
|
||||
|
||||
task t2(output q);
|
||||
q <= #1 1;
|
||||
endtask
|
||||
endmodule
|
||||
|
|
@ -1,42 +1,46 @@
|
|||
%Error: t/t_timing_func_fork_bad.v:13:9: Writing to an output variable of a function after a timing control is not allowed
|
||||
%Error: t/t_timing_func_fork_bad.v:13:9: Writing to an output automatic variable of a function after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
13 | f1 = 0;
|
||||
| ^~
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: t/t_timing_func_fork_bad.v:14:9: Writing to an output variable of a function after a timing control is not allowed
|
||||
%Error: t/t_timing_func_fork_bad.v:14:9: Writing to an output automatic variable of a function after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
14 | o1 = 0;
|
||||
| ^~
|
||||
%Error: t/t_timing_func_fork_bad.v:22:9: Writing to an output variable of a function after a timing control is not allowed
|
||||
%Error: t/t_timing_func_fork_bad.v:22:7: Writing to an output automatic variable of a task after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
22 | f2 = #5 0;
|
||||
22 | o1 = 0;
|
||||
| ^~
|
||||
%Error: t/t_timing_func_fork_bad.v:29:9: Writing to an output automatic variable of a function after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
29 | f2 = #5 0;
|
||||
| ^~
|
||||
%Error: t/t_timing_func_fork_bad.v:24:9: Writing to an inout variable of a function after a timing control is not allowed
|
||||
%Error: t/t_timing_func_fork_bad.v:31:9: Writing to an inout automatic variable of a function after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
24 | io2 = 0;
|
||||
31 | io2 = 0;
|
||||
| ^~~
|
||||
%Error: t/t_timing_func_fork_bad.v:34:9: Writing to an output variable of a function after a timing control is not allowed
|
||||
%Error: t/t_timing_func_fork_bad.v:41:9: Writing to an output automatic variable of a function after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
34 | f3 = 0;
|
||||
41 | f3 = 0;
|
||||
| ^~
|
||||
%Error: t/t_timing_func_fork_bad.v:35:9: Writing to an output variable of a function after a timing control is not allowed
|
||||
%Error: t/t_timing_func_fork_bad.v:42:9: Writing to an output automatic variable of a function after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
35 | o3 = 0;
|
||||
42 | o3 = 0;
|
||||
| ^~
|
||||
%Error: t/t_timing_func_fork_bad.v:43:9: Writing to an output variable of a function after a timing control is not allowed
|
||||
%Error: t/t_timing_func_fork_bad.v:50:9: Writing to an output automatic variable of a function after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
43 | f4 = @e 0;
|
||||
50 | f4 = @e 0;
|
||||
| ^~
|
||||
%Error: t/t_timing_func_fork_bad.v:45:9: Writing to an inout variable of a function after a timing control is not allowed
|
||||
%Error: t/t_timing_func_fork_bad.v:52:9: Writing to an inout automatic variable of a function after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
45 | io4 = 0;
|
||||
52 | io4 = 0;
|
||||
| ^~~
|
||||
%Error: t/t_timing_func_fork_bad.v:56:9: Writing to an output variable of a function after a timing control is not allowed
|
||||
%Error: t/t_timing_func_fork_bad.v:63:9: Writing to an output automatic variable of a function after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
56 | f5 = 0;
|
||||
63 | f5 = 0;
|
||||
| ^~
|
||||
%Error: t/t_timing_func_fork_bad.v:57:9: Writing to an output variable of a function after a timing control is not allowed
|
||||
%Error: t/t_timing_func_fork_bad.v:64:9: Writing to an output automatic variable of a function after a timing control is not allowed (IEEE 1800-2023 13.2.2)
|
||||
: ... note: In instance 't'
|
||||
57 | o5 = 0;
|
||||
64 | o5 = 0;
|
||||
| ^~
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
module t;
|
||||
|
||||
function int f1(output int o1);
|
||||
function automatic int f1(output int o1);
|
||||
fork
|
||||
begin
|
||||
#1 $stop;
|
||||
|
|
@ -16,7 +16,14 @@ module t;
|
|||
join_none
|
||||
endfunction
|
||||
|
||||
function int f2(inout io2);
|
||||
task automatic t1(output int o1);
|
||||
fork begin
|
||||
#1 $stop;
|
||||
o1 = 0;
|
||||
end join_none
|
||||
endtask
|
||||
|
||||
function automatic int f2(inout io2);
|
||||
fork
|
||||
begin
|
||||
f2 = #5 0;
|
||||
|
|
@ -27,7 +34,7 @@ module t;
|
|||
endfunction
|
||||
|
||||
event e;
|
||||
function int f3(output int o3);
|
||||
function automatic int f3(output int o3);
|
||||
fork
|
||||
begin
|
||||
@e $stop;
|
||||
|
|
@ -37,7 +44,7 @@ module t;
|
|||
join_none
|
||||
endfunction
|
||||
|
||||
function int f4(inout int io4);
|
||||
function automatic int f4(inout int io4);
|
||||
fork
|
||||
begin
|
||||
f4 = @e 0;
|
||||
|
|
@ -49,7 +56,7 @@ module t;
|
|||
|
||||
int i;
|
||||
|
||||
function int f5(output int o5);
|
||||
function automatic int f5(output int o5);
|
||||
fork
|
||||
begin
|
||||
wait (i == 0) $stop;
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ if re.search(r'clang', test.cxx_version):
|
|||
test.skip("uvm_regex.cc from upstream has clang warnings")
|
||||
|
||||
test.compile(verilator_flags2=[
|
||||
"--binary", test.build_jobs, "--vpi", "+define+T_V2017_1_0", "+incdir+t/uvm/v2017_1_0",
|
||||
test.pli_filename
|
||||
"--binary", "-Wno-IMPLICITSTATIC", test.build_jobs, "--vpi", "+define+T_V2017_1_0",
|
||||
"+incdir+t/uvm/v2017_1_0", test.pli_filename
|
||||
])
|
||||
|
||||
test.execute(expect_filename=test.golden_filename)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ if re.search(r'clang', test.cxx_version):
|
|||
|
||||
test.compile(verilator_flags2=[
|
||||
"--binary", test.build_jobs, "--vpi", "+define+T_V2020_3_1", "+incdir+t/uvm/v2020_3_1",
|
||||
test.pli_filename
|
||||
"-Wno-IMPLICITSTATIC", test.pli_filename
|
||||
])
|
||||
|
||||
test.execute(expect_filename=test.golden_filename)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ test.compile(v_flags2=[
|
|||
"--vpi",
|
||||
"--CFLAGS -O0",
|
||||
"-Wall",
|
||||
"-Wno-IMPLICITSTATIC",
|
||||
"+incdir+t/uvm", #
|
||||
"t/uvm/uvm_pkg_all_v2017_1_0_dpi.svh",
|
||||
test.pli_filename
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ test.compile(v_flags2=[
|
|||
"--vpi",
|
||||
"--CFLAGS -O0",
|
||||
"-Wall",
|
||||
'-Wno-IMPLICITSTATIC',
|
||||
"+incdir+t/uvm", #
|
||||
"t/uvm/uvm_pkg_all_v2020_3_1_dpi.svh",
|
||||
test.pli_filename
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(v_flags2=["--binary"], verilator_make_gmake=False)
|
||||
test.compile(v_flags2=["--binary", '-Wno-IMPLICITSTATIC'], verilator_make_gmake=False)
|
||||
|
||||
test.execute()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue