Fix hierarchical verilation for projects with dot-f dependency lists (#5199) (#5669)

This commit is contained in:
Bartłomiej Chmiel 2024-12-12 17:25:19 +01:00 committed by GitHub
parent 03e8ef0b0f
commit 32f9cf072b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 187 additions and 8 deletions

View File

@ -115,6 +115,8 @@ static void V3HierWriteCommonInputs(const V3HierBlock* hblockp, std::ostream* of
if (hblockp) topModuleFile = hblockp->vFileIfNecessary(); if (hblockp) topModuleFile = hblockp->vFileIfNecessary();
if (!forCMake) { if (!forCMake) {
if (!topModuleFile.empty()) *of << topModuleFile << "\n"; 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(); const V3StringSet& libraryFiles = v3Global.opt.libraryFiles();
for (const string& i : libraryFiles) { for (const string& i : libraryFiles) {
@ -253,7 +255,7 @@ void V3HierBlock::writeCommandArgsFile(bool forCMake) const {
for (const string& opt : commandOpts) *of << opt << "\n"; for (const string& opt : commandOpts) *of << opt << "\n";
*of << hierBlockArgs().front() << "\n"; *of << hierBlockArgs().front() << "\n";
for (const auto& hierblockp : m_children) *of << hierblockp->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 { string V3HierBlock::commandArgsFilename(bool forCMake) const {
@ -477,7 +479,7 @@ void V3HierBlockPlan::writeCommandArgsFiles(bool forCMake) const {
} }
*of << "--threads " << cvtToStr(v3Global.opt.threads()) << "\n"; *of << "--threads " << cvtToStr(v3Global.opt.threads()) << "\n";
*of << (v3Global.opt.systemC() ? "--sc" : "--cc") << "\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) { string V3HierBlockPlan::topCommandArgsFilename(bool forCMake) {

View File

@ -412,7 +412,7 @@ string V3Options::allArgsString() const VL_MT_SAFE {
} }
// Delete some options for Verilation of the hierarchical blocks. // 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<string> vFiles; std::set<string> vFiles;
for (const auto& vFile : m_vFiles) vFiles.insert(vFile); for (const auto& vFile : m_vFiles) vFiles.insert(vFile);
string out; string out;
@ -443,7 +443,7 @@ string V3Options::allArgsStringForHierBlock(bool forTop, bool forCMake) const {
continue; continue;
} }
} else { // Not an option } 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++ || m_cppFiles.find(arg) != m_cppFiles.end()) { // Remove C++
continue; 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 // 3: Delete the option and its argument if it is a number
int V3Options::stripOptionsForChildRun(const string& opt, bool forTop) { int V3Options::stripOptionsForChildRun(const string& opt, bool forTop) {
if (opt == "j") return 3; if (opt == "j") return 3;
if (opt == "Mdir" || opt == "clk" || opt == "lib-create" || opt == "f" || opt == "v" if (opt == "Mdir" || opt == "clk" || opt == "lib-create" || opt == "f" || opt == "F"
|| opt == "l2-name" || opt == "mod-prefix" || opt == "prefix" || opt == "protect-lib" || opt == "v" || opt == "l2-name" || opt == "mod-prefix" || opt == "prefix"
|| opt == "protect-key" || opt == "threads" || opt == "top-module") { || opt == "protect-lib" || opt == "protect-key" || opt == "threads"
|| opt == "top-module") {
return 2; return 2;
} }
if (opt == "build" || (!forTop && (opt == "cc" || opt == "exe" || opt == "sc")) if (opt == "build" || (!forTop && (opt == "cc" || opt == "exe" || opt == "sc"))

View File

@ -727,7 +727,7 @@ public:
string allArgsString() const VL_MT_SAFE; ///< Return all passed arguments as simple string 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 // Return options for child hierarchical blocks when forTop==false, otherwise returns args for
// the top module. // 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 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 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; void parseOptsFile(FileLine* fl, const string& filename, bool rel) VL_MT_DISABLED;

View File

@ -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()

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()