diff --git a/bin/verilator b/bin/verilator index 74c5b49c6..852ad516c 100755 --- a/bin/verilator +++ b/bin/verilator @@ -284,6 +284,7 @@ detailed descriptions of these arguments. --bbox-unsup Blackbox unsupported language features --bin Override Verilator binary --build Build model executable/library after Verilation + --build-jobs Parallelism for --build --cc Create C++ output --cdc Clock domain crossing analysis -CFLAGS C++ compiler arguments for makefile @@ -334,7 +335,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 + -j Parallelism for --build (alias to --build-jobs) --l2-name Verilog scope name of the top module --language Default language standard to parse -LDFLAGS Linker pre-object arguments for makefile diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 8d2ccda86..cf7690a14 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -129,6 +129,15 @@ Summary: is also used). Verilator manages the build itself, and for this --build requires GNU Make to be available on the platform. +.. option:: --build-jobs [] + + Specify the level of parallelism for :vlopt:`--build`. 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. + + See also :vlopt:`-j`. + .. option:: --cc Specifies C++ without SystemC output mode; see also :vlopt:`--sc` @@ -615,11 +624,10 @@ Summary: .. option:: -j [] - Specify the level of parallelism for :vlopt:`--build`. The must - be a positive integer specifying the maximum number of parallel build - jobs, or can be omitted. When is omitted, the build will not try - to limit the number of parallel build jobs but attempt to execute all - independent build steps in parallel. + 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. .. option:: --l2-name diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 0580fdac4..6836b5167 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include "config_rev.h" @@ -1006,6 +1007,17 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char }); DECL_OPTION("-bin", Set, &m_bin); DECL_OPTION("-build", Set, &m_build); + DECL_OPTION("-build-jobs", CbVal, [this, fl](const char* valp) { + int val = std::atoi(valp); + if (val < 0) { + fl->v3fatal("--build-jobs requires a non-negative integer, but '" << valp + << "' was passed"); + val = 1; + } else if (val == 0) { + val = std::thread::hardware_concurrency(); + } + m_buildJobs = val; + }); DECL_OPTION("-CFLAGS", CbVal, callStrSetter(&V3Options::addCFlags)); DECL_OPTION("-cc", CbCall, [this]() { ccSet(); }); @@ -1514,14 +1526,19 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char if (!std::strcmp(argv[i], "-j") || !std::strcmp(argv[i], "--j")) { // Allow gnu -- switches ++i; - m_buildJobs = 0; // Unlimited parallelism + int val = 0; if (i < argc && isdigit(argv[i][0])) { - m_buildJobs = std::atoi(argv[i]); - if (m_buildJobs <= 0) { - fl->v3error("-j accepts positive integer, but '" << argv[i] << "' is passed"); + val = atoi(argv[i]); + if (val < 0) { + fl->v3error("-j requires a non-negative integer argument, but '" + << argv[i] << "' was passed"); + val = 1; // Fall-back value, though we will exit on error. + } else if (val == 0) { + val = std::thread::hardware_concurrency(); } ++i; } + if (m_buildJobs == -1) m_buildJobs = 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)) { @@ -1553,6 +1570,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char ++i; } } + if (m_buildJobs == -1) m_buildJobs = 1; } //====================================================================== diff --git a/src/V3Options.h b/src/V3Options.h index 190d4c7ab..028171c5a 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -283,7 +283,7 @@ private: bool m_xInitialEdge = false; // main switch: --x-initial-edge bool m_xmlOnly = false; // main switch: --xml-only - int m_buildJobs = 1; // main switch: -j + int m_buildJobs = -1; // main switch: --build-jobs, -j int m_convergeLimit = 100; // main switch: --converge-limit int m_coverageMaxWidth = 256; // main switch: --coverage-max-width int m_dumpTree = 0; // main switch: --dump-tree diff --git a/src/Verilator.cpp b/src/Verilator.cpp index b5d2df2cb..eb07fb664 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -663,11 +663,7 @@ static string buildMakeCmd(const string& makefile, const string& target) { cmd << v3Global.opt.getenvMAKE(); cmd << " -C " << v3Global.opt.makeDir(); cmd << " -f " << makefile; - if (jobs == 0) { - cmd << " -j"; - } else if (jobs > 1) { - cmd << " -j " << jobs; - } + if (jobs > 0) cmd << " -j " << jobs; for (const string& flag : makeFlags) cmd << ' ' << flag; if (!target.empty()) cmd << ' ' << target; diff --git a/test_regress/t/t_flag_build-jobs_bad.out b/test_regress/t/t_flag_build-jobs_bad.out new file mode 100644 index 000000000..341b1b979 --- /dev/null +++ b/test_regress/t/t_flag_build-jobs_bad.out @@ -0,0 +1 @@ +%Error: --build-jobs requires a non-negative integer, but '-1' was passed diff --git a/test_regress/t/t_flag_j_bad.pl b/test_regress/t/t_flag_build-jobs_bad.pl similarity index 91% rename from test_regress/t/t_flag_j_bad.pl rename to test_regress/t/t_flag_build-jobs_bad.pl index ee3d0fdc8..8432e74c6 100755 --- a/test_regress/t/t_flag_j_bad.pl +++ b/test_regress/t/t_flag_build-jobs_bad.pl @@ -14,7 +14,7 @@ top_filename("t/t_flag_werror.v"); lint( fails => 1, - verilator_flags => [qw(-j 0 --build)], + verilator_flags => [qw(--build-jobs -1 --build)], expect_filename => $Self->{golden_filename}, ); diff --git a/test_regress/t/t_flag_build_jobs_and_j.pl b/test_regress/t/t_flag_build_jobs_and_j.pl new file mode 100755 index 000000000..03ce21108 --- /dev/null +++ b/test_regress/t/t_flag_build_jobs_and_j.pl @@ -0,0 +1,29 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd.. 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_flag_make_cmake.v"); + +compile( + verilator_make_cmake => 0, + verilator_make_gmake => 0, + verilator_flags2 => ['--exe --cc --build -j 10 --build-jobs 2', + '../' . $Self->{main_filename}, + '-MAKEFLAGS -p --trace'], + ); + +execute( + check_finished => 1, + ); + +file_grep($Self->{obj_dir} . '/vlt_compile.log', qr/MAKEFLAGS = pw -j2/); + +ok(1); +1; diff --git a/test_regress/t/t_flag_j_bad.out b/test_regress/t/t_flag_j_bad.out deleted file mode 100644 index 2fe652c5d..000000000 --- a/test_regress/t/t_flag_j_bad.out +++ /dev/null @@ -1,2 +0,0 @@ -%Error: -j accepts positive integer, but '0' is passed -%Error: Exiting due to