diff --git a/Changes b/Changes index 35974cbf0..a429b4e0e 100644 --- a/Changes +++ b/Changes @@ -29,6 +29,7 @@ Verilator 5.031 devel * Add coverage point hierarchy to coverage reports (#5575) (#5576). [Andrew Nolte] * Add warning on global constraints (#5625). [Ryszard Rozak, Antmicro Ltd.] * Add error on `solve before` or soft constraints of `randc` variable. +* Add `--fno-inline-funcs` to disable function inlining. * Improve concatenation performance (#5598) (#5599) (#5602). [Geza Lore] * Fix dotted reference in delay value (#2410). * Fix `function fork...join_none` regression with unknown type (#4449). diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 9b252f51e..5b9aaf3f0 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -599,6 +599,8 @@ Summary: .. option:: -fno-inline +.. option:: -fno-inline-funcs + .. option:: -fno-life .. option:: -fno-life-post diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 2980e3467..a5ea5f7e0 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1317,6 +1317,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, DECL_OPTION("-ffunc-opt-split-cat", FOnOff, &m_fFuncSplitCat); DECL_OPTION("-fgate", FOnOff, &m_fGate); DECL_OPTION("-finline", FOnOff, &m_fInline); + DECL_OPTION("-finline-funcs", FOnOff, &m_fInlineFuncs); DECL_OPTION("-flife", FOnOff, &m_fLife); DECL_OPTION("-flife-post", FOnOff, &m_fLifePost); DECL_OPTION("-flocalize", FOnOff, &m_fLocalize); diff --git a/src/V3Options.h b/src/V3Options.h index c1b295c90..c60a86224 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -390,6 +390,7 @@ private: bool m_fFuncSplitCat = true; // main switch: -fno-func-split-cat: expansion of C macros bool m_fGate; // main switch: -fno-gate: gate wire elimination bool m_fInline; // main switch: -fno-inline: module inlining + bool m_fInlineFuncs = true; // main switch: -fno-inline-funcs: function inlining bool m_fLife; // main switch: -fno-life: variable lifetime bool m_fLifePost; // main switch: -fno-life-post: delayed assignment elimination bool m_fLocalize; // main switch: -fno-localize: convert temps to local variables @@ -685,6 +686,7 @@ public: bool fFunc() const { return fFuncSplitCat() || fFuncBalanceCat(); } bool fGate() const { return m_fGate; } bool fInline() const { return m_fInline; } + bool fInlineFuncs() const { return m_fInlineFuncs; } bool fLife() const { return m_fLife; } bool fLifePost() const { return m_fLifePost; } bool fLocalize() const { return m_fLocalize; } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index f7b810765..b54af15c1 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -30,6 +30,7 @@ #include "V3Const.h" #include "V3EmitCBase.h" #include "V3Graph.h" +#include "V3Stats.h" #include @@ -132,7 +133,9 @@ public: void remapFuncClassp(AstNodeFTask* nodep, AstNodeFTask* newp) { m_funcToClassMap[newp] = getClassp(nodep); } - bool ftaskNoInline(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->noInline(); } + bool ftaskNoInline(AstNodeFTask* nodep) { + return !v3Global.opt.fInlineFuncs() || getFTaskVertex(nodep)->noInline(); + } AstCFunc* ftaskCFuncp(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->cFuncp(); } void ftaskCFuncp(AstNodeFTask* nodep, AstCFunc* cfuncp) { getFTaskVertex(nodep)->cFuncp(cfuncp); @@ -365,7 +368,10 @@ class TaskVisitor final : public VNVisitor { AstNode* m_insStmtp = nullptr; // Where to insert statement bool m_inSensesp = false; // Are we under a senitem? int m_modNCalls = 0; // Incrementing func # for making symbols + + // STATE - across all visitors DpiCFuncs m_dpiNames; // Map of all created DPI functions + VDouble0 m_statInlines; // Statistic tracking // METHODS @@ -1454,6 +1460,7 @@ class TaskVisitor final : public VNVisitor { beginp = createNonInlinedFTask(nodep, namePrefix, outvscp, cnewp /*ref*/); } else { beginp = createInlinedFTask(nodep, namePrefix, outvscp); + ++m_statInlines; } if (VN_IS(nodep, New)) { @@ -1606,7 +1613,7 @@ public: : m_statep{statep} { iterate(nodep); } - ~TaskVisitor() override = default; + ~TaskVisitor() { V3Stats::addStat("Optimizations, Functions inlined", m_statInlines); } }; //###################################################################### diff --git a/test_regress/driver.py b/test_regress/driver.py index 1ae850a38..cd7015d23 100755 --- a/test_regress/driver.py +++ b/test_regress/driver.py @@ -2450,7 +2450,7 @@ class VlTest: if not match: self.error("File_grep: " + filename + ": Regexp not found: " + regexp) return None - if expvalue and str(expvalue) != match.group(1): + if expvalue is not None and str(expvalue) != match.group(1): self.error("File_grep: " + filename + ": Got='" + match.group(1) + "' Expected='" + str(expvalue) + "' in regexp: '" + regexp + "'") return None @@ -2472,7 +2472,7 @@ class VlTest: return match = re.search(regexp, contents) if match: - if expvalue and str(expvalue) != match.group(1): + if expvalue is not None and str(expvalue) != match.group(1): self.error("file_grep: " + filename + ": Got='" + match.group(1) + "' Expected='" + str(expvalue) + "' in regexp: " + regexp) return diff --git a/test_regress/t/t_opt_inline_funcs.py b/test_regress/t/t_opt_inline_funcs.py new file mode 100755 index 000000000..53c9b79fa --- /dev/null +++ b/test_regress/t/t_opt_inline_funcs.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--stats'], verilator_make_gmake=False) + +test.file_grep(test.stats, r'Optimizations, Functions inlined\s+(\d+)', 2) + +test.passes() diff --git a/test_regress/t/t_opt_inline_funcs.v b/test_regress/t/t_opt_inline_funcs.v new file mode 100644 index 000000000..0fb2c6e2b --- /dev/null +++ b/test_regress/t/t_opt_inline_funcs.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + function void allfin; + $write("*-* All Finished *-*\n"); + endfunction + + task done; + $finish; + endtask + + initial begin + allfin(); + done(); + end +endmodule diff --git a/test_regress/t/t_opt_inline_funcs_no.py b/test_regress/t/t_opt_inline_funcs_no.py new file mode 100755 index 000000000..28f5acd13 --- /dev/null +++ b/test_regress/t/t_opt_inline_funcs_no.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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 + +import vltest_bootstrap + +test.scenarios('vlt') +test.top_filename = "t/t_opt_inline_funcs.v" + +test.compile(verilator_flags2=['--fno-inline-funcs', '--stats'], verilator_make_gmake=False) + +test.file_grep(test.stats, r'Optimizations, Functions inlined\s+(\d+)', 0) + +test.passes()