This commit is contained in:
jalcim 2026-03-03 13:41:47 +01:00 committed by GitHub
commit 24542eff1f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 57 additions and 3 deletions

View File

@ -390,6 +390,7 @@ detailed descriptions of these arguments.
-f <file> Parse arguments from a file
-FI <file> Force include of a file
--flatten Force inlining of all modules, tasks and functions
--func-recursion-depth <value> Maximum recursive constant function depth
--future0 <option> Ignore an option for compatibility
--future1 <option> Ignore an option with argument for compatibility
-fno-<optimization> Disable internal optimization stage

View File

@ -610,6 +610,14 @@ Summary:
Flattening large designs may require significant CPU time, memory and
storage.
.. option:: --func-recursion-depth <value>
Specifies the maximum depth of recursive constant function evaluation.
When a recursive function exceeds this depth during constant folding,
Verilator gives up and treats the expression as non-constant.
Defaults to 1000.
.. option:: -fno-acyc-simp
.. option:: -fno-assemble

View File

@ -1590,6 +1590,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
fl->v3error("Unknown --make system specified: '" << valp << "'");
}
});
DECL_OPTION("-func-recursion-depth", Set, &m_funcRecursion);
DECL_OPTION("-max-num-width", Set, &m_maxNumWidth);
DECL_OPTION("-mod-prefix", CbVal, [this, fl](const char* valp) {
validateIdentifier(fl, valp, "--mod-prefix");

View File

@ -330,6 +330,7 @@ private:
int m_localizeMaxSize = 1024; // main switch: --localize-max-size
VOptionBool m_makeDepend; // main switch: -MMD
int m_maxNumWidth = 65536; // main switch: --max-num-width
int m_funcRecursion = 1000; // main switch: --func-recursion-depth
int m_moduleRecursion = 100; // main switch: --module-recursion-depth
int m_outputGroups = -1; // main switch: --output-groups
int m_outputSplit = 20000; // main switch: --output-split
@ -612,6 +613,7 @@ public:
bool jsonIds() const { return m_jsonIds; }
VOptionBool makeDepend() const { return m_makeDepend; }
int maxNumWidth() const { return m_maxNumWidth; }
int funcRecursionDepth() const { return m_funcRecursion; }
int moduleRecursionDepth() const { return m_moduleRecursion; }
int outputSplit() const { return m_outputSplit; }
int outputSplitCFuncs() const { return m_outputSplitCFuncs; }

View File

@ -75,7 +75,6 @@ class SimulateVisitor VL_NOT_FINAL : public VNVisitorConst {
private:
// CONSTANTS
static constexpr int CONST_FUNC_RECURSION_MAX = 1000;
static constexpr int CALL_STACK_MAX = 100;
// NODE STATE
@ -1158,9 +1157,10 @@ private:
UASSERT_OBJ(funcp, nodep, "Not linked");
if (funcp->recursive()) {
if (m_recurseCount >= CONST_FUNC_RECURSION_MAX) {
if (m_recurseCount >= v3Global.opt.funcRecursionDepth()) {
clearOptimizable(funcp, "Constant function recursed more than "s
+ std::to_string(CONST_FUNC_RECURSION_MAX) + " times");
+ std::to_string(v3Global.opt.funcRecursionDepth())
+ " times");
return;
}
++m_recurseCount;

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2026 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('simulator')
test.compile(verilator_flags2=['--func-recursion-depth 2000'])
test.execute()
test.passes()

View File

@ -0,0 +1,24 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2026 by jalcim.
// SPDX-License-Identifier: CC0-1.0
module t;
// Recursive function that needs depth > 1000 to constant-fold
function automatic int recurse_sum;
input int i;
if (i == 0) recurse_sum = 0;
else recurse_sum = i + recurse_sum(i - 1);
endfunction
localparam int S1500 = recurse_sum(1500);
initial begin
if (S1500 !== 1125750) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule