diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index 3027259f5..3ccd63be5 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -2122,14 +2122,14 @@ class AstWith final : public AstNodeExpr { // Children: expression (equation establishing the with) // @astgen op1 := indexArgRefp : AstLambdaArgRef // @astgen op2 := valueArgRefp : AstLambdaArgRef - // @astgen op3 := exprp : AstNodeExpr + // @astgen op3 := exprp : List[AstNode] public: AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp, AstNodeExpr* exprp) : ASTGEN_SUPER_With(fl) { this->indexArgRefp(indexArgRefp); this->valueArgRefp(valueArgRefp); - this->exprp(exprp); + this->addExprp(exprp); } ASTGEN_MEMBERS_AstWith; bool same(const AstNode* /*samep*/) const override { return true; } diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 218517aa0..303480fd2 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -298,7 +298,11 @@ private: } void visit(AstWith* nodep) override { iterateChildren(nodep); - ensureCleanAndNext(nodep->exprp()); + setClean(nodep, true); + } + void visit(AstCReturn* nodep) override { + iterateChildren(nodep); + ensureClean(nodep->lhsp()); setClean(nodep, true); } void visit(AstIntfRef* nodep) override { diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index 165413aab..3a4f0c683 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -476,10 +476,9 @@ public: if (auto* const argrefp = nodep->valueArgRefp()) { putbs(argrefp->dtypep()->cType(argrefp->nameProtect(), false, false)); } - // Probably fragile, V3Task may need to convert to a AstCReturn - puts(") { return "); + puts(") {\n"); iterateAndNextConstNull(nodep->exprp()); - puts("; }\n"); + puts("}\n"); } void visit(AstNodeCase* nodep) override { // LCOV_EXCL_LINE // In V3Case... diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 9bc068a19..95691ce4f 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1371,6 +1371,15 @@ private: iterateChildren(nodep); } } + void visit(AstWith* nodep) override { + if (nodep->user1SetOnce()) { + // Make sure that the return expression is converted only once + return; + } + AstNodeExpr* const withExprp = VN_AS(nodep->exprp()->unlinkFrBack(), NodeExpr); + nodep->addExprp(new AstCReturn{withExprp->fileline(), withExprp}); + iterateChildren(nodep); + } void visit(AstScope* nodep) override { m_scopep = nodep; m_insStmtp = nullptr; diff --git a/test_regress/t/t_array_query_with.v b/test_regress/t/t_array_query_with.v index bb4fa6137..d69ddfa42 100644 --- a/test_regress/t/t_array_query_with.v +++ b/test_regress/t/t_array_query_with.v @@ -4,11 +4,24 @@ // any use, without warranty, 2022 by Antmicro Ltd. // SPDX-License-Identifier: CC0-1.0 -module t (/*AUTOARG*/ - clk - ); +class Cls; + static function bit get_true(); + return 1'b1; + endfunction - input clk; + static function bit test_find_index_in_class(); + if (get_true) begin + int q[$] = {0, -1, 3, 1, 4, 1}; + int found_idx[$]; + found_idx = q.find_index(node) with (node == 1); + return found_idx[0] == 3; + end + return 0; + endfunction +endclass + +module t (/*AUTOARG*/ + ); function bit test_find; string bar[$]; @@ -31,22 +44,31 @@ module t (/*AUTOARG*/ return first_even_idx[0] == 1; endfunction + function bit is_even(int a); + return a % 2 == 0; + endfunction + + function static bit test_find_first_index_by_func; + int q[] = {1, 2, 3, 4, 5, 6}; + int first_even_idx[$] = q.find_first_index(x) with (is_even(x)); + return first_even_idx[0] == 1; + endfunction + function automatic bit test_sort; int q[] = {-5, 2, -3, 0, 4}; q.sort(x) with (x >= 0 ? x : -x); return q[1] == 2; endfunction - always @(posedge clk) begin - bit [3:0] results = {test_find(), test_find_index(), - test_find_first_index(), test_sort()}; - if (results == '1) begin - $write("*-* All Finished *-*\n"); - $finish; - end - else begin - $write("Results: %b\n", results); - $stop; - end + initial begin + if (!test_find()) $stop; + if (!test_find_index()) $stop; + if (!test_find_first_index()) $stop; + if (!test_find_first_index_by_func()) $stop; + if (!test_sort()) $stop; + if (!Cls::test_find_index_in_class()) $stop; + + $write("*-* All Finished *-*\n"); + $finish; end endmodule