Add creating __inputs.vpp file with --debug (#4177).

This commit is contained in:
Wilson Snyder 2023-05-07 17:58:14 -04:00
parent 444020f7c7
commit d269fbb446
11 changed files with 134 additions and 38 deletions

View File

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

View File

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

View File

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

View File

@ -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,11 +248,9 @@ 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 {
const bool noblanks = v3Global.opt.preprocOnly() && v3Global.opt.preprocNoLine();
for (auto& buf : m_ppBuffers) { for (auto& buf : m_ppBuffers) {
if (noblanks) { if (noblanks) {
bool blank = true; bool blank = true;
@ -262,11 +261,11 @@ void V3ParseImp::preprocDumps(std::ostream& os) {
} }
} }
if (blank) continue; if (blank) continue;
if (nolines && buf.rfind("`line ", 0) == 0) continue;
} }
os << buf; os << buf;
} }
} }
}
void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary, void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
const string& errmsg) { // "" for no error, make fake node const string& errmsg) { // "" for no error, make fake node
@ -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,14 +302,19 @@ 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) { if (ofp) {
ofp->close(); ofp->close();
VL_DO_DANGLING(delete ofp, ofp); VL_DO_DANGLING(delete ofp, ofp);
} }
} }
}
if (debug() && modfilename != V3Options::getStdPackagePath()) dumpInputsFile();
// Parse it // Parse it
if (!v3Global.opt.preprocOnly()) { if (!v3Global.opt.preprocOnly()) {
@ -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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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