From 6a5d3b0b722bd3fdce87459506d1fe675a2e9d4f Mon Sep 17 00:00:00 2001 From: Todd Strader Date: Mon, 23 Feb 2026 16:51:37 -0500 Subject: [PATCH] Add --max-replication option (#7139) --- bin/verilator | 1 + docs/guide/exe_verilator.rst | 8 ++++++++ src/V3Number.cpp | 5 +++-- src/V3Options.cpp | 4 ++++ src/V3Options.h | 2 ++ test_regress/t/t_concat_large.py | 4 ++-- test_regress/t/t_concat_large.v | 4 ++-- test_regress/t/t_concat_large_bad.out | 10 +++++++--- test_regress/t/t_concat_large_bad.v | 1 + test_regress/t/t_concat_large_flag.py | 19 +++++++++++++++++++ test_regress/t/t_concat_large_flag_zero.py | 19 +++++++++++++++++++ test_regress/t/t_flag_values_bad.out | 1 + test_regress/t/t_flag_values_bad.py | 2 +- test_regress/t/t_func_const3_bad.out | 2 +- 14 files changed, 71 insertions(+), 11 deletions(-) create mode 100755 test_regress/t/t_concat_large_flag.py create mode 100755 test_regress/t/t_concat_large_flag_zero.py diff --git a/bin/verilator b/bin/verilator index b79d0c29c..ab07e6201 100755 --- a/bin/verilator +++ b/bin/verilator @@ -482,6 +482,7 @@ detailed descriptions of these arguments. --quiet-stats Don't print statistics --relative-includes Resolve includes relative to current file --reloop-limit Minimum iterations for forming loops + --replication-limit Replication concatenation limit (default: 8k) --report-unoptflat Extra diagnostics for UNOPTFLAT --rr Run Verilator and record with rr --runtime-debug Enable model runtime debugging diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 572b2c68f..a3d421fff 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -1516,6 +1516,14 @@ Summary: improve C++ compilation time on designs where these sequences are common; however, the effect on model performance requires benchmarking. +.. option:: --replication-limit + + Set the limit for replication concatenation (e.g. {1024{1'b1}}). Also applies + to unsized literals (e.g. '0). + + This option is on by default with a value of 8k. To disable, pass with a + value of 0. + .. option:: --report-unoptflat Enable extra diagnostics for :option:`UNOPTFLAT` warnings. This diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 616d7ac82..61a8460af 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -1532,8 +1532,9 @@ V3Number& V3Number::opRepl(const V3Number& lhs, // i op repl, L(i)*value(rhs) bit return NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); - if (rhsval > 8192) { - v3warn(WIDTHCONCAT, "More than a 8k bit replication is probably wrong: " << rhsval); + if (v3Global.opt.replicationLimit() && rhsval > (uint32_t)v3Global.opt.replicationLimit()) { + v3warn(WIDTHCONCAT, "Replication of more that --replication-limit " + << v3Global.opt.replicationLimit() << " is suspect: " << rhsval); } setZero(); int obit = 0; diff --git a/src/V3Options.cpp b/src/V3Options.cpp index f2b160962..246aee89e 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1700,6 +1700,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, if (m_reloopLimit < 2) fl->v3error("--reloop-limit must be >= 2: " << valp); }); DECL_OPTION("-report-unoptflat", OnOff, &m_reportUnoptflat); + DECL_OPTION("-replication-limit", CbVal, [this, fl](const char* valp) { + m_replicationLimit = std::atoi(valp); + if (m_replicationLimit < 0) fl->v3error("--replication-limit must be >= 0: " << valp); + }); DECL_OPTION("-rr", CbCall, []() {}); // Processed only in bin/verilator shell DECL_OPTION("-runtime-debug", CbCall, [this, fl]() { decorations(fl, "node"); diff --git a/src/V3Options.h b/src/V3Options.h index 52b01c2ac..08df2599d 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -338,6 +338,7 @@ private: int m_preprocTokenLimit = 40000; // main switch: --preproc-token-limit int m_publicDepth = 0; // main switch: --public-depth int m_reloopLimit = 40; // main switch: --reloop-limit + int m_replicationLimit = 8192; // main switch: --replication-limit VOptionBool m_skipIdentical; // main switch: --skip-identical bool m_stopFail = true; // main switch: --stop-fail int m_threads = 1; // main switch: --threads @@ -615,6 +616,7 @@ public: int outputGroups() const { return m_outputGroups; } int pinsBv() const VL_MT_SAFE { return m_pinsBv; } int reloopLimit() const { return m_reloopLimit; } + int replicationLimit() const { return m_replicationLimit; } VOptionBool skipIdentical() const { return m_skipIdentical; } bool stopFail() const { return m_stopFail; } int threads() const VL_MT_SAFE { return m_threads; } diff --git a/test_regress/t/t_concat_large.py b/test_regress/t/t_concat_large.py index 3cc73805c..8d105c7c5 100755 --- a/test_regress/t/t_concat_large.py +++ b/test_regress/t/t_concat_large.py @@ -9,9 +9,9 @@ import vltest_bootstrap -test.scenarios('simulator') +test.scenarios("simulator") -test.compile() +test.compile(verilator_flags2=["--Wno-WIDTHCONCAT"]) test.execute() diff --git a/test_regress/t/t_concat_large.v b/test_regress/t/t_concat_large.v index 8f0adcb35..ee6d315f9 100644 --- a/test_regress/t/t_concat_large.v +++ b/test_regress/t/t_concat_large.v @@ -9,10 +9,10 @@ module t; reg [32767:0] a; initial begin - // verilator lint_off WIDTHCONCAT a = {32768{1'b1}}; - // verilator lint_on WIDTHCONCAT if (a[32000] != 1'b1) $stop; + a = '0; + if (a[32000] != 1'b0) $stop; $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_concat_large_bad.out b/test_regress/t/t_concat_large_bad.out index 9ae1fcc8c..2b458b997 100644 --- a/test_regress/t/t_concat_large_bad.out +++ b/test_regress/t/t_concat_large_bad.out @@ -1,7 +1,11 @@ -%Warning-WIDTHCONCAT: t/t_concat_large_bad.v:9:29: More than a 8k bit replication is probably wrong: 32768 +%Warning-WIDTHCONCAT: t/t_concat_large_bad.v:10:23: Replication of more that --replication-limit 8192 is suspect: 32768 + : ... note: In instance 't' + 10 | wire [32767:0] b = '0; + | ^~ + ... For warning description see https://verilator.org/warn/WIDTHCONCAT?v=latest + ... Use "/* verilator lint_off WIDTHCONCAT */" and lint_on around source to disable this message. +%Warning-WIDTHCONCAT: t/t_concat_large_bad.v:9:29: Replication of more that --replication-limit 8192 is suspect: 32768 : ... note: In instance 't' 9 | wire [32767:0] a = {32768{1'b1}}; | ^ - ... For warning description see https://verilator.org/warn/WIDTHCONCAT?v=latest - ... Use "/* verilator lint_off WIDTHCONCAT */" and lint_on around source to disable this message. %Error: Exiting due to diff --git a/test_regress/t/t_concat_large_bad.v b/test_regress/t/t_concat_large_bad.v index 7d489f61f..e97257ce0 100644 --- a/test_regress/t/t_concat_large_bad.v +++ b/test_regress/t/t_concat_large_bad.v @@ -7,6 +7,7 @@ module t; wire [32767:0] a = {32768{1'b1}}; + wire [32767:0] b = '0; initial begin $stop; diff --git a/test_regress/t/t_concat_large_flag.py b/test_regress/t/t_concat_large_flag.py new file mode 100755 index 000000000..ba2879438 --- /dev/null +++ b/test_regress/t/t_concat_large_flag.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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-FileCopyrightText: 2024 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios("simulator") +test.top_filename = "t/t_concat_large.v" + +test.compile(verilator_flags2=["--replication-limit 32768"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_concat_large_flag_zero.py b/test_regress/t/t_concat_large_flag_zero.py new file mode 100755 index 000000000..feda09073 --- /dev/null +++ b/test_regress/t/t_concat_large_flag_zero.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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-FileCopyrightText: 2024 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios("simulator") +test.top_filename = "t/t_concat_large.v" + +test.compile(verilator_flags2=["--replication-limit 0"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_flag_values_bad.out b/test_regress/t/t_flag_values_bad.out index ff3be40f5..d875faf80 100644 --- a/test_regress/t/t_flag_values_bad.out +++ b/test_regress/t/t_flag_values_bad.out @@ -3,4 +3,5 @@ %Error: --output-split-ctrace must be >= 0: -1 %Error: --preproc-token-limit must be > 0: 0 %Error: --reloop-limit must be >= 2: -1 +%Error: --replication-limit must be >= 0: -1 %Error: Exiting due to diff --git a/test_regress/t/t_flag_values_bad.py b/test_regress/t/t_flag_values_bad.py index e21fbaf55..e8b403f54 100755 --- a/test_regress/t/t_flag_values_bad.py +++ b/test_regress/t/t_flag_values_bad.py @@ -13,7 +13,7 @@ test.scenarios('vlt') test.lint(verilator_flags2=[ "--output-split-cfuncs -1", "--output-split-ctrace -1", "--preproc-token-limit 0", - "--reloop-limit -1" + "--reloop-limit -1", "--replication-limit -1" ], fails=True, expect_filename=test.golden_filename) diff --git a/test_regress/t/t_func_const3_bad.out b/test_regress/t/t_func_const3_bad.out index 6172af3b0..4c996d982 100644 --- a/test_regress/t/t_func_const3_bad.out +++ b/test_regress/t/t_func_const3_bad.out @@ -1,4 +1,4 @@ -%Warning-WIDTHCONCAT: t/t_func_const3_bad.v:12:28: More than a 8k bit replication is probably wrong: 9000 +%Warning-WIDTHCONCAT: t/t_func_const3_bad.v:12:28: Replication of more that --replication-limit 8192 is suspect: 9000 : ... note: In instance 't.b9k.c9' 12 | localparam SOMEP = {BITS{1'b0}}; | ^