diff --git a/bin/verilator b/bin/verilator
index 7d4c84bd4..dff24c375 100755
--- a/bin/verilator
+++ b/bin/verilator
@@ -362,7 +362,7 @@ detailed descriptions of these arguments.
+incdir+
Directory to search for includes
--inline-mult Tune module inlining
--instr-count-dpi Assumed dynamic instruction count of DPI imports
- -j Parallelism for --build (alias to --build-jobs)
+ -j Parallelism for --build-jobs/--verilate-jobs
--l2-name Verilog scope name of the top module
--language Default language standard to parse
-LDFLAGS Linker pre-object arguments for makefile
@@ -445,6 +445,7 @@ detailed descriptions of these arguments.
--unused-regexp Tune UNUSED lint signals
-V Verbose version and config
-v Verilog library
+ --verilate-jobs Job threads for Verilation stage
--no-verilate Skip Verilation and just compile previously Verilated code
+verilog1995ext+ Synonym for +1364-1995ext+
+verilog2001ext+ Synonym for +1364-2001ext+
diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst
index e610fa926..52017c50d 100644
--- a/docs/guide/exe_verilator.rst
+++ b/docs/guide/exe_verilator.rst
@@ -707,9 +707,10 @@ Summary:
.. option:: -j []
Specify the level of parallelism for :vlopt:`--build` if
- :vlopt:`--build-jobs` isn't provided. If zero, uses the number of threads
- in the current hardware. Otherwise, the must be a positive
- integer specifying the maximum number of parallel build jobs.
+ :vlopt:`--build-jobs` isn't provided, and the internal compilation steps
+ of Verilator if :vlopt:`--verilate-jobs` isn't provided. If zero, uses
+ the number of threads in the current hardware. Otherwise, must be a
+ positive integer specifying the maximum number of parallel build jobs.
.. option:: --l2-name
@@ -1429,6 +1430,15 @@ Summary:
execute only the build. This can be useful for rebuilding the Verilated code
produced by a previous invocation of Verilator.
+.. option:: --verilate-jobs []
+
+ Specify the level of parallelism for the internal compilation steps of
+ Verilator. If zero, uses the number of threads in the current hardware.
+ Otherwise, must be a positive integer specifying the maximum number of
+ parallel build jobs.
+
+ See also :vlopt:`-j`.
+
.. option:: +verilog1995ext+
Synonym for :vlopt:`+1364-1995ext+\`.
diff --git a/src/V3Options.cpp b/src/V3Options.cpp
index 2785a939b..8ea9d7aab 100644
--- a/src/V3Options.cpp
+++ b/src/V3Options.cpp
@@ -1505,6 +1505,17 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
DECL_OPTION("-v", CbVal, [this, &optdir](const char* valp) {
V3Options::addLibraryFile(parseFileArg(optdir, valp));
});
+ DECL_OPTION("-verilate-jobs", CbVal, [this, fl](const char* valp) {
+ int val = std::atoi(valp);
+ if (val < 0) {
+ fl->v3error("--verilate-jobs requires a non-negative integer, but '"
+ << valp << "' was passed");
+ val = 1;
+ } else if (val == 0) {
+ val = std::thread::hardware_concurrency();
+ }
+ m_verilateJobs = val;
+ });
DECL_OPTION("-verilate", OnOff, &m_verilate);
DECL_OPTION("-version", CbCall, [this]() {
showVersion(false);
@@ -1628,6 +1639,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
++i;
}
if (m_buildJobs == -1) m_buildJobs = val;
+ if (m_verilateJobs == -1) m_verilateJobs = val;
} else if (argv[i][0] == '-' || argv[i][0] == '+') {
const char* argvNoDashp = (argv[i][1] == '-') ? (argv[i] + 2) : (argv[i] + 1);
if (const int consumed = parser.parse(i, argc, argv)) {
@@ -1660,6 +1672,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
}
}
if (m_buildJobs == -1) m_buildJobs = 1;
+ if (m_verilateJobs == -1) m_verilateJobs = 1;
}
//======================================================================
diff --git a/src/V3Options.h b/src/V3Options.h
index 27e4f5036..b6c169561 100644
--- a/src/V3Options.h
+++ b/src/V3Options.h
@@ -317,6 +317,7 @@ private:
int m_traceThreads = 0; // main switch: --trace-threads
int m_unrollCount = 64; // main switch: --unroll-count
int m_unrollStmts = 30000; // main switch: --unroll-stmts
+ int m_verilateJobs = -1; // main switch: --verilate-jobs
int m_compLimitBlocks = 0; // compiler selection; number of nested blocks
int m_compLimitMembers = 64; // compiler selection; number of members in struct before make anon array
@@ -544,6 +545,7 @@ public:
}
int unrollCount() const { return m_unrollCount; }
int unrollStmts() const { return m_unrollStmts; }
+ int verilateJobs() const { return m_verilateJobs; }
int compLimitBlocks() const { return m_compLimitBlocks; }
int compLimitMembers() const { return m_compLimitMembers; }
diff --git a/src/V3StatsReport.cpp b/src/V3StatsReport.cpp
index 72123b2df..d72f13c1c 100644
--- a/src/V3StatsReport.cpp
+++ b/src/V3StatsReport.cpp
@@ -47,6 +47,7 @@ class StatsReport final {
os << " " << V3Options::version() << '\n';
os << " Arguments: " << v3Global.opt.allArgsString() << '\n';
os << " Build jobs: " << v3Global.opt.buildJobs() << '\n';
+ os << " Verilate jobs: " << v3Global.opt.verilateJobs() << '\n';
os << '\n';
}
diff --git a/test_regress/t/t_flag_verilate_threads_bad.out b/test_regress/t/t_flag_verilate_threads_bad.out
new file mode 100644
index 000000000..f26bfdd19
--- /dev/null
+++ b/test_regress/t/t_flag_verilate_threads_bad.out
@@ -0,0 +1,2 @@
+%Error: --verilate-jobs requires a non-negative integer, but '-1' was passed
+%Error: Exiting due to
diff --git a/test_regress/t/t_flag_verilate_threads_bad.pl b/test_regress/t/t_flag_verilate_threads_bad.pl
new file mode 100755
index 000000000..8743294da
--- /dev/null
+++ b/test_regress/t/t_flag_verilate_threads_bad.pl
@@ -0,0 +1,22 @@
+#!/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(vlt => 1);
+
+top_filename("t/t_flag_werror.v");
+
+lint(
+ fails => 1,
+ verilator_flags => [qw(--verilate-jobs -1)],
+ expect_filename => $Self->{golden_filename},
+ );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_vthread.pl b/test_regress/t/t_vthread.pl
new file mode 100755
index 000000000..5a360513a
--- /dev/null
+++ b/test_regress/t/t_vthread.pl
@@ -0,0 +1,58 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2023 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
+use IO::File;
+
+scenarios(vlt => 1);
+
+sub gen {
+ my $filename = shift;
+ my $n = shift;
+
+ my $fh = IO::File->new(">$filename");
+ $fh->print("// Generated by t_vthread.pl\n");
+ $fh->print("module genmod #(int val = 0)(clk, o);\n");
+ $fh->print(" input clk;\n");
+ $fh->print(" output int o;\n");
+ $fh->print(" always @ (posedge clk) begin\n");
+ $fh->print(" o <= val;\n");
+ $fh->print(" end\n");
+ $fh->print("endmodule\n");
+ $fh->print("module t (clk, o);\n");
+ $fh->print(" input clk;\n");
+ $fh->print(" output int o;\n");
+ for (my $i = 0; $i < ($n + 1); ++$i) {
+ $fh->print(" int r$i;\n");
+ $fh->print(" genmod #(.val($i)) rm$i (.clk(clk), .o(r$i));\n");
+ }
+ $fh->print(" always @ (posedge clk) begin\n");
+ $fh->print(" o <= r$n;\n");
+ $fh->print(' $write("*-* All Finished *-*\n");', "\n");
+ $fh->print(' $finish;', "\n");
+ $fh->print(" end\n");
+ $fh->print("endmodule\n");
+}
+
+top_filename("$Self->{obj_dir}/t_vthread.v");
+
+gen($Self->{top_filename}, 6000);
+
+compile(
+ # use --trace to generate trace files that can be parallelized
+ verilator_flags2=>["--stats --trace --verilate-jobs 2"],
+ );
+
+execute(
+ check_finished => 1,
+ );
+
+file_grep($Self->{stats}, qr/Verilate jobs: 2/);
+
+ok(1);
+1;