Fix inline function ref port persistence

This commit is contained in:
Wilson Snyder 2024-07-23 18:47:04 -04:00
parent d2dfcbca53
commit 1e3c7a5496
7 changed files with 54 additions and 40 deletions

View File

@ -198,7 +198,22 @@ private:
}
// We make multiple edges if a task is called multiple times from another task.
UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked task");
new TaskEdge{&m_callGraph, m_curVxp, getFTaskVertex(nodep->taskp())};
TaskFTaskVertex* const taskVtxp = getFTaskVertex(nodep->taskp());
new TaskEdge{&m_callGraph, m_curVxp, taskVtxp};
// Do we have to disable inlining the function?
const V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp());
if (!taskVtxp->noInline()) { // Else short-circuit below
for (const auto& itr : tconnects) {
const AstVar* const portp = itr.first;
const AstArg* const argp = itr.second;
if (const AstNodeExpr* const pinp = argp->exprp()) {
if ((portp->isRef() || portp->isConstRef()) && !VN_IS(pinp, VarRef)) {
UINFO(9, "No function inline due to ref " << pinp << endl);
taskVtxp->noInline(true);
}
}
}
}
}
void visit(AstNodeFTask* nodep) override {
UINFO(9, " TASK " << nodep << endl);
@ -494,12 +509,7 @@ class TaskVisitor final : public VNVisitor {
UASSERT_OBJ(localVscp, varrefp, "Null var scope");
portp->user2p(localVscp);
} else {
pinp->v3warn(E_TASKNSVAR, "Unsupported: ref argument of inlined "
"function/task is not a simple variable");
// Providing a var to avoid an internal error.
AstVarScope* const newvscp
= createVarScope(portp, namePrefix + "__" + portp->shortName());
portp->user2p(newvscp);
pinp->v3fatalSrc("ref argument should have caused non-inline of function");
}
}
} else if (portp->isInoutish()) {

View File

@ -1,18 +1,20 @@
#!/usr/bin/perl
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# 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(vlt => 1);
scenarios(simulator => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
compile(
);
execute(
check_finished => 1,
);
ok(1);

View File

@ -1,8 +0,0 @@
%Error-TASKNSVAR: t/t_func_ref_unsup.v:29:28: Unsupported: ref argument of inlined function/task is not a simple variable
29 | b = get_val_set_5(mi.x);
| ^
... For error description see https://verilator.org/warn/TASKNSVAR?v=latest
%Error-TASKNSVAR: t/t_func_ref_unsup.v:34:28: Unsupported: ref argument of inlined function/task is not a simple variable
34 | b = get_val_set_5(arr[0]);
| ^
%Error: Exiting due to

View File

@ -9,7 +9,8 @@
module t(/*AUTOARG*/);
int q[$];
int qdel[$];
int qkept[$];
task automatic func(ref int vrefed);
`ifdef TEST_NOINLINE
@ -18,23 +19,35 @@ module t(/*AUTOARG*/);
`checkd(vrefed, 2);
#100;
vrefed = 10;
#10;
`checkd(vrefed, 10);
endtask
initial begin
q.push_back(1);
q.push_back(2);
q.push_back(3);
`checkd(q[0], 1);
`checkd(q[1], 2);
`checkd(q[2], 3);
func(q[1]);
qkept.push_back(1);
qkept.push_back(2);
qkept.push_back(3);
qdel = qkept;
$display("qkept=%p qdel=%p", qkept, qdel);
`checkd(qkept[0], 1);
`checkd(qkept[1], 2);
`checkd(qkept[2], 3);
func(qdel[1]);
func(qkept[1]);
$display("qkept=%p qdel=%p", qkept, qdel);
`checkd(qdel.size, 0);
`checkd(qkept[0], 1);
`checkd(qkept[1], 10);
`checkd(qkept[2], 3);
end
initial begin
#50;
`checkd(q[1], 2);
q.delete();
`checkd(qdel[1], 2);
`checkd(qkept[1], 2);
qdel.delete();
#100;
$write("*-* All Finished *-*\n");

View File

@ -18,9 +18,11 @@ if (!$Self->have_coroutines) {
else {
compile(
timing_loop => 1,
verilator_flags2 => ["--binary --timing"],
fails => 1, # bug3385 need to fix "ref"
expect_filename => $Self->{golden_filename},
verilator_flags2 => ["--timing"],
);
execute(
check_finished => 1,
);
}

View File

@ -1,5 +0,0 @@
%Error-TASKNSVAR: t/t_queue_persistence.v:31:13: Unsupported: ref argument of inlined function/task is not a simple variable
31 | func(q[1]);
| ^
... For error description see https://verilator.org/warn/TASKNSVAR?v=latest
%Error: Exiting due to