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:**
* Support get_randstate/set_randstate class method function.
* Add creating __inputs.vpp file with --debug (#4177). [Tudor Timi]
* Optimize VPI callValueCbs (#4155). [Hennadii Chernyshchyk]
* Fix crash on duplicate imported modules (#3231). [Robert Balas]
* 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)
* - *{prefix}{misc}*\ .tree
- Debugging files (from --debug)
* - {mod_prefix}_{each_verilog_base_filename}*\ .vpp
- Pre-processed verilog (from --debug)
* - *{prefix}*\ __inputs\ .vpp
- 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:

View File

@ -1503,8 +1503,19 @@ debug level 5, with the V3Width.cpp file at level 9.
--debug
-------
When you run with ``--debug``, there are two primary output file types
placed into the obj_dir, .tree and .dot files.
When you run with ``--debug``, there are three primary output file types
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

View File

@ -35,6 +35,7 @@
#include "V3Os.h"
#include "V3ParseBison.h" // Generated by bison
#include "V3PreShell.h"
#include "V3Stats.h"
#include <sstream>
@ -247,24 +248,22 @@ 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 {
const bool noblanks = v3Global.opt.preprocOnly() && v3Global.opt.preprocNoLine();
for (auto& buf : m_ppBuffers) {
if (noblanks) {
bool blank = true;
for (string::iterator its = buf.begin(); its != buf.end(); ++its) {
if (!std::isspace(*its) && *its != '\n') {
blank = false;
break;
}
void V3ParseImp::preprocDumps(std::ostream& os, bool forInputs) {
bool noblanks = forInputs || (v3Global.opt.preprocOnly() && v3Global.opt.preprocNoLine());
bool nolines = forInputs;
for (auto& buf : m_ppBuffers) {
if (noblanks) {
bool blank = true;
for (string::iterator its = buf.begin(); its != buf.end(); ++its) {
if (!std::isspace(*its) && *its != '\n') {
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()) {
// Create output file with all the preprocessor output we buffered up
const string vppfilename = v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix()
+ "_" + nondirname + ".vpp";
+ "__" + nondirname + ".vpp";
std::ofstream* ofp = nullptr;
std::ostream* osp;
if (v3Global.opt.preprocOnly()) {
@ -303,15 +302,20 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
if (osp->fail()) {
fileline->v3error("Cannot write preprocessor output: " + vppfilename);
return;
}
if (v3Global.opt.dumpDefines()) {
V3PreShell::dumpDefines(*osp);
} else {
preprocDumps(*osp);
if (ofp) {
ofp->close();
VL_DO_DANGLING(delete ofp, ofp);
}
preprocDumps(*osp, false);
}
if (ofp) {
ofp->close();
VL_DO_DANGLING(delete ofp, ofp);
}
}
if (debug() && modfilename != V3Options::getStdPackagePath()) dumpInputsFile();
// Parse it
if (!v3Global.opt.preprocOnly()) {
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) {
// Prepare for lexing
UINFO(3, "Lexing " << modname << endl);

View File

@ -295,6 +295,7 @@ public:
void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
const string& errmsg);
void dumpInputsFile();
private:
void lexFile(const string& modname);
@ -305,7 +306,7 @@ private:
size_t tokenPipeScanParam(size_t depth);
size_t tokenPipeScanType(size_t depth);
const V3ParseBisonYYSType* tokenPeekp(size_t depth);
void preprocDumps(std::ostream& os);
void preprocDumps(std::ostream& os, bool forInputs);
};
#endif // Guard

View File

@ -121,6 +121,8 @@ public:
static void statsFinalAll(AstNetlist* nodep);
/// Called by the top level to dump the statistics
static void statsReport();
/// Called by debug dumps
static void infoHeader(std::ofstream& os, const string& prefix);
};
#endif // Guard

View File

@ -40,18 +40,8 @@ class StatsReport final {
std::ofstream& os; ///< Output stream
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() {
os << '\n';
// If sumit is set on a statistic, combine with others of same name
std::multimap<std::string, V3Statistic*> byName;
// * is always first
@ -179,7 +169,8 @@ public:
// CONSTRUCTORS
explicit StatsReport(std::ofstream* aofp)
: os(*aofp) { // Need () or GCC 4.8 false warning
header();
os << "Verilator Statistics Report\n\n";
V3Stats::infoHeader(os, "");
sumit();
stars();
stages();
@ -222,6 +213,14 @@ void V3Stats::statsStage(const string& name) {
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() {
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