From e0654dc2188cb2fae8a64bf1b5f56b62396be15a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 25 Oct 2018 19:45:06 -0400 Subject: [PATCH] Add --dump-defines. --- Changes | 2 ++ bin/verilator | 10 ++++++++++ src/V3Options.cpp | 2 ++ src/V3Options.h | 2 ++ src/V3ParseImp.cpp | 30 ++++++++++++++++++---------- src/V3ParseImp.h | 1 + src/V3PreProc.cpp | 11 ++++++++++ src/V3PreProc.h | 5 +++-- src/V3PreShell.cpp | 3 +++ src/V3PreShell.h | 1 + test_regress/t/t_preproc.out | 4 +++- test_regress/t/t_preproc.v | 2 ++ test_regress/t/t_preproc_defines.out | 25 +++++++++++++++++++++++ test_regress/t/t_preproc_defines.pl | 25 +++++++++++++++++++++++ 14 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 test_regress/t/t_preproc_defines.out create mode 100755 test_regress/t/t_preproc_defines.pl diff --git a/Changes b/Changes index e25ce8f72..863b817ad 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.005 devel +** Add --dump-defines. + *** For --trace-fst, save enum decoding information, bug1358. [Sergi Granell] (To visualize enumeration data you must use GTKwave 3.3.95 or newer.) diff --git a/bin/verilator b/bin/verilator index 25da8cd5e..10569b379 100755 --- a/bin/verilator +++ b/bin/verilator @@ -289,6 +289,7 @@ detailed descriptions in L for more information. --debugi- Enable debugging a source file at a level --default-language Default language to parse +define+= Set preprocessor define + --dump-defines Show preprocessor defines with -E --dump-tree Enable dumping .tree files --dump-treei Enable dumping .tree files at a level --dump-treei- Enable dumping .tree file at a source file at a level @@ -718,6 +719,15 @@ Defines the given preprocessor symbol, or multiple symbols if separated by plusses. Similar to -D; +define is fairly standard across Verilog tools while -D is an alias for GCC compatibility. +=item --dump-defines + +With -E, suppress normal output, and instead print a list of all defines +existing at the end of pre-processing the input files. Similar to GCC "-dM" +option. This also gives you a way of finding out what is predefined in +Verilator using the command: + + touch foo.v ; verilator -E --dump-defines foo.v + =item --dump-tree Rarely needed. Enable writing .tree debug files with dumping level 3, diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 3dac13ce8..433453cc1 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -670,6 +670,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char else if ( !strcmp (sw, "-debug-sigsegv") ) { throwSigsegv(); } // Undocumented, see also --debug-abort else if ( !strcmp (sw, "-debug-fatalsrc") ) { v3fatalSrc("--debug-fatal-src"); } // Undocumented, see also --debug-abort else if ( onoff (sw, "-decoration", flag/*ref*/) ) { m_decoration = flag; } + 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, "-ignc", flag/*ref*/) ) { m_ignc = flag; } @@ -1253,6 +1254,7 @@ V3Options::V3Options() { m_debugPartition = false; m_debugSelfTest = false; m_decoration = true; + m_dumpDefines = false; m_exe = false; m_ignc = false; m_inhibitSim = false; diff --git a/src/V3Options.h b/src/V3Options.h index 69f896423..7e1c4958a 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -117,6 +117,7 @@ class V3Options { bool m_debugPartition; // main switch: --debug-partition bool m_debugSelfTest; // main switch: --debug-self-test bool m_decoration; // main switch: --decoration + bool m_dumpDefines; // main switch: --dump-defines bool m_exe; // main switch: --exe bool m_ignc; // main switch: --ignc bool m_inhibitSim; // main switch: --inhibit-sim @@ -282,6 +283,7 @@ class V3Options { bool debugPartition() const { return m_debugPartition; } bool debugSelfTest() const { return m_debugSelfTest; } bool decoration() const { return m_decoration; } + bool dumpDefines() const { return m_dumpDefines; } bool exe() const { return m_exe; } bool threadsDpiPure() const { return m_threadsDpiPure; } bool threadsDpiUnpure() const { return m_threadsDpiUnpure; } diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index a1f9dfed6..cdba8e791 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -89,6 +89,24 @@ size_t V3ParseImp::ppInputToLex(char* buf, size_t max_size) { return got; } +void V3ParseImp::preprocDumps(std::ostream& os) { + if (v3Global.opt.dumpDefines()) { + V3PreShell::dumpDefines(os); + } else { + bool noblanks = v3Global.opt.preprocOnly() && v3Global.opt.preprocNoLine(); + for (std::deque::iterator it = m_ppBuffers.begin(); it!=m_ppBuffers.end(); ++it) { + if (noblanks) { + bool blank = true; + for (string::iterator its = it->begin(); its != it->end(); ++its) { + if (!isspace(*its) && *its!='\n') { blank=false; break; } + } + if (blank) continue; + } + os << *it; + } + } +} + void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary, const string& errmsg) { // "" for no error, make fake node string modname = V3Os::filenameNonExt(modfilename); @@ -123,7 +141,6 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i string vppfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_"+modname+".vpp"; std::ofstream* ofp = NULL; std::ostream* osp; - bool noblanks = v3Global.opt.preprocOnly() && v3Global.opt.preprocNoLine(); if (v3Global.opt.preprocOnly()) { osp = &cout; } else { @@ -133,16 +150,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i fileline->v3error("Cannot write preprocessor output: "+vppfilename); return; } else { - for (std::deque::iterator it = m_ppBuffers.begin(); it!=m_ppBuffers.end(); ++it) { - if (noblanks) { - bool blank = true; - for (string::iterator its = it->begin(); its != it->end(); ++its) { - if (!isspace(*its) && *its!='\n') { blank=false; break; } - } - if (blank) continue; - } - *osp << *it; - } + preprocDumps(*osp); if (ofp) { ofp->close(); delete ofp; VL_DANGLING(ofp); diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index 333c5df92..6f58d196d 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -244,6 +244,7 @@ private: void lexFile(const string& modname); int yylexReadTok(); void lexToken(); // Internal; called from lexToBison + void preprocDumps(std::ostream& os); }; #endif // Guard diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 811c7e2d1..807e3baa7 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -231,6 +231,7 @@ public: void insertUnreadback(const string& text) { m_lineCmt += text; } void insertUnreadbackAtBol(const string& text); void addLineComment(int enterExit); + void dumpDefines(std::ostream& os); // METHODS, callbacks virtual void comment(const string& text); // Comment detected (if keepComments==2) @@ -798,6 +799,16 @@ void V3PreProcImp::addLineComment(int enterExit) { } } +void V3PreProcImp::dumpDefines(std::ostream& os) { + for (DefinesMap::iterator it = m_defines.begin(); it != m_defines.end(); ++it) { + os<<"`define "<first; + // No need to print "()" below as already part of params() + if (!it->second.params().empty()) os<second.params(); + if (!it->second.value().empty()) os<<" "<second.value(); + os<v3error(msg); } ///< Report a error - void fatal(const string& msg) { fileline()->v3fatalSrc(msg); } ///< Report a fatal error + void error(const string& msg) { fileline()->v3error(msg); } ///< Report an error + void fatal(const string& msg) { fileline()->v3fatalSrc(msg); } ///< Report a fatal error + virtual void dumpDefines(std::ostream& os) = 0; ///< Print list of `defines protected: // CONSTUCTORS diff --git a/src/V3PreShell.cpp b/src/V3PreShell.cpp index 030ff0515..bbf624707 100644 --- a/src/V3PreShell.cpp +++ b/src/V3PreShell.cpp @@ -167,3 +167,6 @@ void V3PreShell::defineCmdLine(const string& name, const string& value) { void V3PreShell::undef(const string& name) { V3PreShellImp::s_preprocp->undef(name); } +void V3PreShell::dumpDefines(std::ostream& os) { + V3PreShellImp::s_preprocp->dumpDefines(os); +} diff --git a/src/V3PreShell.h b/src/V3PreShell.h index 553aaf6fd..0044a3dc1 100644 --- a/src/V3PreShell.h +++ b/src/V3PreShell.h @@ -42,6 +42,7 @@ public: static string dependFiles() { return ""; } // Perl only static void defineCmdLine(const string& name, const string& value); static void undef(const string& name); + static void dumpDefines(std::ostream& os); }; #endif // Guard diff --git a/test_regress/t/t_preproc.out b/test_regress/t/t_preproc.out index 14f1206c4..df2757029 100644 --- a/test_regress/t/t_preproc.out +++ b/test_regress/t/t_preproc.out @@ -948,5 +948,7 @@ predef 0 0 predef 1 1 predef 2 2 + + -`line 654 "t/t_preproc.v" 2 +`line 656 "t/t_preproc.v" 2 diff --git a/test_regress/t/t_preproc.v b/test_regress/t/t_preproc.v index 386c7faef..035188082 100644 --- a/test_regress/t/t_preproc.v +++ b/test_regress/t/t_preproc.v @@ -650,3 +650,5 @@ predef `SV_COV_NOCOV 0 predef `SV_COV_OK 1 predef `SV_COV_PARTIAL 2 //====================================================================== +// After `undefineall above, for testing --dump-defines +`define WITH_ARG(a) (a)(a) diff --git a/test_regress/t/t_preproc_defines.out b/test_regress/t/t_preproc_defines.out new file mode 100644 index 000000000..a1eaedd69 --- /dev/null +++ b/test_regress/t/t_preproc_defines.out @@ -0,0 +1,25 @@ +`define DEF_A0 +`define PREDEF_COMMAND_LINE +`define SV_COV_ASSERTION 20 +`define SV_COV_CHECK 3 +`define SV_COV_ERROR -1 +`define SV_COV_FSM_STATE 21 +`define SV_COV_HIER 11 +`define SV_COV_MODULE 10 +`define SV_COV_NOCOV 0 +`define SV_COV_OK 1 +`define SV_COV_OVERFLOW -2 +`define SV_COV_PARTIAL 2 +`define SV_COV_RESET 2 +`define SV_COV_START 0 +`define SV_COV_STATEMENT 22 +`define SV_COV_STOP 1 +`define SV_COV_TOGGLE 23 +`define SYSTEMVERILOG 1 +`define TEST_OBJ_DIR obj_vlt/t_preproc_defines +`define VERILATOR 1 +`define WITH_ARG(a) (a)(a) +`define coverage_block_off /*verilator coverage_block_off*/ +`define systemc_clock /*verilator systemc_clock*/ +`define verilator 1 +`define verilator3 1 diff --git a/test_regress/t/t_preproc_defines.pl b/test_regress/t/t_preproc_defines.pl new file mode 100755 index 000000000..eb1d00b5e --- /dev/null +++ b/test_regress/t/t_preproc_defines.pl @@ -0,0 +1,25 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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. + +scenarios(vlt => 1); + +top_filename("t/t_preproc.v"); + +$Self->{golden_out} ||= "t/$Self->{name}.out"; +my $stdout_filename = "$Self->{obj_dir}/$Self->{name}__test.vpp"; + +compile( + verilator_flags2 => ['-DDEF_A0 -DPREDEF_COMMAND_LINE -E --dump-defines'], + verilator_make_gcc => 0, + stdout_filename => $stdout_filename, + ); + +ok(files_identical($stdout_filename, $Self->{golden_out})); + +1;