From aa0ef554b3e18d5d08b1201bb397cadf75ac34a1 Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Fri, 21 Jul 2023 09:29:11 +0200 Subject: [PATCH] Fix order of evaluation of function calls in statements (#4375) --- src/V3Task.cpp | 8 +----- test_regress/t/t_func_call_order.pl | 21 +++++++++++++++ test_regress/t/t_func_call_order.v | 42 +++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 7 deletions(-) create mode 100755 test_regress/t/t_func_call_order.pl create mode 100644 test_regress/t/t_func_call_order.v diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 163b5d37e..a37cc1c6e 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -350,7 +350,6 @@ private: // TYPES enum InsertMode : uint8_t { IM_BEFORE, // Pointing at statement ref is in, insert before this - IM_AFTER, // Pointing at last inserted stmt, insert after IM_WHILE_PRECOND // Pointing to for loop, add to body end }; using DpiCFuncs = std::map>; @@ -1346,16 +1345,13 @@ private: AstNode* insertBeforeStmt(AstNode* nodep, AstNode* newp) { // Return node that must be visited, if any if (debug() >= 9) nodep->dumpTree("- newstmt: "); - UASSERT_OBJ(m_insStmtp, nodep, "Function not underneath a statement"); + UASSERT_OBJ(m_insStmtp, nodep, "Function call not underneath a statement"); AstNode* visitp = nullptr; if (m_insMode == IM_BEFORE) { // Add the whole thing before insertAt UINFO(5, " IM_Before " << m_insStmtp << endl); if (debug() >= 9) newp->dumpTree("- newfunc: "); m_insStmtp->addHereThisAsNext(newp); - } else if (m_insMode == IM_AFTER) { - UINFO(5, " IM_After " << m_insStmtp << endl); - m_insStmtp->addNextHere(newp); } else if (m_insMode == IM_WHILE_PRECOND) { UINFO(5, " IM_While_Precond " << m_insStmtp << endl); AstWhile* const whilep = VN_AS(m_insStmtp, While); @@ -1365,8 +1361,6 @@ private: } else { nodep->v3fatalSrc("Unknown InsertMode"); } - m_insMode = IM_AFTER; - m_insStmtp = newp; return visitp; } diff --git a/test_regress/t/t_func_call_order.pl b/test_regress/t/t_func_call_order.pl new file mode 100755 index 000000000..aabcde63e --- /dev/null +++ b/test_regress/t/t_func_call_order.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 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(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_call_order.v b/test_regress/t/t_func_call_order.v new file mode 100644 index 000000000..7bba5a785 --- /dev/null +++ b/test_regress/t/t_func_call_order.v @@ -0,0 +1,42 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +`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); + +module t(/*AUTOARG*/); + int a; + function int assign5; + a = 5; + return 5; + endfunction + function int assign3; + a = 3; + return 3; + endfunction + function int incr; + a++; + return a; + endfunction + function int assign5_return_arg(int x); + a = 5; + return x; + endfunction + int i; + + initial begin + a = 1; + i = assign5() + assign3() + incr(); + `checkd(a, 4); `checkd(i, 12); + + a = 1; + i = assign5_return_arg(assign3()+incr()); + `checkd(a, 5); `checkd(i, 7); + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule