From a6015863d8a48e7a69a26e5930caf151301b0d4c Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Fri, 21 Jul 2023 09:27:00 +0200 Subject: [PATCH] Support for static method calls as default values of function arguments (#4378) --- src/V3Task.cpp | 21 ++++++++++++++++----- test_regress/t/t_func_defaults.v | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 5fbd76ce3..163b5d37e 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1546,6 +1546,13 @@ private: iterateChildren(nodep); m_insStmtp = nullptr; // Next thing should be new statement } + void visit(AstVar* nodep) override { + if (nodep->isFuncLocal() && nodep->direction() == VDirection::INPUT && nodep->valuep()) { + // It's the default value of optional argument. + // Such values are added to function calls on this stage and aren't needed here. + pushDeletep(nodep->valuep()->unlinkFrBack()); + } + } void visit(AstStmtExpr* nodep) override { m_insMode = IM_BEFORE; m_insStmtp = nodep; @@ -1658,7 +1665,14 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) << portp->prettyNameQ() << " in function call to " << nodep->taskp()->prettyTypeName()); newvaluep = new AstConst{nodep->fileline(), AstConst::Unsized32{}, 0}; - } else if (!VN_IS(portp->valuep(), Const)) { + } else if (AstFuncRef* const funcRefp = VN_CAST(portp->valuep(), FuncRef)) { + const AstNodeFTask* const funcp = funcRefp->taskp(); + if (funcp->classMethod() && funcp->lifetime().isStatic()) newvaluep = funcRefp; + } else if (AstConst* const constp = VN_CAST(portp->valuep(), Const)) { + newvaluep = constp; + } + + if (!newvaluep) { // The default value for this port might be a constant // expression that hasn't been folded yet. Try folding it // now; we don't have much to lose if it fails. @@ -1672,12 +1686,9 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) << portp->prettyNameQ() << " in function call to " << nodep->taskp()->prettyTypeName()); newvaluep = new AstConst{nodep->fileline(), AstConst::Unsized32{}, 0}; - } else { - newvaluep = newvaluep->cloneTree(true); } - } else { - newvaluep = VN_AS(portp->valuep(), NodeExpr)->cloneTree(true); } + newvaluep = newvaluep->cloneTree(true); // To avoid problems with callee needing to know to deleteTree // or not, we make this into a pin UINFO(9, "Default pin for " << portp << endl); diff --git a/test_regress/t/t_func_defaults.v b/test_regress/t/t_func_defaults.v index 7928a0bce..3d360fa7a 100644 --- a/test_regress/t/t_func_defaults.v +++ b/test_regress/t/t_func_defaults.v @@ -19,6 +19,17 @@ function automatic logic [1:0] foo return x + y; endfunction +class Foo; + static int x; + function static int get_x; + return x; + endfunction +endclass + +function int mult2(int x = Foo::get_x()); + return 2 * x; +endfunction + module t (/*AUTOARG*/); logic [1:0] foo_val; @@ -26,6 +37,11 @@ module t (/*AUTOARG*/); foo_val = foo(); if (foo_val != 2'b10) $stop; + if (mult2(1) != 2) $stop; + if (mult2() != 0) $stop; + Foo::x = 30; + if (mult2() != 60) $stop; + $write("*-* All Finished *-*\n"); $finish; end