Add creating __inputs.vpp file with --debug (#4177).
This commit is contained in:
parent
444020f7c7
commit
d269fbb446
1
Changes
1
Changes
|
|
@ -19,6 +19,7 @@ Verilator 5.011 devel
|
||||||
**Minor:**
|
**Minor:**
|
||||||
|
|
||||||
* Support get_randstate/set_randstate class method function.
|
* Support get_randstate/set_randstate class method function.
|
||||||
|
* Add creating __inputs.vpp file with --debug (#4177). [Tudor Timi]
|
||||||
* Optimize VPI callValueCbs (#4155). [Hennadii Chernyshchyk]
|
* Optimize VPI callValueCbs (#4155). [Hennadii Chernyshchyk]
|
||||||
* Fix crash on duplicate imported modules (#3231). [Robert Balas]
|
* Fix crash on duplicate imported modules (#3231). [Robert Balas]
|
||||||
* Fix false WIDTHEXPAND on array declarations (#3959). [JOTEGO]
|
* Fix false WIDTHEXPAND on array declarations (#3959). [JOTEGO]
|
||||||
|
|
|
||||||
|
|
@ -126,8 +126,10 @@ In specific debug and other modes, it also creates:
|
||||||
- Debugging graph files (from --debug)
|
- Debugging graph files (from --debug)
|
||||||
* - *{prefix}{misc}*\ .tree
|
* - *{prefix}{misc}*\ .tree
|
||||||
- Debugging files (from --debug)
|
- Debugging files (from --debug)
|
||||||
* - {mod_prefix}_{each_verilog_base_filename}*\ .vpp
|
* - *{prefix}*\ __inputs\ .vpp
|
||||||
- Pre-processed verilog (from --debug)
|
- Pre-processed verilog for all files (from --debug)
|
||||||
|
* - *{prefix}*\ _ *{each_verilog_base_filename}*\ .vpp
|
||||||
|
- Pre-processed verilog for each file (from --debug)
|
||||||
|
|
||||||
After running Make, the C++ compiler may produce the following:
|
After running Make, the C++ compiler may produce the following:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1503,8 +1503,19 @@ debug level 5, with the V3Width.cpp file at level 9.
|
||||||
--debug
|
--debug
|
||||||
-------
|
-------
|
||||||
|
|
||||||
When you run with ``--debug``, there are two primary output file types
|
When you run with ``--debug``, there are three primary output file types
|
||||||
placed into the obj_dir, .tree and .dot files.
|
placed into the obj_dir, .vpp, .tree and .dot files.
|
||||||
|
|
||||||
|
.vpp Output
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Verilator creates a *{mod_prefix}*\ __inputs\ .vpp file containing all the
|
||||||
|
files that were read, filtered by preprocessing. This file can be fed back
|
||||||
|
into Verilator, replacing on the command line all of the previous input
|
||||||
|
files, to enable simplification of test cases.
|
||||||
|
|
||||||
|
Verilator also creates .vpp files for each individual file passed on the
|
||||||
|
command line.
|
||||||
|
|
||||||
|
|
||||||
.dot Output
|
.dot Output
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include "V3Os.h"
|
#include "V3Os.h"
|
||||||
#include "V3ParseBison.h" // Generated by bison
|
#include "V3ParseBison.h" // Generated by bison
|
||||||
#include "V3PreShell.h"
|
#include "V3PreShell.h"
|
||||||
|
#include "V3Stats.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
@ -247,24 +248,22 @@ size_t V3ParseImp::ppInputToLex(char* buf, size_t max_size) {
|
||||||
return got;
|
return got;
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3ParseImp::preprocDumps(std::ostream& os) {
|
void V3ParseImp::preprocDumps(std::ostream& os, bool forInputs) {
|
||||||
if (v3Global.opt.dumpDefines()) {
|
bool noblanks = forInputs || (v3Global.opt.preprocOnly() && v3Global.opt.preprocNoLine());
|
||||||
V3PreShell::dumpDefines(os);
|
bool nolines = forInputs;
|
||||||
} else {
|
for (auto& buf : m_ppBuffers) {
|
||||||
const bool noblanks = v3Global.opt.preprocOnly() && v3Global.opt.preprocNoLine();
|
if (noblanks) {
|
||||||
for (auto& buf : m_ppBuffers) {
|
bool blank = true;
|
||||||
if (noblanks) {
|
for (string::iterator its = buf.begin(); its != buf.end(); ++its) {
|
||||||
bool blank = true;
|
if (!std::isspace(*its) && *its != '\n') {
|
||||||
for (string::iterator its = buf.begin(); its != buf.end(); ++its) {
|
blank = false;
|
||||||
if (!std::isspace(*its) && *its != '\n') {
|
break;
|
||||||
blank = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (blank) continue;
|
|
||||||
}
|
}
|
||||||
os << buf;
|
if (blank) continue;
|
||||||
|
if (nolines && buf.rfind("`line ", 0) == 0) continue;
|
||||||
}
|
}
|
||||||
|
os << buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -292,7 +291,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
|
||||||
if (v3Global.opt.preprocOnly() || v3Global.opt.keepTempFiles()) {
|
if (v3Global.opt.preprocOnly() || v3Global.opt.keepTempFiles()) {
|
||||||
// Create output file with all the preprocessor output we buffered up
|
// Create output file with all the preprocessor output we buffered up
|
||||||
const string vppfilename = v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix()
|
const string vppfilename = v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix()
|
||||||
+ "_" + nondirname + ".vpp";
|
+ "__" + nondirname + ".vpp";
|
||||||
std::ofstream* ofp = nullptr;
|
std::ofstream* ofp = nullptr;
|
||||||
std::ostream* osp;
|
std::ostream* osp;
|
||||||
if (v3Global.opt.preprocOnly()) {
|
if (v3Global.opt.preprocOnly()) {
|
||||||
|
|
@ -303,15 +302,20 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
|
||||||
if (osp->fail()) {
|
if (osp->fail()) {
|
||||||
fileline->v3error("Cannot write preprocessor output: " + vppfilename);
|
fileline->v3error("Cannot write preprocessor output: " + vppfilename);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
if (v3Global.opt.dumpDefines()) {
|
||||||
|
V3PreShell::dumpDefines(*osp);
|
||||||
} else {
|
} else {
|
||||||
preprocDumps(*osp);
|
preprocDumps(*osp, false);
|
||||||
if (ofp) {
|
}
|
||||||
ofp->close();
|
if (ofp) {
|
||||||
VL_DO_DANGLING(delete ofp, ofp);
|
ofp->close();
|
||||||
}
|
VL_DO_DANGLING(delete ofp, ofp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debug() && modfilename != V3Options::getStdPackagePath()) dumpInputsFile();
|
||||||
|
|
||||||
// Parse it
|
// Parse it
|
||||||
if (!v3Global.opt.preprocOnly()) {
|
if (!v3Global.opt.preprocOnly()) {
|
||||||
lexFile(modfilename);
|
lexFile(modfilename);
|
||||||
|
|
@ -320,6 +324,31 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3ParseImp::dumpInputsFile() {
|
||||||
|
// Create output file with joined preprocessor output we buffered up,
|
||||||
|
// Useful for debug to feed back into Verilator
|
||||||
|
static bool append = false;
|
||||||
|
const string vppfilename
|
||||||
|
= v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix() + "__inputs.vpp";
|
||||||
|
std::ofstream* ofp = V3File::new_ofstream(vppfilename, append);
|
||||||
|
if (ofp->fail()) {
|
||||||
|
v3error("Cannot write preprocessor output: " + vppfilename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!append) {
|
||||||
|
append = true;
|
||||||
|
UINFO(1, "Writing all preprocessed output to " << vppfilename << endl);
|
||||||
|
*ofp << "// Dump of all post-preprocessor input\n";
|
||||||
|
*ofp << "// Blank lines and `line directives have been removed\n";
|
||||||
|
*ofp << "//\n";
|
||||||
|
V3Stats::infoHeader(*ofp, "// ");
|
||||||
|
}
|
||||||
|
*ofp << "\n";
|
||||||
|
preprocDumps(*ofp, true);
|
||||||
|
ofp->close();
|
||||||
|
VL_DO_DANGLING(delete ofp, ofp);
|
||||||
|
}
|
||||||
|
|
||||||
void V3ParseImp::lexFile(const string& modname) {
|
void V3ParseImp::lexFile(const string& modname) {
|
||||||
// Prepare for lexing
|
// Prepare for lexing
|
||||||
UINFO(3, "Lexing " << modname << endl);
|
UINFO(3, "Lexing " << modname << endl);
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,7 @@ public:
|
||||||
|
|
||||||
void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
|
void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
|
||||||
const string& errmsg);
|
const string& errmsg);
|
||||||
|
void dumpInputsFile();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void lexFile(const string& modname);
|
void lexFile(const string& modname);
|
||||||
|
|
@ -305,7 +306,7 @@ private:
|
||||||
size_t tokenPipeScanParam(size_t depth);
|
size_t tokenPipeScanParam(size_t depth);
|
||||||
size_t tokenPipeScanType(size_t depth);
|
size_t tokenPipeScanType(size_t depth);
|
||||||
const V3ParseBisonYYSType* tokenPeekp(size_t depth);
|
const V3ParseBisonYYSType* tokenPeekp(size_t depth);
|
||||||
void preprocDumps(std::ostream& os);
|
void preprocDumps(std::ostream& os, bool forInputs);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,8 @@ public:
|
||||||
static void statsFinalAll(AstNetlist* nodep);
|
static void statsFinalAll(AstNetlist* nodep);
|
||||||
/// Called by the top level to dump the statistics
|
/// Called by the top level to dump the statistics
|
||||||
static void statsReport();
|
static void statsReport();
|
||||||
|
/// Called by debug dumps
|
||||||
|
static void infoHeader(std::ofstream& os, const string& prefix);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
|
|
@ -40,18 +40,8 @@ class StatsReport final {
|
||||||
std::ofstream& os; ///< Output stream
|
std::ofstream& os; ///< Output stream
|
||||||
static StatColl s_allStats; ///< All statistics
|
static StatColl s_allStats; ///< All statistics
|
||||||
|
|
||||||
void header() {
|
|
||||||
os << "Verilator Statistics Report\n\n";
|
|
||||||
|
|
||||||
os << "Information:\n";
|
|
||||||
os << " " << V3Options::version() << '\n';
|
|
||||||
os << " Arguments: " << v3Global.opt.allArgsString() << '\n';
|
|
||||||
os << " Build jobs: " << v3Global.opt.buildJobs() << '\n';
|
|
||||||
os << " Verilate jobs: " << v3Global.opt.verilateJobs() << '\n';
|
|
||||||
os << '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
void sumit() {
|
void sumit() {
|
||||||
|
os << '\n';
|
||||||
// If sumit is set on a statistic, combine with others of same name
|
// If sumit is set on a statistic, combine with others of same name
|
||||||
std::multimap<std::string, V3Statistic*> byName;
|
std::multimap<std::string, V3Statistic*> byName;
|
||||||
// * is always first
|
// * is always first
|
||||||
|
|
@ -179,7 +169,8 @@ public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
explicit StatsReport(std::ofstream* aofp)
|
explicit StatsReport(std::ofstream* aofp)
|
||||||
: os(*aofp) { // Need () or GCC 4.8 false warning
|
: os(*aofp) { // Need () or GCC 4.8 false warning
|
||||||
header();
|
os << "Verilator Statistics Report\n\n";
|
||||||
|
V3Stats::infoHeader(os, "");
|
||||||
sumit();
|
sumit();
|
||||||
stars();
|
stars();
|
||||||
stages();
|
stages();
|
||||||
|
|
@ -222,6 +213,14 @@ void V3Stats::statsStage(const string& name) {
|
||||||
V3Stats::addStatPerf("Stage, Memory (MB), " + digitName, memory);
|
V3Stats::addStatPerf("Stage, Memory (MB), " + digitName, memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3Stats::infoHeader(std::ofstream& os, const string& prefix) {
|
||||||
|
os << prefix << "Information:\n";
|
||||||
|
os << prefix << " " << V3Options::version() << '\n';
|
||||||
|
os << prefix << " Arguments: " << v3Global.opt.allArgsString() << '\n';
|
||||||
|
os << prefix << " Build jobs: " << v3Global.opt.buildJobs() << '\n';
|
||||||
|
os << prefix << " Verilate jobs: " << v3Global.opt.verilateJobs() << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
void V3Stats::statsReport() {
|
void V3Stats::statsReport() {
|
||||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 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);
|
||||||
|
|
||||||
|
lint(
|
||||||
|
v_flags => ["--debug --debugi 1 -Wno-MULTITOP t/t_debug_inputs_b.v"],
|
||||||
|
);
|
||||||
|
|
||||||
|
file_grep("$Self->{obj_dir}/V$Self->{name}__inputs.vpp", qr/module t_debug_inputs /);
|
||||||
|
file_grep("$Self->{obj_dir}/V$Self->{name}__inputs.vpp", qr/module t_debug_inputs_a /);
|
||||||
|
file_grep("$Self->{obj_dir}/V$Self->{name}__inputs.vpp", qr/module t_debug_inputs_b /);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// DESCRIPTION: Verilator: Dotted reference that uses another dotted reference
|
||||||
|
// as the select expression
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2023 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
`include "t/t_debug_inputs_a.v"
|
||||||
|
|
||||||
|
module t_debug_inputs (/*AUTOARG*/);
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// DESCRIPTION: Verilator: Dotted reference that uses another dotted reference
|
||||||
|
// as the select expression
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2023 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t_debug_inputs_a (/*AUTOARG*/);
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// DESCRIPTION: Verilator: Dotted reference that uses another dotted reference
|
||||||
|
// as the select expression
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2023 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t_debug_inputs_b (/*AUTOARG*/);
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue