diff --git a/Changes b/Changes index b01f73847..c5888960a 100644 --- a/Changes +++ b/Changes @@ -34,6 +34,7 @@ Verilator 4.202 2021-04-24 * Add VerilatedCovContext::forcePerInstance (#2793). [Kevin Laeufer] * Add FST SystemC tracing (#2806). [Alex Torregrosa] * Add PINNOTFOUND warning in place of error (#2868). [Udi Finkelstein] +* Add --reloop-limit argument (#2943). [Geza Lore] * Support overlaps in priority case statements (#2864). [Rupert Swarbrick] * Support for null ports (#2875). [Udi Finkelstein] * Optimize large lookup tables to static data (#2925). [Geza Lore] diff --git a/bin/verilator b/bin/verilator index 9e1ce7094..706de8e28 100755 --- a/bin/verilator +++ b/bin/verilator @@ -378,6 +378,7 @@ detailed descriptions of these arguments. --quiet-exit Don't print the command on failure --relative-includes Resolve includes relative to current file --no-relative-cfuncs Disallow 'this->' in generated functions + --reloop-limit Minimum iterations for forming loops --report-unoptflat Extra diagnostics for UNOPTFLAT --rr Run Verilator and record with rr --savable Enable model save-restore diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index f7cf6dbd4..eedfd9683 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -915,6 +915,15 @@ Summary: the path of the referencing file, instead of relative to the current directory. +.. option:: --reloop-limit + + Rarely needed. Verilator attempts to turn some common sequences of + statements into loops in the output. This argument specifies the minimum + number of iterations the resulting loop needs to have in order to perform + this transformation. Default limit is 40. A smaller number may slightly + improve C++ compilation time on designs where these sequences are common, + however effect on model performance requires benchmarking. + .. option:: --report-unoptflat Extra diagnostics for UNOPTFLAT warnings. This includes for each loop, diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 7533f01a8..f816b7d41 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1242,6 +1242,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char fl->v3warn(DEPRECATED, "Deprecated --no-relative-cfuncs, unnecessary with C++11."); }); DECL_OPTION("-relative-includes", OnOff, &m_relativeIncludes); + DECL_OPTION("-reloop-limit", CbVal, [this, fl](const char* valp) { + m_reloopLimit = std::atoi(valp); + if (m_reloopLimit < 2) { fl->v3error("--reloop-limit must be >= 2: " << valp); } + }); DECL_OPTION("-report-unoptflat", OnOff, &m_reportUnoptflat); DECL_OPTION("-rr", CbCall, []() {}); // Processed only in bin/verilator shell diff --git a/src/V3Options.h b/src/V3Options.h index 7cb64f2ea..4d3bd8612 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -295,6 +295,7 @@ private: int m_outputSplitCFuncs = -1; // main switch: --output-split-cfuncs int m_outputSplitCTrace = -1; // main switch: --output-split-ctrace int m_pinsBv = 65; // main switch: --pins-bv + int m_reloopLimit = 40; // main switch: --reloop-limit VOptionBool m_skipIdentical; // main switch: --skip-identical int m_threads = 0; // main switch: --threads (0 == --no-threads) int m_threadsMaxMTasks = 0; // main switch: --threads-max-mtasks @@ -491,6 +492,7 @@ public: int outputSplitCFuncs() const { return m_outputSplitCFuncs; } int outputSplitCTrace() const { return m_outputSplitCTrace; } int pinsBv() const { return m_pinsBv; } + int reloopLimit() const { return m_reloopLimit; } VOptionBool skipIdentical() const { return m_skipIdentical; } int threads() const { return m_threads; } int threadsMaxMTasks() const { return m_threadsMaxMTasks; } diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp index facf7497e..96e6a4dc8 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -39,8 +39,6 @@ #include -constexpr unsigned RELOOP_MIN_ITERS = 40; // Need at least this many loops to do this optimization - //###################################################################### class ReloopVisitor final : public AstNVisitor { @@ -85,7 +83,7 @@ private: uint32_t items = m_mgIndexHi - m_mgIndexLo + 1; UINFO(9, "End merge iter=" << items << " " << m_mgIndexHi << ":" << m_mgIndexLo << " " << m_mgOffset << " " << m_mgAssignps[0] << endl); - if (items >= RELOOP_MIN_ITERS) { + if (items >= static_cast(v3Global.opt.reloopLimit())) { UINFO(6, "Reloop merging items=" << items << " " << m_mgIndexHi << ":" << m_mgIndexLo << " " << m_mgOffset << " " << m_mgAssignps[0] << endl); diff --git a/test_regress/t/t_reloop_offset_lim_63.pl b/test_regress/t/t_reloop_offset_lim_63.pl new file mode 100755 index 000000000..06d25c7b3 --- /dev/null +++ b/test_regress/t/t_reloop_offset_lim_63.pl @@ -0,0 +1,37 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 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); + +top_filename("t/t_reloop_offset.v"); +golden_filename("t/t_reloop_offset.out"); + +compile( + verilator_flags2 => ["-unroll-count 1024", + $Self->wno_unopthreads_for_few_cores(), + "--reloop-limit 63", + "--stats"], + ); + +execute( + check_finished => 1, + expect_filename => $Self->{golden_filename}, + ); + +if ($Self->{vlt}) { + # Note, with vltmt this might be split differently, so only checking vlt + file_grep($Self->{stats}, qr/Optimizations, Reloop iterations\s+(\d+)/i, + 63); + file_grep($Self->{stats}, qr/Optimizations, Reloops\s+(\d+)/i, + 1); +} + +ok(1); +1;