diff --git a/bin/verilator b/bin/verilator index 5bab12f33..65acaf2f8 100755 --- a/bin/verilator +++ b/bin/verilator @@ -372,6 +372,7 @@ detailed descriptions of these arguments. --make Generate scripts for specified build tool -MAKEFLAGS Arguments to pass to make during --build --main Generate C++ main() file + --main-top-name Specify top name passed to Verilated model in generated C++ main --max-num-width Maximum number width (default: 64K) --Mdir Name of output object directory --MMD Create .d dependency files diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index ba86f3b4d..d82c05948 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -25,6 +25,7 @@ David Horton David Metz David Stanford David Turner +Don Williamson Drew Ranck Drew Taussig Driss Hafdi diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 5bc6c0474..a4d0af876 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -808,6 +808,13 @@ Summary: See also :vlopt:`--binary`. +.. option:: --main-top-name + + Specify the name passed to the Verilated model being constructed, in the + generated C++ main() function. + + If the string ``"-"`` is used, no top level scope is added. + .. option:: --max-num-width Set the maximum number literal width (e.g., in 1024'd22 this diff --git a/src/V3EmitCMain.cpp b/src/V3EmitCMain.cpp index 10216025b..3ea952903 100644 --- a/src/V3EmitCMain.cpp +++ b/src/V3EmitCMain.cpp @@ -51,6 +51,14 @@ private: // Not defining main_time/vl_time_stamp, so v3Global.opt.addCFlags("-DVL_TIME_CONTEXT"); // On MSVC++ anyways + // Optional main top name argument, with empty string replacement + string topArg; + string topName = v3Global.opt.mainTopName(); + if (!topName.empty()) { + if (topName == "-") topName = ""; + topArg = ", \"" + topName + "\""; + } + // Heavily commented output, as users are likely to look at or copy this code ofp()->putsHeader(); puts("// DESCRIPTION: main() calling loop, created with Verilator --main\n"); @@ -71,7 +79,7 @@ private: puts("// Construct the Verilated model, from Vtop.h generated from Verilating\n"); puts("const std::unique_ptr<" + topClassName() + "> topp{new " + topClassName() - + "{contextp.get()}};\n"); + + "{contextp.get()" + topArg + "}};\n"); puts("\n"); puts("// Simulate until $finish\n"); diff --git a/src/V3Options.cpp b/src/V3Options.cpp index d6d3fec8e..219c8e30c 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1279,6 +1279,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char DECL_OPTION("-l2-name", Set, &m_l2Name); DECL_OPTION("-no-l2name", CbCall, [this]() { m_l2Name = ""; }).undocumented(); // Historical DECL_OPTION("-l2name", CbCall, [this]() { m_l2Name = "v"; }).undocumented(); // Historical + DECL_OPTION("-main-top-name", Set, &m_mainTopName); DECL_OPTION("-MAKEFLAGS", CbVal, callStrSetter(&V3Options::addMakeFlags)); DECL_OPTION("-MMD", OnOff, &m_makeDepend); diff --git a/src/V3Options.h b/src/V3Options.h index 7e6b639b3..fea00aaf8 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -330,6 +330,7 @@ private: string m_flags; // main switch: -f {name} string m_l2Name; // main switch: --l2name; "" for top-module's name string m_libCreate; // main switch: --lib-create {lib_name} + string m_mainTopName; // main switch: --main-top-name string m_makeDir; // main switch: -Mdir string m_modPrefix; // main switch: --mod-prefix string m_pipeFilter; // main switch: --pipe-filter @@ -567,6 +568,7 @@ public: } return libName; } + string mainTopName() const { return m_mainTopName; } string makeDir() const VL_MT_SAFE { return m_makeDir; } string modPrefix() const VL_MT_SAFE { return m_modPrefix; } string pipeFilter() const { return m_pipeFilter; } diff --git a/test_regress/t/t_flag_main_top_name.pl b/test_regress/t/t_flag_main_top_name.pl new file mode 100644 index 000000000..876acdd1c --- /dev/null +++ b/test_regress/t/t_flag_main_top_name.pl @@ -0,0 +1,28 @@ +#!/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 Don Williamson and 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_flag_main_top_name.v"); + +compile( + verilator_flags => ["-Mdir $Self->{obj_dir}", "--exe", "--build", "--main"], + verilator_flags2 => ["--top-module top", "--main-top-name ALTOP"], + verilator_make_cmake => 0, + verilator_make_gmake => 0, + make_main => 0, + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_flag_main_top_name.v b/test_regress/t/t_flag_main_top_name.v new file mode 100644 index 000000000..ced845c9a --- /dev/null +++ b/test_regress/t/t_flag_main_top_name.v @@ -0,0 +1,22 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2023 by Don Williamson and 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 + +module top; + string scope; + initial begin + scope = $sformatf("%m"); + $write("[%0t] In %s\n", $time, scope); + `ifdef MAIN_TOP_NAME_EMPTY + if (scope != "top") $stop; + `else + if (scope != "ALTOP.top") $stop; + `endif + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_flag_main_top_name_empty.pl b/test_regress/t/t_flag_main_top_name_empty.pl new file mode 100644 index 000000000..bd3cc906f --- /dev/null +++ b/test_regress/t/t_flag_main_top_name_empty.pl @@ -0,0 +1,28 @@ +#!/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 Don Williamson and 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_flag_main_top_name.v"); + +compile( + verilator_flags => ["-Mdir $Self->{obj_dir}", "--exe", "--build", "--main"], + verilator_flags2 => ["--top-module top", "--main-top-name -", "-DMAIN_TOP_NAME_EMPTY"], + verilator_make_cmake => 0, + verilator_make_gmake => 0, + make_main => 0, + ); + +execute( + check_finished => 1, + ); + +ok(1); +1;