diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp index 853bc41eb..b9e985837 100644 --- a/src/V3HierBlock.cpp +++ b/src/V3HierBlock.cpp @@ -115,6 +115,8 @@ static void V3HierWriteCommonInputs(const V3HierBlock* hblockp, std::ostream* of if (hblockp) topModuleFile = hblockp->vFileIfNecessary(); if (!forCMake) { if (!topModuleFile.empty()) *of << topModuleFile << "\n"; + const V3StringList& vFiles = v3Global.opt.vFiles(); + for (const string& i : vFiles) *of << i << "\n"; } const V3StringSet& libraryFiles = v3Global.opt.libraryFiles(); for (const string& i : libraryFiles) { @@ -253,7 +255,7 @@ void V3HierBlock::writeCommandArgsFile(bool forCMake) const { for (const string& opt : commandOpts) *of << opt << "\n"; *of << hierBlockArgs().front() << "\n"; for (const auto& hierblockp : m_children) *of << hierblockp->hierBlockArgs().front() << "\n"; - *of << v3Global.opt.allArgsStringForHierBlock(false, forCMake) << "\n"; + *of << v3Global.opt.allArgsStringForHierBlock(false) << "\n"; } string V3HierBlock::commandArgsFilename(bool forCMake) const { @@ -477,7 +479,7 @@ void V3HierBlockPlan::writeCommandArgsFiles(bool forCMake) const { } *of << "--threads " << cvtToStr(v3Global.opt.threads()) << "\n"; *of << (v3Global.opt.systemC() ? "--sc" : "--cc") << "\n"; - *of << v3Global.opt.allArgsStringForHierBlock(true, forCMake) << "\n"; + *of << v3Global.opt.allArgsStringForHierBlock(true) << "\n"; } string V3HierBlockPlan::topCommandArgsFilename(bool forCMake) { diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 422c09a30..8131f3c6e 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -412,7 +412,7 @@ string V3Options::allArgsString() const VL_MT_SAFE { } // Delete some options for Verilation of the hierarchical blocks. -string V3Options::allArgsStringForHierBlock(bool forTop, bool forCMake) const { +string V3Options::allArgsStringForHierBlock(bool forTop) const { std::set vFiles; for (const auto& vFile : m_vFiles) vFiles.insert(vFile); string out; @@ -443,7 +443,7 @@ string V3Options::allArgsStringForHierBlock(bool forTop, bool forCMake) const { continue; } } else { // Not an option - if ((forCMake && vFiles.find(arg) != vFiles.end()) // Remove HDL + if (vFiles.find(arg) != vFiles.end() // Remove HDL || m_cppFiles.find(arg) != m_cppFiles.end()) { // Remove C++ continue; } @@ -549,9 +549,10 @@ string V3Options::filePathCheckOneDir(const string& modname, const string& dirna // 3: Delete the option and its argument if it is a number int V3Options::stripOptionsForChildRun(const string& opt, bool forTop) { if (opt == "j") return 3; - if (opt == "Mdir" || opt == "clk" || opt == "lib-create" || opt == "f" || opt == "v" - || opt == "l2-name" || opt == "mod-prefix" || opt == "prefix" || opt == "protect-lib" - || opt == "protect-key" || opt == "threads" || opt == "top-module") { + if (opt == "Mdir" || opt == "clk" || opt == "lib-create" || opt == "f" || opt == "F" + || opt == "v" || opt == "l2-name" || opt == "mod-prefix" || opt == "prefix" + || opt == "protect-lib" || opt == "protect-key" || opt == "threads" + || opt == "top-module") { return 2; } if (opt == "build" || (!forTop && (opt == "cc" || opt == "exe" || opt == "sc")) diff --git a/src/V3Options.h b/src/V3Options.h index a1e9b1b0c..e1486aeda 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -727,7 +727,7 @@ public: string allArgsString() const VL_MT_SAFE; ///< Return all passed arguments as simple string // Return options for child hierarchical blocks when forTop==false, otherwise returns args for // the top module. - string allArgsStringForHierBlock(bool forTop, bool forCMake) const; + string allArgsStringForHierBlock(bool forTop) const; void parseOpts(FileLine* fl, int argc, char** argv) VL_MT_DISABLED; void parseOptsList(FileLine* fl, const string& optdir, int argc, char** argv) VL_MT_DISABLED; void parseOptsFile(FileLine* fl, const string& filename, bool rel) VL_MT_DISABLED; diff --git a/test_regress/t/t_hier_block_import.py b/test_regress/t/t_hier_block_import.py new file mode 100755 index 000000000..d9142462d --- /dev/null +++ b/test_regress/t/t_hier_block_import.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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 + +import vltest_bootstrap + +test.scenarios('vlt_all') + +# stats will be deleted but generation will be skipped if libs of hierarchical blocks exist. +test.clean_objs() + +test.setenv('TEST_ROOT', test.t_dir + "/t_hier_block_import") + +# CI environment offers 2 VCPUs, 2 thread setting causes the following warning. +# %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. +# So use 6 threads here though it's not optimal in performance, but ok. + +test.compile(verilator_flags2=[ + '$TEST_ROOT/t_hier_block_import_def.vh', '-f $TEST_ROOT/t_hier_block_import_args.f', + '-I$TEST_ROOT' +], + threads=(6 if test.vltmt else 1)) + +test.execute() + +test.file_grep(test.obj_dir + "/VsubA/subA.sv", r'^module\s+(\S+)\s+', "subA") +test.file_grep(test.stats, r'HierBlock,\s+Hierarchical blocks\s+(\d+)', 2) + +test.passes() diff --git a/test_regress/t/t_hier_block_import.v b/test_regress/t/t_hier_block_import.v new file mode 100644 index 000000000..c2ad81e44 --- /dev/null +++ b/test_regress/t/t_hier_block_import.v @@ -0,0 +1,30 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Antmicro. 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 t(/*AUTOARG*/ + // inputs + clk +); + input clk; + bit [31:0] outA; + bit [31:0] outB; + + subA subA(.out(outA)); + subB subB(.out(outB)); + + always @(posedge clk) begin + if (outA == `VALUE_A && outB == `VALUE_B) begin + $write("*-* All Finished *-*\n"); + $finish; + end + else begin + $write("Mismatch\n"); + $stop; + end + end +endmodule diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import.vh b/test_regress/t/t_hier_block_import/t_hier_block_import.vh new file mode 100644 index 000000000..d0cc5e74d --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import.vh @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 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 + +// No include guards to validate if included once. + +parameter param_t pt = '{ + PARAM_VALUE: `VALUE_A +} diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import_args.f b/test_regress/t/t_hier_block_import/t_hier_block_import_args.f new file mode 100644 index 000000000..11c92e3ab --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import_args.f @@ -0,0 +1,11 @@ +# Copyright 2024 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 + +--stats +--hierarchical +$TEST_ROOT/t_hier_block_import_subA.v +-v $TEST_ROOT/t_hier_block_import_subB.v +$TEST_ROOT/t_hier_block_import_subsub.v diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import_def.vh b/test_regress/t/t_hier_block_import/t_hier_block_import_def.vh new file mode 100644 index 000000000..e2877ac06 --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import_def.vh @@ -0,0 +1,16 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 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 + +// No include guards to validate if included once. + +`define VALUE_A 32'h12345678 +`define VALUE_B 32'h87654321 + +typedef struct packed { + bit [31:0] PARAM_VALUE; +} param_t; diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import_subA.v b/test_regress/t/t_hier_block_import/t_hier_block_import_subA.v new file mode 100644 index 000000000..770b57f67 --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import_subA.v @@ -0,0 +1,11 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Antmicro. 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 subA (output bit [31:0] out); /*verilator hier_block*/ + subsub subsub(.out(out)); +endmodule diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import_subB.v b/test_regress/t/t_hier_block_import/t_hier_block_import_subB.v new file mode 100644 index 000000000..3fb930bd8 --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import_subB.v @@ -0,0 +1,12 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Antmicro. 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 + +// Note: no hier_block pragma here to validate partial hier_block design +module subB (output bit [31:0] out); + assign out = `VALUE_B; +endmodule diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import_subsub.v b/test_regress/t/t_hier_block_import/t_hier_block_import_subsub.v new file mode 100644 index 000000000..13d6d4014 --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import_subsub.v @@ -0,0 +1,15 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Antmicro. 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 subsub +#( + `include "t_hier_block_import.vh" +) +(output bit [31:0] out); /*verilator hier_block*/ + assign out = pt.PARAM_VALUE; +endmodule diff --git a/test_regress/t/t_hier_block_import_cmake.py b/test_regress/t/t_hier_block_import_cmake.py new file mode 100755 index 000000000..866eb3ff7 --- /dev/null +++ b/test_regress/t/t_hier_block_import_cmake.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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 + +import vltest_bootstrap + +test.scenarios('vlt_all') +# CMake build executes from a different directory than the Make one. +test.top_filename = os.path.abspath("t/t_hier_block_import.v") + +# stats will be deleted but generation will be skipped if libs of hierarchical blocks exist. +test.clean_objs() + +test.setenv('TEST_ROOT', test.t_dir + "/t_hier_block_import") + +test.compile(verilator_make_cmake=True, + verilator_make_gmake=False, + verilator_flags2=[ + '$TEST_ROOT/t_hier_block_import_def.vh', + '-f $TEST_ROOT/t_hier_block_import_args.f', '-I$TEST_ROOT' + ], + threads=(6 if test.vltmt else 1)) + +test.execute() + +test.file_grep(test.obj_dir + "/VsubA/subA.sv", r'^module\s+(\S+)\s+', "subA") +test.file_grep(test.stats, r'HierBlock,\s+Hierarchical blocks\s+(\d+)', 2) + +test.passes()