diff --git a/Changes b/Changes index 8c68249c5..cefd3e574 100644 --- a/Changes +++ b/Changes @@ -20,6 +20,8 @@ The contributors that suggested a given feature are shown in []. Thanks! ** Fix DPI import/export to be standard compliant, #2236. [Geza Lore] +*** Add --flatten for use with --xml-only, #2270. [James Hanlon] + **** Support $ferror, and $fflush without arguments, #1638. **** Add error if use SystemC 2.2 and earlier (pre-2011) as is deprecated. diff --git a/bin/verilator b/bin/verilator index 2a2ea028b..3fa55b771 100755 --- a/bin/verilator +++ b/bin/verilator @@ -303,6 +303,7 @@ detailed descriptions in L for more information. -F Parse options from a file, relatively -f Parse options from a file -FI Force include of a file + --flatten Force inlining of all modules, tasks and functions -G= Overwrite toplevel parameter --gdb Run Verilator under GDB interactively --gdbbt Run Verilator under GDB for backtrace @@ -847,6 +848,12 @@ specified file might be used to contain define prototypes of custom VL_VPRINTF functions, and may need to include verilatedos.h as this file is included before any other standard includes. +=item --flatten + +Force flattening of the design's hierarchy, with all modules, tasks and +functions inlined. Typically used with C<--xml-only>. Note flattening +large designs may require significant CPU time, memory and storage. + =item -GI=I Overwrites the given parameter of the toplevel module. The value is limited diff --git a/docs/xml.adoc b/docs/xml.adoc index 3dabedc02..0189b44cf 100644 --- a/docs/xml.adoc +++ b/docs/xml.adoc @@ -21,7 +21,7 @@ parser. == Structure -The XML document is consists of 4 sections within the top level `verilator_xml` +The XML document consists of 4 sections within the top level `verilator_xml` element: ``...``:: diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index dce048684..49c795669 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -194,13 +194,15 @@ private: int refs = modp->user3(); // Should we automatically inline this module? + // If --flatten is specified, then force everything to be inlined that can be. // inlineMult = 2000 by default. // If a mod*#refs is < this # nodes, can inline it bool doit = ((allowed == CIL_USER) || ((allowed == CIL_MAYBE) - && (refs == 1 || statements < INLINE_MODS_SMALLER - || v3Global.opt.inlineMult() < 1 - || refs * statements < v3Global.opt.inlineMult()))); + && (v3Global.opt.flatten() + || (refs == 1 || statements < INLINE_MODS_SMALLER + || v3Global.opt.inlineMult() < 1 + || refs * statements < v3Global.opt.inlineMult())))); // Packages aren't really "under" anything so they confuse this algorithm if (VN_IS(modp, Package)) doit = false; UINFO(4, " Inline=" << doit << " Possible=" << allowed << " Refs=" << refs diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 641424df8..1f0b30f15 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -842,6 +842,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char else if ( onoff (sw, "-dump-defines", flag/*ref*/)) { m_dumpDefines = flag; } else if ( onoff (sw, "-dump-tree", flag/*ref*/)) { m_dumpTree = flag ? 3 : 0; } // Also see --dump-treei else if ( onoff (sw, "-exe", flag/*ref*/)) { m_exe = flag; } + else if ( onoff (sw, "-flatten", flag/*ref*/)) { m_flatten = flag; } else if ( onoff (sw, "-ignc", flag/*ref*/)) { m_ignc = flag; } else if ( onoff (sw, "-inhibit-sim", flag/*ref*/)) { m_inhibitSim = flag; } else if ( onoff (sw, "-lint-only", flag/*ref*/)) { m_lintOnly = flag; } @@ -1525,6 +1526,7 @@ V3Options::V3Options() { m_dpiHdrOnly = false; m_dumpDefines = false; m_exe = false; + m_flatten = false; m_ignc = false; m_inhibitSim = false; m_lintOnly = false; diff --git a/src/V3Options.h b/src/V3Options.h index 32745c8d6..d8d233112 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -230,6 +230,7 @@ private: bool m_dpiHdrOnly; // main switch: --dpi-hdr-only bool m_dumpDefines; // main switch: --dump-defines bool m_exe; // main switch: --exe + bool m_flatten; // main switch: --flatten bool m_ignc; // main switch: --ignc bool m_inhibitSim; // main switch: --inhibit-sim bool m_lintOnly; // main switch: --lint-only @@ -424,6 +425,7 @@ public: bool dpiHdrOnly() const { return m_dpiHdrOnly; } bool dumpDefines() const { return m_dumpDefines; } bool exe() const { return m_exe; } + bool flatten() const { return m_flatten; } bool gmake() const { return m_gmake; } bool threadsDpiPure() const { return m_threadsDpiPure; } bool threadsDpiUnpure() const { return m_threadsDpiUnpure; } diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 23471fe7e..31a499e28 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -160,7 +160,7 @@ static void process() { // V3Assert::assertAll(v3Global.rootp()); - if (!v3Global.opt.xmlOnly()) { + if (!(v3Global.opt.xmlOnly() && !v3Global.opt.flatten())) { // Add top level wrapper with instance pointing to old top // Move packages to under new top // Must do this after we know parameters and dtypes (as don't clone dtype decls) @@ -170,7 +170,7 @@ static void process() { // Propagate constants into expressions V3Const::constifyAllLint(v3Global.rootp()); - if (!v3Global.opt.xmlOnly()) { + if (!(v3Global.opt.xmlOnly() && !v3Global.opt.flatten())) { // Split packed variables into multiple pieces to resolve UNOPTFLAT. // should be after constifyAllLint() which flattens to 1D bit vector V3SplitVar::splitVariable(v3Global.rootp()); @@ -214,7 +214,7 @@ static void process() { //--FLATTENING--------------- - if (!v3Global.opt.xmlOnly()) { + if (!(v3Global.opt.xmlOnly() && !v3Global.opt.flatten())) { // We're going to flatten the hierarchy, so as many optimizations that // can be done as possible should be before this.... @@ -234,19 +234,25 @@ static void process() { //--SCOPE BASED OPTIMIZATIONS-------------- - if (!v3Global.opt.xmlOnly()) { + if (!(v3Global.opt.xmlOnly() && !v3Global.opt.flatten())) { // Cleanup V3Const::constifyAll(v3Global.rootp()); V3Dead::deadifyDTypesScoped(v3Global.rootp()); v3Global.checkTree(); + } + if (!v3Global.opt.xmlOnly()) { // Convert case statements to if() blocks. Must be after V3Unknown // Must be before V3Task so don't need to deal with task in case value compares V3Case::caseAll(v3Global.rootp()); + } + if (!(v3Global.opt.xmlOnly() && !v3Global.opt.flatten())) { // Inline all tasks V3Task::taskAll(v3Global.rootp()); + } + if (!v3Global.opt.xmlOnly()) { // Add __PVT's // After V3Task so task internal variables will get renamed V3Name::nameAll(v3Global.rootp()); diff --git a/test_regress/t/t_xml_flat.out b/test_regress/t/t_xml_flat.out new file mode 100644 index 000000000..4ba3a085a --- /dev/null +++ b/test_regress/t/t_xml_flat.out @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test_regress/t/t_xml_flat.pl b/test_regress/t/t_xml_flat.pl new file mode 100755 index 000000000..f8062ce2d --- /dev/null +++ b/test_regress/t/t_xml_flat.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2012 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 + +scenarios(vlt => 1); + +my $out_filename = "$Self->{obj_dir}/V$Self->{name}.xml"; + +top_filename("t/t_xml_first.v"); + +compile( + verilator_flags2 => ['--xml-only', '--flatten'], + verilator_make_gmake => 0, + make_top_shell => 0, + make_main => 0, + ); + +files_identical("$out_filename", $Self->{golden_filename}); + +ok(1); +1;