diff --git a/bin/verilator b/bin/verilator index 0285e2df7..ee917f7a9 100755 --- a/bin/verilator +++ b/bin/verilator @@ -428,6 +428,7 @@ detailed descriptions of these arguments. --pipe-filter Filter all input through a script --pp-comments Show preprocessor comments with -E --prefix Name of top-level class + --preproc-resolve Include all found modules in the output with -E --preproc-token-limit Maximum tokens on a line allowed by preprocessor --private Debugging; see docs --prof-c Compile C++ code with profiling diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 155e93ce1..9259686bb 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -490,8 +490,8 @@ Summary: out. Beware of enabling debugging messages, as they will also go to standard out. See :vlopt:`--no-std`, which is implied by this. - See also :vlopt:`--dump-defines`, :vlopt:`-P`, and - :vlopt:`--pp-comments` options. + See also :vlopt:`--dump-defines`, :vlopt:`-P`, :vlopt:`--pp-comments` + and :vlopt:`--preproc-resolve` options. .. option:: --emit-accessors @@ -1152,6 +1152,14 @@ Summary: prepended to the name of the :vlopt:`--top` option, or V prepended to the first Verilog filename passed on the command line. +.. option:: --preproc-resolve + + With :vlopt:`-E`, include preprocessed output of submodules defined + in included files. Gives you a way of converting a multifile design + into a single file using include directory option. + + See :vlopt:`-E`. + .. option:: --preproc-token-limit Rarely needed. Configure the limit of the number of tokens Verilator diff --git a/src/V3Global.cpp b/src/V3Global.cpp index 08bab7a2d..357f910b0 100644 --- a/src/V3Global.cpp +++ b/src/V3Global.cpp @@ -104,7 +104,7 @@ void V3Global::readFiles() { // v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("parse.tree")); V3Error::abortIfErrors(); - if (!v3Global.opt.preprocOnly()) { + if (!v3Global.opt.preprocOnly() || v3Global.opt.preprocResolve()) { // Resolve all modules cells refer to V3LinkCells::link(v3Global.rootp(), &filter, &parseSyms); } diff --git a/src/V3Options.cpp b/src/V3Options.cpp index dd0176c84..0ef5207f7 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1504,6 +1504,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, validateIdentifier(fl, valp, "--prefix"); m_prefix = valp; }); + DECL_OPTION("-preproc-resolve", OnOff, &m_preprocResolve); DECL_OPTION("-preproc-token-limit", CbVal, [this, fl](const char* valp) { m_preprocTokenLimit = std::atoi(valp); if (m_preprocTokenLimit <= 0) fl->v3error("--preproc-token-limit must be > 0: " << valp); diff --git a/src/V3Options.h b/src/V3Options.h index 2e3c37da8..cae2e8cfa 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -219,6 +219,7 @@ private: V3StringSet m_fDfgPeepholeDisabled; // argument: -f[no-]dfg-peephole- bool m_preprocOnly = false; // main switch: -E + bool m_preprocResolve = false; // main switch: --preproc-resolve bool m_makePhony = false; // main switch: -MP bool m_preprocNoLine = false; // main switch: -P bool m_assert = false; // main switch: --assert @@ -470,6 +471,7 @@ public: bool preprocOnly() const { return m_preprocOnly; } bool makePhony() const { return m_makePhony; } bool preprocNoLine() const { return m_preprocNoLine; } + bool preprocResolve() const { return m_preprocResolve; } int preprocTokenLimit() const { return m_preprocTokenLimit; } bool underlineZero() const { return m_underlineZero; } string flags() const { return m_flags; } diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index c2cc2cf6f..4225a9c21 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -356,7 +356,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i dumpInputsFile(); // Parse it - if (!v3Global.opt.preprocOnly()) { + if (!v3Global.opt.preprocOnly() || v3Global.opt.preprocResolve()) { lexFile(modfilename); } else { m_ppBuffers.clear(); diff --git a/test_regress/t/t_preproc_resolve.out b/test_regress/t/t_preproc_resolve.out new file mode 100644 index 000000000..7f76f5919 --- /dev/null +++ b/test_regress/t/t_preproc_resolve.out @@ -0,0 +1,26 @@ +`timescale 1ns/1ps +module top( + input logic clk, + input logic rst, + output logic top_out +); + submod u_submod ( + .clk (clk), + .rst (rst), + .out_signal(top_out) + ); +endmodule +`timescale 1ns/1ps +module submod( + input logic clk, + input logic rst, + output logic out_signal +); + always_ff @(posedge clk or posedge rst) begin + if (rst) begin + out_signal <= 1'b0; + end else begin + out_signal <= ~out_signal; + end + end +endmodule diff --git a/test_regress/t/t_preproc_resolve.py b/test_regress/t/t_preproc_resolve.py new file mode 100755 index 000000000..d6f95780f --- /dev/null +++ b/test_regress/t/t_preproc_resolve.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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') + +stdout_filename = os.path.join(test.obj_dir, test.name + ".out") + +test.compile( + # Override default flags + v_flags=[''], + verilator_flags=["-E -P --preproc-resolve -y t/t_preproc_resolve"], + verilator_flags2=[''], + verilator_flags3=[''], + verilator_make_gmake=False, + make_top_shell=False, + make_main=False, + stdout_filename=stdout_filename) + +test.files_identical(stdout_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_preproc_resolve.v b/test_regress/t/t_preproc_resolve.v new file mode 100644 index 000000000..7d49cd8d0 --- /dev/null +++ b/test_regress/t/t_preproc_resolve.v @@ -0,0 +1,18 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +`timescale 1ns/1ps +module top(/*AUTOARG*/ + input logic clk, + input logic rst, + output logic top_out +); + submod u_submod (/*AUTOINST*/ + .clk (clk), + .rst (rst), + .out_signal(top_out) + ); +endmodule diff --git a/test_regress/t/t_preproc_resolve/submod.sv b/test_regress/t/t_preproc_resolve/submod.sv new file mode 100644 index 000000000..701cd7269 --- /dev/null +++ b/test_regress/t/t_preproc_resolve/submod.sv @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +`timescale 1ns/1ps +module submod(/*AUTOARG*/ + input logic clk, + input logic rst, + output logic out_signal +); + always_ff @(posedge clk or posedge rst) begin + if (rst) begin + out_signal <= 1'b0; + end else begin + out_signal <= ~out_signal; + end + end +endmodule