Add --dump-defines.

This commit is contained in:
Wilson Snyder 2018-10-25 19:45:06 -04:00
parent 74a92e739f
commit e0654dc218
14 changed files with 109 additions and 14 deletions

View File

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

View File

@ -289,6 +289,7 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
--debugi-<srcfile> <level> Enable debugging a source file at a level
--default-language <lang> Default language to parse
+define+<var>=<value> Set preprocessor define
--dump-defines Show preprocessor defines with -E
--dump-tree Enable dumping .tree files
--dump-treei <level> Enable dumping .tree files at a level
--dump-treei-<srcfile> <level> 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,

View File

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

View File

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

View File

@ -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<string>::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<string>::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);

View File

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

View File

@ -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 "<<it->first;
// No need to print "()" below as already part of params()
if (!it->second.params().empty()) os<<it->second.params();
if (!it->second.value().empty()) os<<" "<<it->second.value();
os<<endl;
}
}
int V3PreProcImp::getRawToken() {
// Get a token from the file, whatever it may be.
while (1) {

View File

@ -90,8 +90,9 @@ public:
virtual string removeDefines(const string& text)=0; // Remove defines in a text string
// UTILITIES
void error(const string& msg) { fileline()->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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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