diff --git a/src/V3Task.cpp b/src/V3Task.cpp index ceea85b75..b59ca7065 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -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()) { diff --git a/test_regress/t/t_func_ref_unsup.pl b/test_regress/t/t_func_ref.pl similarity index 55% rename from test_regress/t/t_func_ref_unsup.pl rename to test_regress/t/t_func_ref.pl index 23eda8f99..e64ab41be 100755 --- a/test_regress/t/t_func_ref_unsup.pl +++ b/test_regress/t/t_func_ref.pl @@ -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); diff --git a/test_regress/t/t_func_ref_unsup.v b/test_regress/t/t_func_ref.v similarity index 100% rename from test_regress/t/t_func_ref_unsup.v rename to test_regress/t/t_func_ref.v diff --git a/test_regress/t/t_func_ref_unsup.out b/test_regress/t/t_func_ref_unsup.out deleted file mode 100644 index 1888aea08..000000000 --- a/test_regress/t/t_func_ref_unsup.out +++ /dev/null @@ -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 diff --git a/test_regress/t/t_queue_persistence.v b/test_regress/t/t_queue_persistence.v index 26f4dfa11..2327e7530 100644 --- a/test_regress/t/t_queue_persistence.v +++ b/test_regress/t/t_queue_persistence.v @@ -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"); diff --git a/test_regress/t/t_queue_persistence_inl_unsup.pl b/test_regress/t/t_queue_persistence_inl.pl similarity index 81% rename from test_regress/t/t_queue_persistence_inl_unsup.pl rename to test_regress/t/t_queue_persistence_inl.pl index bbbc342e1..fee610ab8 100755 --- a/test_regress/t/t_queue_persistence_inl_unsup.pl +++ b/test_regress/t/t_queue_persistence_inl.pl @@ -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, ); } diff --git a/test_regress/t/t_queue_persistence_inl_unsup.out b/test_regress/t/t_queue_persistence_inl_unsup.out deleted file mode 100644 index 97622e53f..000000000 --- a/test_regress/t/t_queue_persistence_inl_unsup.out +++ /dev/null @@ -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