Add support for and , #2126.

This commit is contained in:
Wilson Snyder 2020-03-01 21:39:23 -05:00
parent 0ca0e07354
commit 30a33a6104
51 changed files with 1378 additions and 137 deletions

View File

@ -7,6 +7,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
** Add split_var metacomment to assist UNOPTFLAT fixes, #2066. [Yutetsu TAKATSUKASA] ** Add split_var metacomment to assist UNOPTFLAT fixes, #2066. [Yutetsu TAKATSUKASA]
** Add support for $dumpfile and $dumpvars, #2126. [Alexander Grobman]
*** Add +verilator+noassert flag to disable assertion checking. [Tobias Wölfel] *** Add +verilator+noassert flag to disable assertion checking. [Tobias Wölfel]
*** Add check for assertOn for asserts, #2162. [Tobias Wölfel] *** Add check for assertOn for asserts, #2162. [Tobias Wölfel]

View File

@ -3782,17 +3782,29 @@ $unsigned, $warning.
Generally supported. Generally supported.
=item $display, $write, $fdisplay, $fwrite, $swrite
$display and friends must have a constant format string as the first
argument (as with C's printf). The rare usage which lists variables
standalone without a format is not supported.
=item $displayb, $displayh, $displayo, $writeb, $writeh, $writeo, etc =item $displayb, $displayh, $displayo, $writeb, $writeh, $writeo, etc
The sized display functions are rarely used and so not supported. Replace The sized display functions are rarely used and so not supported. Replace
them with a $write with the appropriate format specifier. them with a $write with the appropriate format specifier.
=item $dump/$dumpports and related
$dumpfile or $dumpports will create a VCD or FST file (which is based on
the --trace argument given when the model was Verilated). This will take
effect starting at the next eval() call. If you have multiple Verilated
designs under the same C model, then this will dump signals only from the
design containing the $dumpvar.
$dumpvars and $dumpports module identifier is ignored; the traced instances
will always start at the top of the design. The levels argument is also
ignored, use tracing_on/tracing_off pragmas instead.
$dumpportson/$dumpportsoff/$dumpportsall/$dumpportslimit filename argument
is ignored, only a single trace file may be active at once.
$dumpall/$dumpportsall, $dumpon/$dumpportson, $dumpoff/$dumpportsoff, and
$dumplimit/$dumpportlimit are currently ignored.
=item $finish, $stop =item $finish, $stop
The rarely used optional parameter to $finish and $stop is ignored. The rarely used optional parameter to $finish and $stop is ignored.
@ -4835,19 +4847,20 @@ designs have topped 16GB.
See the next question for tracing in SystemC mode. See the next question for tracing in SystemC mode.
Add the --trace switch to Verilator, and in your top level C code, call A. Add the --trace switch to Verilator, and in your top level C code, call
Verilated::traceEverOn(true). Then create a VerilatedVcdC object, and Verilated::traceEverOn(true). Then you may use $dumpfile and $dumpvars to
in your main loop call "trace_object->dump(time)" every time step, and enable traces, same as with any Verilog simulator. See
finally call "trace_object->close()". For an example, see below and the C<examples/make_tracing_c>.
examples/make_tracing_c/sim_main.cpp file of the distribution.
You also need to compile verilated_vcd_c.cpp and add it to your link, B. Or, for finer-grained control, or C++ files with multiple Verilated
preferably by adding the dependencies in $(VK_GLOBAL_OBJS) to your modules you may also create the trace purely from C++. Create a
Makefile's link rule. This is done for you if using the Verilator --exe VerilatedVcdC object, and in your main loop call "trace_object->dump(time)"
flag. every time step, and finally call "trace_object->close()". You also need
to compile verilated_vcd_c.cpp and add it to your link, preferably by
Note you can also call ->trace on multiple Verilated objects with the same adding the dependencies in $(VK_GLOBAL_OBJS) to your Makefile's link rule.
trace file if you want all data to land in the same output file. This is done for you if using the Verilator --exe flag. Note you can also
call ->trace on multiple Verilated objects with the same trace file if you
want all data to land in the same output file.
#include "verilated_vcd_c.h" #include "verilated_vcd_c.h"
... ...
@ -4867,11 +4880,17 @@ trace file if you want all data to land in the same output file.
=item How do I generate waveforms (traces) in SystemC? =item How do I generate waveforms (traces) in SystemC?
Add the --trace switch to Verilator, and in your top level C sc_main code, A. Add the --trace switch to Verilator, and in your top level sc_main, call
include verilated_vcd_sc.h. Then call Verilated::traceEverOn(true). Then Verilated::traceEverOn(true). Then you may use $dumpfile and $dumpvars to
create a VerilatedVcdSc object as you would create a normal SystemC trace enable traces, same as with any Verilog simulator, see the non-SystemC
file. For an example, see the call to VerilatedVcdSc in the example in C<examples/make_tracing_c>. This will trace only the module
examples/make_tracing_sc/sc_main.cpp file of the distribution, and below. containing the $dumpvar.
B. Or, you may create a trace purely from SystemC, which may trace all
Verilated designs in the SystemC model. Create a VerilatedVcdSc object as
you would create a normal SystemC trace file. For an example, see the call
to VerilatedVcdSc in the examples/make_tracing_sc/sc_main.cpp file of the
distribution, and below.
Alternatively you may use the C++ trace mechanism described in the previous Alternatively you may use the C++ trace mechanism described in the previous
question, however the timescale and timeprecision will not inherited from question, however the timescale and timeprecision will not inherited from
@ -4901,23 +4920,23 @@ trace file if you want all data to land in the same output file.
=item How do I generate FST waveforms (traces) in C++? =item How do I generate FST waveforms (traces) in C++?
FST a format by GTKWave. FST a format by GTKWave. This version provides a basic FST support. To
This version provides a basic FST support. dump FST format, add the --trace-fst switch to Verilator and either A. use
To dump FST format, add the --trace-fst switch to Verilator and change the include $dumpfile/$dumpvars in Verilog as described in the VCD example above, or
path in the testbench to: B. in C++ change the include described in the VCD example above:
#include "verilated_fst_c.h" #include "verilated_fst_c.h"
VerilatedFstC* tfp = new VerilatedFstC; VerilatedFstC* tfp = new VerilatedFstC;
Note that currently supporting both FST and VCD in a single simulation is impossible, Note that currently supporting both FST and VCD in a single simulation is
but such requirement could be rare. impossible, but such requirement should be rare.
=item How do I generate FST waveforms (traces) in SystemC? =item How do I generate FST waveforms (aka dumps or traces) in SystemC?
The FST library from GTKWave does not currently support SystemC; use VCD The FST library from GTKWave does not currently support SystemC; use VCD
format instead. format instead.
=item How do I view waveforms (traces)? =item How do I view waveforms (aka dumps or traces)?
Verilator makes standard VCD (Value Change Dump) and FST files. VCD files are viewable Verilator makes standard VCD (Value Change Dump) and FST files. VCD files are viewable
with the public domain GTKWave (recommended) or Dinotrace (legacy) with the public domain GTKWave (recommended) or Dinotrace (legacy)

View File

@ -10,11 +10,6 @@
// Include model header, generated from Verilating "top.v" // Include model header, generated from Verilating "top.v"
#include "Vtop.h" #include "Vtop.h"
// If "verilator --trace" is used, include the tracing class
#if VM_TRACE
# include <verilated_vcd_c.h>
#endif
// Current simulation time (64-bit unsigned) // Current simulation time (64-bit unsigned)
vluint64_t main_time = 0; vluint64_t main_time = 0;
// Called by $time in Verilog // Called by $time in Verilog
@ -36,28 +31,19 @@ int main(int argc, char** argv, char** env) {
// May be overridden by commandArgs // May be overridden by commandArgs
Verilated::randReset(2); Verilated::randReset(2);
// Verilator must compute traced signals
Verilated::traceEverOn(true);
// Pass arguments so Verilated code can see them, e.g. $value$plusargs // Pass arguments so Verilated code can see them, e.g. $value$plusargs
// This needs to be called before you create any model // This needs to be called before you create any model
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
// Create logs/ directory in case we have traces to put under it
Verilated::mkdir("logs");
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v" // Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper
#if VM_TRACE
// If verilator was invoked with --trace argument,
// and if at run time passed the +trace argument, turn on tracing
VerilatedVcdC* tfp = NULL;
const char* flag = Verilated::commandArgsPlusMatch("trace");
if (flag && 0==strcmp(flag, "+trace")) {
Verilated::traceEverOn(true); // Verilator must compute traced signals
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
tfp = new VerilatedVcdC;
top->trace(tfp, 99); // Trace 99 levels of hierarchy
Verilated::mkdir("logs");
tfp->open("logs/vlt_dump.vcd"); // Open the dump file
}
#endif
// Set some inputs // Set some inputs
top->reset_l = !0; top->reset_l = !0;
top->fastclk = 0; top->fastclk = 0;
@ -90,13 +76,11 @@ int main(int argc, char** argv, char** env) {
top->in_quad += 0x12; top->in_quad += 0x12;
// Evaluate model // Evaluate model
// (If you have multiple models being simulated in the same
// timestep then instead of eval(), call eval_step() on each, then
// eval_end_step() on each.)
top->eval(); top->eval();
#if VM_TRACE
// Dump trace data for this cycle
if (tfp) tfp->dump(main_time);
#endif
// Read outputs // Read outputs
VL_PRINTF("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x" VL_PRINTF("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
" -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n", " -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n",
@ -107,11 +91,6 @@ int main(int argc, char** argv, char** env) {
// Final model cleanup // Final model cleanup
top->final(); top->final();
// Close trace if opened
#if VM_TRACE
if (tfp) { tfp->close(); tfp = NULL; }
#endif
// Coverage analysis (since test passed) // Coverage analysis (since test passed)
#if VM_COVERAGE #if VM_COVERAGE
Verilated::mkdir("logs"); Verilated::mkdir("logs");

View File

@ -36,6 +36,11 @@ module top
// Print some stuff as an example // Print some stuff as an example
initial begin initial begin
if ($test$plusargs("trace") != 0) begin
$display("[%0t] Tracing to logs/vlt_dump.vcd...\n", $time);
$dumpfile("logs/vlt_dump.vcd");
$dumpvars();
end
$display("[%0t] Model running...\n", $time); $display("[%0t] Model running...\n", $time);
end end

View File

@ -37,6 +37,9 @@ int sc_main(int argc, char* argv[]) {
// This needs to be called before you create any model // This needs to be called before you create any model
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
// Create logs/ directory in case we have traces to put under it
Verilated::mkdir("logs");
// General logfile // General logfile
ios::sync_with_stdio(); ios::sync_with_stdio();

View File

@ -1602,6 +1602,25 @@ IData VL_ATOI_N(const std::string& str, int base) VL_PURE {
return static_cast<IData>(v); return static_cast<IData>(v);
} }
//===========================================================================
// Dumping
const char* vl_dumpctl_filenamep(bool setit, const std::string& filename) VL_MT_SAFE {
// This function performs both accessing and setting so it's easy to make an in-function static
static VL_THREAD_LOCAL std::string t_filename;
if (setit) {
t_filename = filename;
} else {
static VL_THREAD_LOCAL bool t_warned = false;
if (VL_UNLIKELY(t_filename.empty() && !t_warned)) {
t_warned = true;
VL_PRINTF_MT("%%Warning: $dumpvar ignored as not proceeded by $dumpfile\n");
return "";
}
}
return t_filename.c_str();
}
//=========================================================================== //===========================================================================
// Readmem/writemem // Readmem/writemem

View File

@ -83,6 +83,7 @@ class VerilatedVar;
class VerilatedVarNameMap; class VerilatedVarNameMap;
class VerilatedVcd; class VerilatedVcd;
class VerilatedVcdC; class VerilatedVcdC;
class VerilatedVcdSc;
class VerilatedFst; class VerilatedFst;
class VerilatedFstC; class VerilatedFstC;

View File

@ -64,9 +64,12 @@ protected:
vluint32_t m_code; ///< Starting code number vluint32_t m_code; ///< Starting code number
// CONSTRUCTORS // CONSTRUCTORS
VerilatedFstCallInfo(VerilatedFstCallback_t icb, VerilatedFstCallback_t fcb, VerilatedFstCallInfo(VerilatedFstCallback_t icb, VerilatedFstCallback_t fcb,
VerilatedFstCallback_t changecb, VerilatedFstCallback_t changecb, void* ut)
void* ut, vluint32_t code) : m_initcb(icb)
: m_initcb(icb), m_fullcb(fcb), m_changecb(changecb), m_userthis(ut), m_code(code) {} , m_fullcb(fcb)
, m_changecb(changecb)
, m_userthis(ut)
, m_code(1) {}
~VerilatedFstCallInfo() {} ~VerilatedFstCallInfo() {}
}; };
@ -173,17 +176,16 @@ void VerilatedFst::declSymbol(vluint32_t code, const char* name,
//============================================================================= //=============================================================================
// Callbacks // Callbacks
void VerilatedFst::addCallback( void VerilatedFst::addCallback(VerilatedFstCallback_t initcb, VerilatedFstCallback_t fullcb,
VerilatedFstCallback_t initcb, VerilatedFstCallback_t fullcb, VerilatedFstCallback_t changecb, void* userthis) VL_MT_UNSAFE_ONE {
VerilatedFstCallback_t changecb, void* userthis) VL_MT_UNSAFE_ONE {
m_assertOne.check(); m_assertOne.check();
if (VL_UNLIKELY(isOpen())) { if (VL_UNLIKELY(isOpen())) {
std::string msg = (std::string("Internal: ")+__FILE__+"::"+__FUNCTION__ std::string msg = (std::string("Internal: ") + __FILE__ + "::" + __FUNCTION__
+" called with already open file"); + " called with already open file");
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str()); VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
} }
VerilatedFstCallInfo* vci = new VerilatedFstCallInfo(initcb, fullcb, changecb, userthis, 1); VerilatedFstCallInfo* cip = new VerilatedFstCallInfo(initcb, fullcb, changecb, userthis);
m_callbacks.push_back(vci); m_callbacks.push_back(cip);
} }
//============================================================================= //=============================================================================
@ -192,7 +194,7 @@ void VerilatedFst::addCallback(
void VerilatedFst::dump(vluint64_t timeui) { void VerilatedFst::dump(vluint64_t timeui) {
if (!isOpen()) return; if (!isOpen()) return;
if (VL_UNLIKELY(m_fullDump)) { if (VL_UNLIKELY(m_fullDump)) {
m_fullDump = false; // No need for more full dumps m_fullDump = false; // No more need for next dump to be full
for (vluint32_t ent = 0; ent< m_callbacks.size(); ++ent) { for (vluint32_t ent = 0; ent< m_callbacks.size(); ++ent) {
VerilatedFstCallInfo* cip = m_callbacks[ent]; VerilatedFstCallInfo* cip = m_callbacks[ent];
(cip->m_fullcb)(this, cip->m_userthis, cip->m_code); (cip->m_fullcb)(this, cip->m_userthis, cip->m_code);

View File

@ -198,7 +198,7 @@ class VerilatedFstC {
VL_UNCOPYABLE(VerilatedFstC); VL_UNCOPYABLE(VerilatedFstC);
public: public:
explicit VerilatedFstC(void* filep=NULL) : m_sptrace(filep) {} explicit VerilatedFstC(void* filep=NULL) : m_sptrace(filep) {}
~VerilatedFstC() {} ~VerilatedFstC() { close(); }
public: public:
// ACCESSORS // ACCESSORS
/// Is file open? /// Is file open?

View File

@ -441,4 +441,10 @@ inline IData VL_CMP_NN(const std::string& lhs, const std::string& rhs, bool igno
extern IData VL_ATOI_N(const std::string& str, int base) VL_PURE; extern IData VL_ATOI_N(const std::string& str, int base) VL_PURE;
//======================================================================
// Dumping
extern const char* vl_dumpctl_filenamep(bool setit = false,
const std::string& filename = "") VL_MT_SAFE;
#endif // Guard #endif // Guard

View File

@ -119,7 +119,7 @@ protected:
bool VerilatedVcdFile::open(const std::string& name) VL_MT_UNSAFE { bool VerilatedVcdFile::open(const std::string& name) VL_MT_UNSAFE {
m_fd = ::open(name.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK|O_CLOEXEC, 0666); m_fd = ::open(name.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK|O_CLOEXEC, 0666);
return (m_fd>=0); return m_fd >= 0;
} }
void VerilatedVcdFile::close() VL_MT_UNSAFE { void VerilatedVcdFile::close() VL_MT_UNSAFE {
@ -136,7 +136,10 @@ ssize_t VerilatedVcdFile::write(const char* bufp, ssize_t len) VL_MT_UNSAFE {
// Opening/Closing // Opening/Closing
VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep) VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
: m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) { : m_isOpen(false)
, m_rolloverMB(0)
, m_modDepth(0)
, m_nextCode(1) {
// Not in header to avoid link issue if header is included without this .cpp file // Not in header to avoid link issue if header is included without this .cpp file
m_fileNewed = (filep == NULL); m_fileNewed = (filep == NULL);
m_filep = m_fileNewed ? new VerilatedVcdFile : filep; m_filep = m_fileNewed ? new VerilatedVcdFile : filep;
@ -156,7 +159,7 @@ VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
void VerilatedVcd::open(const char* filename) { void VerilatedVcd::open(const char* filename) {
m_assertOne.check(); m_assertOne.check();
if (isOpen()) return; if (isOpen() || !filename || !*filename) return;
// Set member variables // Set member variables
m_filename = filename; m_filename = filename;
@ -690,7 +693,7 @@ void VerilatedVcd::dump(vluint64_t timeui) {
m_assertOne.check(); m_assertOne.check();
if (!isOpen()) return; if (!isOpen()) return;
if (VL_UNLIKELY(m_fullDump)) { if (VL_UNLIKELY(m_fullDump)) {
m_fullDump = false; // No need for more full dumps m_fullDump = false; // No more need for next dump to be full
dumpFull(timeui); dumpFull(timeui);
return; return;
} }

View File

@ -103,9 +103,9 @@ private:
typedef std::vector<VerilatedVcdSig> SigVec; typedef std::vector<VerilatedVcdSig> SigVec;
SigVec m_sigs; ///< Pointer to signal information SigVec m_sigs; ///< Pointer to signal information
typedef std::vector<VerilatedVcdCallInfo*> CallbackVec; typedef std::vector<VerilatedVcdCallInfo*> CallbackVec;
CallbackVec m_callbacks; ///< Routines to perform dumping CallbackVec m_callbacks; ///< Routines to perform dumping
typedef std::map<std::string,std::string> NameMap; typedef std::map<std::string,std::string> NameMap;
NameMap* m_namemapp; ///< List of names for the header NameMap* m_namemapp; ///< List of names for the header
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
@ -445,7 +445,7 @@ class VerilatedVcdC {
public: public:
explicit VerilatedVcdC(VerilatedVcdFile* filep = NULL) explicit VerilatedVcdC(VerilatedVcdFile* filep = NULL)
: m_sptrace(filep) {} : m_sptrace(filep) {}
~VerilatedVcdC() {} ~VerilatedVcdC() { close(); }
public: public:
// ACCESSORS // ACCESSORS
/// Is file open? /// Is file open?

View File

@ -62,7 +62,7 @@ public:
spTrace()->set_time_resolution(sc_get_time_resolution().to_string()); spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
# endif # endif
} }
virtual ~VerilatedVcdSc() {} virtual ~VerilatedVcdSc() { close(); }
// METHODS // METHODS
/// Called by SystemC simulate() /// Called by SystemC simulate()

View File

@ -815,6 +815,32 @@ inline bool operator==(AstDisplayType::en lhs, const AstDisplayType& rhs) {
//###################################################################### //######################################################################
class VDumpCtlType {
public:
enum en { FILE, VARS, ALL, FLUSH, LIMIT, OFF, ON };
enum en m_e;
inline VDumpCtlType()
: m_e(ON) {}
// cppcheck-suppress noExplicitConstructor
inline VDumpCtlType(en _e)
: m_e(_e) {}
explicit inline VDumpCtlType(int _e)
: m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
const char* ascii() const {
static const char* const names[] = {"$dumpfile", "$dumpvars", "$dumpall", "$dumpflush",
"$dumplimit", "$dumpoff", "$dumpon"};
return names[m_e];
}
};
inline bool operator==(const VDumpCtlType& lhs, const VDumpCtlType& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const VDumpCtlType& lhs, VDumpCtlType::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VDumpCtlType::en lhs, const VDumpCtlType& rhs) { return lhs == rhs.m_e; }
//######################################################################
class VParseRefExp { class VParseRefExp {
public: public:
enum en { enum en {

View File

@ -3033,6 +3033,31 @@ public:
void filep(AstNodeVarRef* nodep) { setNOp3p(nodep); } void filep(AstNodeVarRef* nodep) { setNOp3p(nodep); }
}; };
class AstDumpCtl : public AstNodeStmt {
// $dumpon etc
// Parents: expr
// Child: expr based on type of control statement
VDumpCtlType m_ctlType; // Type of operation
public:
AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNode* exprp = NULL)
: ASTGEN_SUPER(fl), m_ctlType(ctlType) {
setNOp1p(exprp);
}
ASTNODE_NODE_FUNCS(DumpCtl)
virtual string verilogKwd() const { return ctlType().ascii(); }
virtual string emitVerilog() { return "%f" + verilogKwd() + "(%l)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isOutputter() const { return true; }
virtual bool cleanOut() const { return true; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
VDumpCtlType ctlType() const { return m_ctlType; }
AstNode* exprp() const { return op1p(); } // op2 = Expressions to output
void exprp(AstNode* nodep) { setOp1p(nodep); }
};
class AstElabDisplay : public AstNode { class AstElabDisplay : public AstNode {
// Parents: stmtlist // Parents: stmtlist
// Children: SFORMATF to generate print string // Children: SFORMATF to generate print string

View File

@ -402,6 +402,44 @@ public:
if (nodep->addNewline()) text += "\n"; if (nodep->addNewline()) text += "\n";
displayNode(nodep, nodep->fmtp()->scopeNamep(), text, nodep->fmtp()->exprsp(), false); displayNode(nodep, nodep->fmtp()->scopeNamep(), text, nodep->fmtp()->exprsp(), false);
} }
virtual void visit(AstDumpCtl* nodep) VL_OVERRIDE {
switch (nodep->ctlType()) {
case VDumpCtlType::FILE:
puts("vl_dumpctl_filenamep(true, ");
emitCvtPackStr(nodep->exprp());
puts(");\n");
break;
case VDumpCtlType::VARS:
// We ignore number of levels to dump in exprp()
if (v3Global.opt.trace()) {
puts("vlSymsp->TOPp->_traceDumpOpen();\n");
} else {
puts("VL_PRINTF_MT(\"-Info: ");
puts(protect(nodep->fileline()->filename()));
puts(":");
puts(cvtToStr(nodep->fileline()->lineno()));
puts(": $dumpvar ignored, as Verilated without --trace");
puts("\\n\");\n");
}
break;
case VDumpCtlType::ALL:
// $dumpall currently ignored
break;
case VDumpCtlType::FLUSH:
puts("Verilated::flushCall();\n"); // Also flush stdio, as need lock
break;
case VDumpCtlType::LIMIT:
// $dumplimit currently ignored
break;
case VDumpCtlType::OFF:
// Currently ignored as both Vcd and Fst do not support them, as would need "X" dump
break;
case VDumpCtlType::ON:
// Currently ignored as $dumpoff is also ignored
break;
default: nodep->v3fatalSrc("Bad case, unexpected " << nodep->ctlType().ascii());
}
}
virtual void visit(AstScopeName* nodep) VL_OVERRIDE { virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
// For use under AstCCalls for dpiImports. ScopeNames under // For use under AstCCalls for dpiImports. ScopeNames under
// displays are handled in AstDisplay // displays are handled in AstDisplay
@ -2110,8 +2148,16 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
void EmitCImp::emitDestructorImp(AstNodeModule* modp) { void EmitCImp::emitDestructorImp(AstNodeModule* modp) {
puts("\n"); puts("\n");
puts(prefixNameProtect(modp) + "::~" + prefixNameProtect(modp) + "() {\n"); puts(prefixNameProtect(modp) + "::~" + prefixNameProtect(modp) + "() {\n");
if (modp->isTop() && v3Global.opt.mtasks()) { if (modp->isTop()) {
puts("delete __Vm_threadPoolp; __Vm_threadPoolp = NULL;\n"); if (v3Global.opt.mtasks()) {
puts("delete __Vm_threadPoolp; __Vm_threadPoolp = NULL;\n");
}
// Call via function in __Trace.cpp as this .cpp file does not have trace header
if (v3Global.needTraceDumper()) {
puts("#ifdef VM_TRACE\n");
puts("if (VL_UNLIKELY(__VlSymsp->__Vm_dumperp)) _traceDumpClose();\n");
puts("#endif // VM_TRACE\n");
}
} }
emitTextSection(AstType::atScDtor); emitTextSection(AstType::atScDtor);
if (modp->isTop()) puts("delete __VlSymsp; __VlSymsp=NULL;\n"); if (modp->isTop()) puts("delete __VlSymsp; __VlSymsp=NULL;\n");
@ -2304,7 +2350,7 @@ void EmitCImp::emitSettleLoop(const std::string& eval_call, bool initial) {
} }
void EmitCImp::emitWrapEval(AstNodeModule* modp) { void EmitCImp::emitWrapEval(AstNodeModule* modp) {
puts("\nvoid " + prefixNameProtect(modp) + "::eval() {\n"); puts("\nvoid " + prefixNameProtect(modp) + "::eval_step() {\n");
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate " + prefixNameProtect(modp) puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate " + prefixNameProtect(modp)
+ "::eval\\n\"); );\n"); + "::eval\\n\"); );\n");
puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n"); puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
@ -2316,6 +2362,15 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
putsDecoration("// Initialize\n"); putsDecoration("// Initialize\n");
puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) " puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) "
+protect("_eval_initial_loop")+"(vlSymsp);\n"); +protect("_eval_initial_loop")+"(vlSymsp);\n");
if (v3Global.opt.trace()) {
puts("#ifdef VM_TRACE\n");
putsDecoration("// Tracing\n");
// SystemC's eval loop deals with calling trace, not us
if (v3Global.needTraceDumper() && !optSystemC()) {
puts("if (VL_UNLIKELY(vlSymsp->__Vm_dumperp)) _traceDump();\n");
}
puts("#endif // VM_TRACE\n");
}
if (v3Global.opt.inhibitSim()) { if (v3Global.opt.inhibitSim()) {
puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n"); puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n");
} }
@ -2377,6 +2432,21 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
puts("}\n"); puts("}\n");
splitSizeInc(10); splitSizeInc(10);
//
if (v3Global.needTraceDumper() && !optSystemC()) {
puts("\nvoid " + prefixNameProtect(modp) + "::eval_end_step() {\n");
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+eval_end_step " + prefixNameProtect(modp)
+ "::eval_end_step\\n\"); );\n");
puts("#ifdef VM_TRACE\n");
puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
puts(EmitCBaseVisitor::symTopAssign()+"\n");
putsDecoration("// Tracing\n");
// SystemC's eval loop deals with calling trace, not us
puts("if (VL_UNLIKELY(vlSymsp->__Vm_dumperp)) _traceDump();\n");
puts("#endif // VM_TRACE\n");
puts("}\n");
}
// //
puts("\nvoid " + prefixNameProtect(modp) + "::" + protect("_eval_initial_loop") + "(" puts("\nvoid " + prefixNameProtect(modp) + "::" + protect("_eval_initial_loop") + "("
+ EmitCBaseVisitor::symClassVar() + ") {\n"); + EmitCBaseVisitor::symClassVar() + ") {\n");
@ -2693,11 +2763,11 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
ofp()->putsPrivate(!modp->isTop()); // private: unless top ofp()->putsPrivate(!modp->isTop()); // private: unless top
puts(symClassName()+"* __VlSymsp; // Symbol table\n"); puts(symClassName()+"* __VlSymsp; // Symbol table\n");
ofp()->putsPrivate(false); // public: ofp()->putsPrivate(false); // public:
if (modp->isTop() && v3Global.opt.inhibitSim()) { if (modp->isTop()) {
puts("bool __Vm_inhibitSim; ///< Set true to disable evaluation of module\n"); if (v3Global.opt.inhibitSim()) {
} puts("bool __Vm_inhibitSim; ///< Set true to disable evaluation of module\n");
if (modp->isTop() && v3Global.opt.mtasks()) { }
emitMTaskState(); if (v3Global.opt.mtasks()) emitMTaskState();
} }
emitCoverageDecl(modp); // may flip public/private emitCoverageDecl(modp); // may flip public/private
@ -2775,14 +2845,26 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
if (modp->isTop()) { if (modp->isTop()) {
puts("\n// API METHODS\n"); puts("\n// API METHODS\n");
string callEvalEndStep
= (v3Global.needTraceDumper() && !optSystemC()) ? "eval_end_step(); " : "";
if (optSystemC()) ofp()->putsPrivate(true); ///< eval() is invoked by our sensitive() calls. if (optSystemC()) ofp()->putsPrivate(true); ///< eval() is invoked by our sensitive() calls.
else puts("/// Evaluate the model. Application must call when inputs change.\n"); if (!optSystemC()) puts("/// Evaluate the model. Application must call when inputs change.\n");
puts("void eval();\n"); puts("void eval() { eval_step(); " + callEvalEndStep + "}\n");
if (!optSystemC()) puts("/// Evaluate when calling multiple units/models per time step.\n");
puts("void eval_step();\n");
if (!optSystemC()) {
puts("/// Evaluate at end of a timestep for tracing, when using eval_step().\n");
puts("/// Application must call after all eval() and before time changes.\n");
puts("void eval_end_step()");
if (callEvalEndStep == "") puts(" {}\n");
else puts(";\n");
}
ofp()->putsPrivate(false); // public: ofp()->putsPrivate(false); // public:
if (!optSystemC()) puts("/// Simulation complete, run final blocks. Application must call on completion.\n"); if (!optSystemC()) puts("/// Simulation complete, run final blocks. Application must call on completion.\n");
puts("void final();\n"); puts("void final();\n");
if (v3Global.opt.inhibitSim()) { if (v3Global.opt.inhibitSim()) {
puts("void inhibitSim(bool flag) { __Vm_inhibitSim=flag; } ///< Set true to disable evaluation of module\n"); puts("/// Disable evaluation of module (e.g. turn off)\n");
puts("void inhibitSim(bool flag) { __Vm_inhibitSim = flag; }\n");
} }
} }
@ -2791,6 +2873,9 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
ofp()->putsPrivate(true); // private: ofp()->putsPrivate(true); // private:
puts("static void "+protect("_eval_initial_loop") puts("static void "+protect("_eval_initial_loop")
+"("+EmitCBaseVisitor::symClassVar()+");\n"); +"("+EmitCBaseVisitor::symClassVar()+");\n");
if (v3Global.needTraceDumper() && !optSystemC()) puts("void _traceDump();");
if (v3Global.needTraceDumper()) puts("void _traceDumpOpen();");
if (v3Global.needTraceDumper()) puts("void _traceDumpClose();");
} }
if (!VN_IS(modp, Class)) { if (!VN_IS(modp, Class)) {
@ -2978,14 +3063,43 @@ class EmitCTrace : EmitCStmts {
void emitTraceHeader() { void emitTraceHeader() {
// Includes // Includes
puts("#include \""+v3Global.opt.traceSourceName()+"_c.h\"\n"); puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n");
puts("#include \""+ symClassName() +".h\"\n"); puts("#include \"" + symClassName() + ".h\"\n");
puts("\n"); puts("\n");
} }
void emitTraceSlow() { void emitTraceSlow() {
puts("\n//======================\n\n"); puts("\n//======================\n\n");
if (v3Global.needTraceDumper() && !optSystemC()) {
puts("void " + topClassName() + "::_traceDump() {\n");
// Caller checked for __Vm_dumperp non-NULL
puts( "VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n");
puts( "__VlSymsp->__Vm_dumperp->dump(VL_TIME_Q());\n");
puts("}\n");
splitSizeInc(10);
}
if (v3Global.needTraceDumper()) {
puts("void " + topClassName() + "::_traceDumpOpen() {\n");
puts( "if (VL_UNLIKELY(!__VlSymsp->__Vm_dumperp)) {\n");
puts( "VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n");
puts( "__VlSymsp->__Vm_dumperp = new " + v3Global.opt.traceClassLang() + "();\n");
puts( "const char* cp = vl_dumpctl_filenamep();\n");
puts( "trace(__VlSymsp->__Vm_dumperp, 0, 0);\n");
puts( "__VlSymsp->__Vm_dumperp->open(vl_dumpctl_filenamep());\n");
puts( "}\n");
puts("}\n");
splitSizeInc(10);
puts("void " + topClassName() + "::_traceDumpClose() {\n");
// Caller checked for __Vm_dumperp non-NULL
puts( "VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n");
puts( "delete __VlSymsp->__Vm_dumperp; __VlSymsp->__Vm_dumperp = NULL;\n");
puts("}\n");
splitSizeInc(10);
}
puts("void "+topClassName()+"::trace("); puts("void "+topClassName()+"::trace(");
puts(v3Global.opt.traceClassBase()+"C* tfp, int, int) {\n"); puts(v3Global.opt.traceClassBase()+"C* tfp, int, int) {\n");
puts( "tfp->spTrace()->addCallback(" puts( "tfp->spTrace()->addCallback("

View File

@ -66,6 +66,11 @@ class EmitCInlines : EmitCBaseVisitor {
v3Global.needHeavy(true); v3Global.needHeavy(true);
iterateChildren(nodep); iterateChildren(nodep);
} }
virtual void visit(AstDumpCtl* nodep) VL_OVERRIDE {
if (v3Global.opt.trace()) v3Global.needTraceDumper(true);
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstPutcN* nodep) VL_OVERRIDE { virtual void visit(AstPutcN* nodep) VL_OVERRIDE {
v3Global.needHeavy(true); v3Global.needHeavy(true);
iterateChildren(nodep); iterateChildren(nodep);

View File

@ -160,13 +160,13 @@ class CMakeEmitter {
} }
if (v3Global.opt.trace()) { if (v3Global.opt.trace()) {
global.push_back("${VERILATOR_ROOT}/include/" global.push_back("${VERILATOR_ROOT}/include/"
+ v3Global.opt.traceSourceName()+"_c.cpp"); + v3Global.opt.traceSourceBase() + "_c.cpp");
if (v3Global.opt.systemC()) { if (v3Global.opt.systemC()) {
if (v3Global.opt.traceFormat() != TraceFormat::VCD) { if (v3Global.opt.traceFormat() != TraceFormat::VCD) {
v3error("Unsupported: This trace format is not supported in SystemC, use VCD format."); v3error("Unsupported: This trace format is not supported in SystemC, use VCD format.");
} }
global.push_back("${VERILATOR_ROOT}/include/" global.push_back("${VERILATOR_ROOT}/include/"
+ v3Global.opt.traceSourceName()+"_sc.cpp"); + v3Global.opt.traceSourceLang() + ".cpp");
} }
} }
if (v3Global.opt.mtasks()) { if (v3Global.opt.mtasks()) {

View File

@ -417,6 +417,13 @@ void EmitCSyms::emitSymHdr() {
puts("\n// LOCAL STATE\n"); puts("\n// LOCAL STATE\n");
puts("const char* __Vm_namep;\n"); // Must be before subcells, as constructor order needed before _vlCoverInsert. puts("const char* __Vm_namep;\n"); // Must be before subcells, as constructor order needed before _vlCoverInsert.
if (v3Global.needTraceDumper()) {
// __Vm_dumperp is local, otherwise we wouldn't know what design's eval()
// should call a global dumpperp
puts("VerilatedMutex __Vm_dumperMutex; // Protect __Vm_dumperp\n");
puts(v3Global.opt.traceClassLang()
+ "* __Vm_dumperp VL_GUARDED_BY(__Vm_dumperMutex); /// Trace class for $dump*\n");
}
if (v3Global.opt.trace()) { if (v3Global.opt.trace()) {
puts("bool __Vm_activity; ///< Used by trace routines to determine change occurred\n"); puts("bool __Vm_activity; ///< Used by trace routines to determine change occurred\n");
} }
@ -582,10 +589,9 @@ void EmitCSyms::emitSymImp() {
puts("\n// FUNCTIONS\n"); puts("\n// FUNCTIONS\n");
puts(symClassName()+"::"+symClassName()+"("+topClassName()+"* topp, const char* namep)\n"); puts(symClassName()+"::"+symClassName()+"("+topClassName()+"* topp, const char* namep)\n");
puts(" // Setup locals\n"); puts(" // Setup locals\n");
puts(" : __Vm_namep(namep)\n"); // No leak, as we get destroyed when the top is destroyed puts(" : __Vm_namep(namep)\n"); // No leak, as gets destroyed when the top is destroyed
if (v3Global.opt.trace()) { if (v3Global.needTraceDumper()) puts(" , __Vm_dumperp(NULL)\n");
puts(" , __Vm_activity(false)\n"); if (v3Global.opt.trace()) puts(" , __Vm_activity(false)\n");
}
puts(" , __Vm_didInit(false)\n"); puts(" , __Vm_didInit(false)\n");
puts(" // Setup submodule names\n"); puts(" // Setup submodule names\n");
char comma = ','; char comma = ',';

View File

@ -85,12 +85,12 @@ public:
putMakeClassEntry(of, "verilated_cov.cpp"); putMakeClassEntry(of, "verilated_cov.cpp");
} }
if (v3Global.opt.trace()) { if (v3Global.opt.trace()) {
putMakeClassEntry(of, v3Global.opt.traceSourceName()+"_c.cpp"); putMakeClassEntry(of, v3Global.opt.traceSourceBase() + "_c.cpp");
if (v3Global.opt.systemC()) { if (v3Global.opt.systemC()) {
if (v3Global.opt.traceFormat() != TraceFormat::VCD) { if (v3Global.opt.traceFormat() != TraceFormat::VCD) {
v3error("Unsupported: This trace format is not supported in SystemC, use VCD format."); v3error("Unsupported: This trace format is not supported in SystemC, use VCD format.");
} else { } else {
putMakeClassEntry(of, v3Global.opt.traceSourceName()+"_sc.cpp"); putMakeClassEntry(of, v3Global.opt.traceSourceLang() + ".cpp");
} }
} }
} }

View File

@ -71,15 +71,16 @@ inline bool operator==(VWidthMinUsage::en lhs, const VWidthMinUsage& rhs) {
class V3Global { class V3Global {
// Globals // Globals
AstNetlist* m_rootp; // Root of entire netlist AstNetlist* m_rootp; // Root of entire netlist
VWidthMinUsage m_widthMinUsage; // What AstNode::widthMin() is used for VWidthMinUsage m_widthMinUsage; // What AstNode::widthMin() is used for
int m_debugFileNumber; // Number to append to debug files created int m_debugFileNumber; // Number to append to debug files created
bool m_assertDTypesResolved; // Tree should have dtypep()'s bool m_assertDTypesResolved; // Tree should have dtypep()'s
bool m_constRemoveXs; // Const needs to strip any Xs bool m_constRemoveXs; // Const needs to strip any Xs
bool m_needHInlines; // Need __Inlines file bool m_needTraceDumper; // Need __Vm_dumperp in symbols
bool m_needHeavy; // Need verilated_heavy.h include bool m_needHInlines; // Need __Inlines file
bool m_dpi; // Need __Dpi include files bool m_needHeavy; // Need verilated_heavy.h include
bool m_dpi; // Need __Dpi include files
public: public:
// Options // Options
@ -92,6 +93,7 @@ public:
m_widthMinUsage = VWidthMinUsage::LINT_WIDTH; m_widthMinUsage = VWidthMinUsage::LINT_WIDTH;
m_assertDTypesResolved = false; m_assertDTypesResolved = false;
m_constRemoveXs = false; m_constRemoveXs = false;
m_needTraceDumper = false;
m_needHInlines = false; m_needHInlines = false;
m_needHeavy = false; m_needHeavy = false;
m_dpi = false; m_dpi = false;
@ -119,10 +121,12 @@ public:
char digits[100]; sprintf(digits, "%03d", m_debugFileNumber); char digits[100]; sprintf(digits, "%03d", m_debugFileNumber);
return opt.makeDir()+"/"+opt.prefix()+"_"+digits+"_"+nameComment; return opt.makeDir()+"/"+opt.prefix()+"_"+digits+"_"+nameComment;
} }
bool needTraceDumper() const { return m_needTraceDumper; }
void needTraceDumper(bool flag) { m_needTraceDumper = flag; }
bool needHInlines() const { return m_needHInlines; } bool needHInlines() const { return m_needHInlines; }
void needHInlines(bool flag) { m_needHInlines=flag; } void needHInlines(bool flag) { m_needHInlines = flag; }
bool needHeavy() const { return m_needHeavy; } bool needHeavy() const { return m_needHeavy; }
void needHeavy(bool flag) { m_needHeavy=flag; } void needHeavy(bool flag) { m_needHeavy = flag; }
bool dpi() const { return m_dpi; } bool dpi() const { return m_dpi; }
void dpi(bool flag) { m_dpi = flag; } void dpi(bool flag) { m_dpi = flag; }
}; };

View File

@ -467,7 +467,11 @@ class V3Options {
bool oTable() const { return m_oTable; } bool oTable() const { return m_oTable; }
string traceClassBase() const { return m_traceFormat.classBase(); } string traceClassBase() const { return m_traceFormat.classBase(); }
string traceSourceName() const { return m_traceFormat.sourceName(); } string traceClassLang() const { return m_traceFormat.classBase() + (systemC() ? "Sc" : "C"); }
string traceSourceBase() const { return m_traceFormat.sourceName(); }
string traceSourceLang() const {
return m_traceFormat.sourceName() + (systemC() ? "_sc" : "_c");
}
// METHODS (from main) // METHODS (from main)
static string version(); static string version();

View File

@ -2872,6 +2872,11 @@ private:
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
} }
} }
virtual void visit(AstDumpCtl* nodep) VL_OVERRIDE {
assertAtStatement(nodep);
// Just let all arguments seek their natural sizes
userIterateChildren(nodep, WidthVP(SELF, BOTH).p());
}
virtual void visit(AstFOpen* nodep) VL_OVERRIDE { virtual void visit(AstFOpen* nodep) VL_OVERRIDE {
// Although a system function in IEEE, here a statement which sets the file pointer (MCD) // Although a system function in IEEE, here a statement which sets the file pointer (MCD)
assertAtStatement(nodep); assertAtStatement(nodep);

View File

@ -197,6 +197,19 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$cos" { FL; return yD_COS; } "$cos" { FL; return yD_COS; }
"$cosh" { FL; return yD_COSH; } "$cosh" { FL; return yD_COSH; }
"$display" { FL; return yD_DISPLAY; } "$display" { FL; return yD_DISPLAY; }
"$dumpall" { FL; return yD_DUMPALL; }
"$dumpfile" { FL; return yD_DUMPFILE; }
"$dumpflush" { FL; return yD_DUMPFLUSH; }
"$dumplimit" { FL; return yD_DUMPLIMIT; }
"$dumpoff" { FL; return yD_DUMPOFF; }
"$dumpon" { FL; return yD_DUMPON; }
"$dumpports" { FL; return yD_DUMPPORTS; }
"$dumpportsall" { FL; return yD_DUMPALL; }
"$dumpportsflush" { FL; return yD_DUMPFLUSH; }
"$dumpportslimit" { FL; return yD_DUMPLIMIT; }
"$dumpportsoff" { FL; return yD_DUMPOFF; }
"$dumpportson" { FL; return yD_DUMPON; }
"$dumpvars" { FL; return yD_DUMPVARS; }
"$exp" { FL; return yD_EXP; } "$exp" { FL; return yD_EXP; }
"$fclose" { FL; return yD_FCLOSE; } "$fclose" { FL; return yD_FCLOSE; }
"$fdisplay" { FL; return yD_FDISPLAY; } "$fdisplay" { FL; return yD_FDISPLAY; }
@ -208,10 +221,10 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$floor" { FL; return yD_FLOOR; } "$floor" { FL; return yD_FLOOR; }
"$fopen" { FL; return yD_FOPEN; } "$fopen" { FL; return yD_FOPEN; }
"$fread" { FL; return yD_FREAD; } "$fread" { FL; return yD_FREAD; }
"$frewind" { FL; return yD_FREWIND; }
"$fscanf" { FL; return yD_FSCANF; } "$fscanf" { FL; return yD_FSCANF; }
"$fseek" { FL; return yD_FSEEK; } "$fseek" { FL; return yD_FSEEK; }
"$ftell" { FL; return yD_FTELL; } "$ftell" { FL; return yD_FTELL; }
"$frewind" { FL; return yD_FREWIND; }
"$fullskew" { FL; return yaTIMINGSPEC; } "$fullskew" { FL; return yaTIMINGSPEC; }
"$fwrite" { FL; return yD_FWRITE; } "$fwrite" { FL; return yD_FWRITE; }
"$hold" { FL; return yaTIMINGSPEC; } "$hold" { FL; return yaTIMINGSPEC; }

View File

@ -553,6 +553,14 @@ class AstSenTree;
%token<fl> yD_COUNTONES "$countones" %token<fl> yD_COUNTONES "$countones"
%token<fl> yD_DIMENSIONS "$dimensions" %token<fl> yD_DIMENSIONS "$dimensions"
%token<fl> yD_DISPLAY "$display" %token<fl> yD_DISPLAY "$display"
%token<fl> yD_DUMPALL "$dumpall"
%token<fl> yD_DUMPFILE "$dumpfile"
%token<fl> yD_DUMPFLUSH "$dumpflush"
%token<fl> yD_DUMPLIMIT "$dumplimit"
%token<fl> yD_DUMPOFF "$dumpoff"
%token<fl> yD_DUMPON "$dumpon"
%token<fl> yD_DUMPPORTS "$dumpports"
%token<fl> yD_DUMPVARS "$dumpvars"
%token<fl> yD_ERROR "$error" %token<fl> yD_ERROR "$error"
%token<fl> yD_EXP "$exp" %token<fl> yD_EXP "$exp"
%token<fl> yD_FATAL "$fatal" %token<fl> yD_FATAL "$fatal"
@ -3154,8 +3162,30 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($<fl>1, *$1, $3); | yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($<fl>1, *$1, $3);
GRAMMARP->argWrapList(VN_CAST($$, TaskRef)); } GRAMMARP->argWrapList(VN_CAST($$, TaskRef)); }
// //
| yD_DUMPPORTS '(' idDotted ',' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FILE, $5); DEL($3);
$$->addNext(new AstDumpCtl($<fl>1, VDumpCtlType::VARS,
new AstConst($<fl>1, 1))); }
| yD_DUMPPORTS '(' ',' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FILE, $4);
$$->addNext(new AstDumpCtl($<fl>1, VDumpCtlType::VARS,
new AstConst($<fl>1, 1))); }
| yD_DUMPFILE '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FILE, $3); }
| yD_DUMPVARS parenE { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::VARS,
new AstConst($<fl>1, 0)); }
| yD_DUMPVARS '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::VARS, $3); }
| yD_DUMPVARS '(' expr ',' idDotted ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::VARS, $3); DEL($5); }
| yD_DUMPALL parenE { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::ALL); }
| yD_DUMPALL '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::ALL); DEL($3); }
| yD_DUMPFLUSH parenE { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FLUSH); }
| yD_DUMPFLUSH '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FLUSH); DEL($3); }
| yD_DUMPLIMIT '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::LIMIT, $3); }
| yD_DUMPLIMIT '(' expr ',' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::LIMIT, $3); DEL($5); }
| yD_DUMPOFF parenE { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::OFF); }
| yD_DUMPOFF '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::OFF); DEL($3); }
| yD_DUMPON parenE { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::ON); }
| yD_DUMPON '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::ON); DEL($3); }
//
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); } | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1, $3); } | yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1, $3); }
// //
| yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); } | yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); }
| yD_FFLUSH parenE { $$ = NULL; BBUNSUP($1, "Unsupported: $fflush of all handles does not map to C++."); } | yD_FFLUSH parenE { $$ = NULL; BBUNSUP($1, "Unsupported: $fflush of all handles does not map to C++."); }

View File

@ -64,15 +64,15 @@ int main(int argc, char* argv[]) {
vluint64_t firstUsage = get_memory_usage(); vluint64_t firstUsage = get_memory_usage();
// Warmup phase // Warmup phase
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 10; i++) {
make_and_destroy(); make_and_destroy();
} }
firstUsage = get_memory_usage(); firstUsage = get_memory_usage();
printf("Memory size %" VL_PRI64 "d bytes\n", firstUsage); printf("Memory size %" VL_PRI64 "d bytes\n", firstUsage);
int loops = 100*1000; int loops = 10;
for (int left = loops; left > 0;) { for (int left = loops; left > 0;) {
for (int j = 0; j < 1000; ++j, --left) { for (int j = 0; j < 1; ++j, --left) {
make_and_destroy(); make_and_destroy();
} }
} }

View File

@ -0,0 +1,2 @@
%Warning: $dumpvar ignored as not proceeded by $dumpfile
*-* All Finished *-*

View File

@ -0,0 +1,22 @@
#!/usr/bin/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.
scenarios(vlt => 1);
compile(
verilator_flags2 => ["-trace"],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,13 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2020 by Wilson Snyder.
module t(/*AUTOARG*/);
initial begin
// Check error when this missing: $dumpfile("/should/not/be/opened");
$dumpvars;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,2 @@
-Info: t/t_trace_flag_off.v:9: $dumpvar ignored, as Verilated without --trace
*-* All Finished *-*

View File

@ -0,0 +1,22 @@
#!/usr/bin/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.
# Test that without --trace we get a message when turning on traces
scenarios(vlt => 1);
compile(
);
execute(
expect_filename => $Self->{golden_filename},
fails => 0,
);
ok(1);
1;

View File

@ -0,0 +1,13 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2020 by Wilson Snyder.
module t(/*AUTOARG*/);
initial begin
$dumpfile("/should/not/be/opened");
$dumpvars();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -3,6 +3,9 @@
// This file ONLY is placed into the Public Domain, for any use, // This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2020 by Wilson Snyder. // without warranty, 2020 by Wilson Snyder.
`define CONCAT(a, b) a``b
`define STRINGIFY(x) `"x`"
module t (/*AUTOARG*/ module t (/*AUTOARG*/
// Inputs // Inputs
clk clk
@ -15,11 +18,55 @@ module t (/*AUTOARG*/
sub sub (); sub sub ();
// verilator tracing_off
string filename;
// verilator tracing_on
initial begin
`ifdef TEST_FST
filename = {`STRINGIFY(`TEST_OBJ_DIR), "/simx.fst"};
`else
filename = {`STRINGIFY(`TEST_OBJ_DIR), "/simx.vcd"};
`endif
`ifdef TEST_DUMP
$dumpfile(filename);
$dumpvars(0, top);
$dumplimit(10 * 1024 * 1024);
`elsif TEST_DUMPPORTS
$dumpports(top, filename);
$dumpportslimit(10 * 1024 * 1024, filename);
`endif
end
always @ (posedge clk) begin always @ (posedge clk) begin
if (cyc != 0) begin if (cyc != 0) begin
cyc <= cyc + 1; cyc <= cyc + 1;
c_trace_on <= cyc + 2; c_trace_on <= cyc + 2;
if (cyc == 10) begin if (cyc == 3) begin
`ifdef TEST_DUMP
$dumpoff;
`elsif TEST_DUMPPORTS
$dumpportsoff(filename);
`endif
end
else if (cyc == 5) begin
`ifdef TEST_DUMP
$dumpall;
$dumpflush;
`elsif TEST_DUMPPORTS
$dumpportsall(filename);
$dumpportsflush(filename);
`endif
end
else if (cyc == 7) begin
`ifdef TEST_DUMP
$dumpon;
`elsif TEST_DUMPPORTS
$dumpportson(filename);
`endif
end
else if (cyc == 10) begin
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
end end

View File

@ -9,7 +9,13 @@
#include VM_PREFIX_INCLUDE #include VM_PREFIX_INCLUDE
#include "Vt_trace_two_b.h" #include "Vt_trace_two_b.h"
#include "verilated.h" #include "verilated.h"
#include "verilated_vcd_c.h" #ifdef TEST_HDR_TRACE
# ifdef TEST_FST
# include "verilated_fst_c.h"
# else
# include "verilated_vcd_c.h"
# endif
#endif
// Compile in place // Compile in place
#include "Vt_trace_two_b.cpp" #include "Vt_trace_two_b.cpp"
@ -26,18 +32,28 @@ int main(int argc, char** argv, char** env) {
double sim_time = 1100; double sim_time = 1100;
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
Verilated::debug(0); Verilated::debug(0);
Verilated::traceEverOn(true);
srand48(5); srand48(5);
ap = new VM_PREFIX("topa"); ap = new VM_PREFIX("topa");
bp = new Vt_trace_two_b("topb"); bp = new Vt_trace_two_b("topb");
ap->eval(); ap->eval_step();
bp->eval(); bp->eval_step();
ap->eval_end_step();
bp->eval_end_step();
#if VM_TRACE #ifdef TEST_HDR_TRACE
Verilated::traceEverOn(true); Verilated::traceEverOn(true);
# ifdef TEST_FST
VerilatedFstC* tfp = new VerilatedFstC;
ap->trace(tfp, 99);
bp->trace(tfp, 99);
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.fst");
# else
VerilatedVcdC* tfp = new VerilatedVcdC; VerilatedVcdC* tfp = new VerilatedVcdC;
ap->trace(tfp, 99); ap->trace(tfp, 99);
bp->trace(tfp, 99); bp->trace(tfp, 99);
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd"); tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
# endif
if (tfp) tfp->dump(main_time); if (tfp) tfp->dump(main_time);
#endif #endif
{ {
@ -48,11 +64,13 @@ int main(int argc, char** argv, char** env) {
while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) { while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {
ap->clk = !ap->clk; ap->clk = !ap->clk;
bp->clk = ap->clk; bp->clk = ap->clk;
ap->eval(); ap->eval_step();
bp->eval(); bp->eval_step();
#if VM_TRACE ap->eval_end_step();
bp->eval_end_step();
#ifdef TEST_HDR_TRACE
if (tfp) tfp->dump(main_time); if (tfp) tfp->dump(main_time);
#endif // VM_TRACE #endif
main_time += 5; main_time += 5;
} }
if (!Verilated::gotFinish()) { if (!Verilated::gotFinish()) {
@ -60,9 +78,9 @@ int main(int argc, char** argv, char** env) {
} }
ap->final(); ap->final();
bp->final(); bp->final();
#if VM_TRACE #ifdef TEST_HDR_TRACE
if (tfp) tfp->close(); if (tfp) tfp->close();
#endif // VM_TRACE #endif
VL_DO_DANGLING(delete ap, ap); VL_DO_DANGLING(delete ap, ap);
VL_DO_DANGLING(delete bp, bp); VL_DO_DANGLING(delete bp, bp);

View File

@ -0,0 +1,102 @@
$version Generated by VerilatedVcd $end
$date Sun Mar 1 20:48:56 2020
$end
$timescale 1ns $end
$scope module topa $end
$var wire 1 3 clk $end
$scope module t $end
$var wire 32 + c_trace_on [31:0] $end
$var wire 1 3 clk $end
$var wire 32 # cyc [31:0] $end
$scope module sub $end
$var wire 32 ; inside_sub_a [31:0] $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
b00000000000000000000000000000001 #
b00000000000000000000000000000000 +
03
b00000000000000000000000000000001 ;
#0
#10
#10
b00000000000000000000000000000010 #
b00000000000000000000000000000011 +
13
#15
#15
03
#20
#20
b00000000000000000000000000000011 #
b00000000000000000000000000000100 +
13
#25
#25
03
#30
#30
b00000000000000000000000000000100 #
b00000000000000000000000000000101 +
13
#35
#35
03
#40
#40
b00000000000000000000000000000101 #
b00000000000000000000000000000110 +
13
#45
#45
03
#50
#50
b00000000000000000000000000000110 #
b00000000000000000000000000000111 +
13
#55
#55
03
#60
#60
b00000000000000000000000000000111 #
b00000000000000000000000000001000 +
13
#65
#65
03
#70
#70
b00000000000000000000000000001000 #
b00000000000000000000000000001001 +
13
#75
#75
03
#80
#80
b00000000000000000000000000001001 #
b00000000000000000000000000001010 +
13
#85
#85
03
#90
#90
b00000000000000000000000000001010 #
b00000000000000000000000000001011 +
13
#95
#95
03
#100
#100
b00000000000000000000000000001011 #
b00000000000000000000000000001100 +
13

View File

@ -0,0 +1,40 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2020 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.
# Test tracing with two models instanced
scenarios(vlt_all => 1);
top_filename("t_trace_two_a.v");
compile(
make_main => 0,
verilator_make_gmake => 0,
top_filename => 't_trace_two_b.v',
VM_PREFIX => 'Vt_trace_two_b',
verilator_flags2 => ['-trace'],
);
compile(
make_main => 0,
top_filename => 't_trace_two_a.v',
verilator_flags2 => ['-exe', '-trace', "$Self->{t_dir}/t_trace_two_cc.cpp"],
v_flags2 => ['+define+TEST_DUMP'],
);
execute(
check_finished => 1,
);
if ($Self->{vlt_all}) {
file_grep("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename});
}
ok(1);
1;

View File

@ -0,0 +1,81 @@
$version Generated by VerilatedVcd $end
$date Sun Mar 1 20:49:13 2020
$end
$timescale 1ps $end
$scope module topa $end
$scope module t $end
$var wire 32 3 c_trace_on [31:0] $end
$var wire 1 # clk $end
$var wire 32 + cyc [31:0] $end
$scope module sub $end
$var wire 32 ; inside_sub_a [31:0] $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
0#
b00000000000000000000000000000001 +
b00000000000000000000000000000000 3
b00000000000000000000000000000001 ;
#10000
1#
b00000000000000000000000000000010 +
b00000000000000000000000000000011 3
#15000
0#
#20000
1#
b00000000000000000000000000000011 +
b00000000000000000000000000000100 3
#25000
0#
#30000
1#
b00000000000000000000000000000100 +
b00000000000000000000000000000101 3
#35000
0#
#40000
1#
b00000000000000000000000000000101 +
b00000000000000000000000000000110 3
#45000
0#
#50000
1#
b00000000000000000000000000000110 +
b00000000000000000000000000000111 3
#55000
0#
#60000
1#
b00000000000000000000000000000111 +
b00000000000000000000000000001000 3
#65000
0#
#70000
1#
b00000000000000000000000000001000 +
b00000000000000000000000000001001 3
#75000
0#
#80000
1#
b00000000000000000000000000001001 +
b00000000000000000000000000001010 3
#85000
0#
#90000
1#
b00000000000000000000000000001010 +
b00000000000000000000000000001011 3
#95000
0#
#100000
1#
b00000000000000000000000000001011 +
b00000000000000000000000000001100 3

View File

@ -0,0 +1,45 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2020 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(simulator => 1);
if (!$Self->have_sc) {
skip("No SystemC installed");
}
else {
top_filename("t_trace_two_a.v");
compile(
make_main => 0,
verilator_make_gmake => 0,
top_filename => 't_trace_two_b.v',
VM_PREFIX => 'Vt_trace_two_b',
verilator_flags2 => ['-sc -trace'],
);
compile(
make_main => 0,
top_filename => 't_trace_two_a.v',
verilator_flags2 => ['-sc', '-exe', '-trace',
"$Self->{t_dir}/t_trace_two_sc.cpp"],
v_flags2 => ['+define+TEST_DUMP'],
);
execute(
check_finished => 1,
);
if ($Self->{vlt_all}) {
file_grep("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename});
}
}
ok(1);
1;

View File

@ -0,0 +1,83 @@
$date
Sun Mar 1 21:31:56 2020
$end
$version
fstWriter
$end
$timescale
1ns
$end
$scope module topa $end
$var wire 1 ! clk $end
$scope module t $end
$var wire 1 ! clk $end
$var integer 32 " cyc $end
$var integer 32 # c_trace_on $end
$scope module sub $end
$var integer 32 $ inside_sub_a $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
#0
0!
#10
1!
b00000000000000000000000000000011 #
b00000000000000000000000000000010 "
#15
0!
#20
1!
b00000000000000000000000000000011 "
b00000000000000000000000000000100 #
#25
0!
#30
1!
b00000000000000000000000000000101 #
b00000000000000000000000000000100 "
#35
0!
#40
1!
b00000000000000000000000000000101 "
b00000000000000000000000000000110 #
#45
0!
#50
1!
b00000000000000000000000000000111 #
b00000000000000000000000000000110 "
#55
0!
#60
1!
b00000000000000000000000000000111 "
b00000000000000000000000000001000 #
#65
0!
#70
1!
b00000000000000000000000000001001 #
b00000000000000000000000000001000 "
#75
0!
#80
1!
b00000000000000000000000000001001 "
b00000000000000000000000000001010 #
#85
0!
#90
1!
b00000000000000000000000000001011 #
b00000000000000000000000000001010 "
#95
0!
#100
1!
b00000000000000000000000000001011 "
b00000000000000000000000000001100 #

View File

@ -0,0 +1,42 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2020 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.
# Test tracing with two models instanced
scenarios(vlt_all => 1);
top_filename("t_trace_two_a.v");
compile(
make_main => 0,
verilator_make_gmake => 0,
top_filename => 't_trace_two_b.v',
VM_PREFIX => 'Vt_trace_two_b',
verilator_flags2 => ['--trace-fst-thread -DTEST_FST'],
);
compile(
make_main => 0,
top_filename => 't_trace_two_a.v',
verilator_flags2 => ['-exe', '--trace-fst-thread',
'-DTEST_FST',
"$Self->{t_dir}/t_trace_two_cc.cpp"],
v_flags2 => ['+define+TEST_DUMP'],
);
execute(
check_finished => 1,
);
if ($Self->{vlt_all}) {
fst2vcd($Self->trace_filename, "$Self->{obj_dir}/simx-fst2vcd.vcd");
vcd_identical("$Self->{obj_dir}/simx-fst2vcd.vcd", $Self->{golden_filename});
}
ok(1);
1;

View File

@ -23,7 +23,8 @@ compile(
compile( compile(
make_main => 0, make_main => 0,
top_filename => 't_trace_two_a.v', top_filename => 't_trace_two_a.v',
verilator_flags2 => ['-exe', '-trace', "$Self->{t_dir}/t_trace_two_hdr_cc.cpp"], make_flags => 'CPPFLAGS_ADD=-DTEST_HDR_TRACE=1',
verilator_flags2 => ['-exe', '-trace', "$Self->{t_dir}/t_trace_two_cc.cpp"],
); );
execute( execute(

View File

@ -26,8 +26,9 @@ else {
compile( compile(
make_main => 0, make_main => 0,
top_filename => 't_trace_two_a.v', top_filename => 't_trace_two_a.v',
make_flags => 'CPPFLAGS_ADD=-DTEST_HDR_TRACE',
verilator_flags2 => ['-sc', '-exe', '-trace', verilator_flags2 => ['-sc', '-exe', '-trace',
"$Self->{t_dir}/t_trace_two_hdr_sc.cpp"], "$Self->{t_dir}/t_trace_two_sc.cpp"],
); );
execute( execute(

Binary file not shown.

View File

@ -0,0 +1,42 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2020 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.
# Test tracing with two models instanced
scenarios(vlt_all => 1);
top_filename("t_trace_two_a.v");
compile(
make_main => 0,
verilator_make_gmake => 0,
top_filename => 't_trace_two_b.v',
VM_PREFIX => 'Vt_trace_two_b',
verilator_flags2 => ['--trace-fst-thread'],
);
compile(
make_main => 0,
top_filename => 't_trace_two_a.v',
make_flags => 'CPPFLAGS_ADD="-DTEST_HDR_TRACE=1 -DTEST_FST=1"',
verilator_flags2 => ['-exe', '--trace-fst-thread',
'-DTEST_FST',
"$Self->{t_dir}/t_trace_two_cc.cpp"],
);
execute(
check_finished => 1,
);
if ($Self->{vlt_all}) {
fst2vcd($Self->trace_filename, "$Self->{obj_dir}/simx-fst2vcd.vcd");
vcd_identical("$Self->{obj_dir}/simx-fst2vcd.vcd", $Self->{golden_filename});
}
ok(1);
1;

View File

@ -0,0 +1,102 @@
$version Generated by VerilatedVcd $end
$date Sun Mar 1 21:32:13 2020
$end
$timescale 1ns $end
$scope module topa $end
$var wire 1 3 clk $end
$scope module t $end
$var wire 32 + c_trace_on [31:0] $end
$var wire 1 3 clk $end
$var wire 32 # cyc [31:0] $end
$scope module sub $end
$var wire 32 ; inside_sub_a [31:0] $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
b00000000000000000000000000000001 #
b00000000000000000000000000000000 +
03
b00000000000000000000000000000001 ;
#0
#10
#10
b00000000000000000000000000000010 #
b00000000000000000000000000000011 +
13
#15
#15
03
#20
#20
b00000000000000000000000000000011 #
b00000000000000000000000000000100 +
13
#25
#25
03
#30
#30
b00000000000000000000000000000100 #
b00000000000000000000000000000101 +
13
#35
#35
03
#40
#40
b00000000000000000000000000000101 #
b00000000000000000000000000000110 +
13
#45
#45
03
#50
#50
b00000000000000000000000000000110 #
b00000000000000000000000000000111 +
13
#55
#55
03
#60
#60
b00000000000000000000000000000111 #
b00000000000000000000000000001000 +
13
#65
#65
03
#70
#70
b00000000000000000000000000001000 #
b00000000000000000000000000001001 +
13
#75
#75
03
#80
#80
b00000000000000000000000000001001 #
b00000000000000000000000000001010 +
13
#85
#85
03
#90
#90
b00000000000000000000000000001010 #
b00000000000000000000000000001011 +
13
#95
#95
03
#100
#100
b00000000000000000000000000001011 #
b00000000000000000000000000001100 +
13

View File

@ -0,0 +1,40 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2020 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.
# Test tracing with two models instanced
scenarios(vlt_all => 1);
top_filename("t_trace_two_a.v");
compile(
make_main => 0,
verilator_make_gmake => 0,
top_filename => 't_trace_two_b.v',
VM_PREFIX => 'Vt_trace_two_b',
verilator_flags2 => ['-trace'],
);
compile(
make_main => 0,
top_filename => 't_trace_two_a.v',
verilator_flags2 => ['-exe', '-trace', "$Self->{t_dir}/t_trace_two_cc.cpp"],
v_flags2 => ['+define+TEST_DUMPPORTS'],
);
execute(
check_finished => 1,
);
if ($Self->{vlt_all}) {
file_grep("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename});
}
ok(1);
1;

View File

@ -0,0 +1,81 @@
$version Generated by VerilatedVcd $end
$date Sun Mar 1 21:32:22 2020
$end
$timescale 1ps $end
$scope module topa $end
$scope module t $end
$var wire 32 3 c_trace_on [31:0] $end
$var wire 1 # clk $end
$var wire 32 + cyc [31:0] $end
$scope module sub $end
$var wire 32 ; inside_sub_a [31:0] $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
0#
b00000000000000000000000000000001 +
b00000000000000000000000000000000 3
b00000000000000000000000000000001 ;
#10000
1#
b00000000000000000000000000000010 +
b00000000000000000000000000000011 3
#15000
0#
#20000
1#
b00000000000000000000000000000011 +
b00000000000000000000000000000100 3
#25000
0#
#30000
1#
b00000000000000000000000000000100 +
b00000000000000000000000000000101 3
#35000
0#
#40000
1#
b00000000000000000000000000000101 +
b00000000000000000000000000000110 3
#45000
0#
#50000
1#
b00000000000000000000000000000110 +
b00000000000000000000000000000111 3
#55000
0#
#60000
1#
b00000000000000000000000000000111 +
b00000000000000000000000000001000 3
#65000
0#
#70000
1#
b00000000000000000000000000001000 +
b00000000000000000000000000001001 3
#75000
0#
#80000
1#
b00000000000000000000000000001001 +
b00000000000000000000000000001010 3
#85000
0#
#90000
1#
b00000000000000000000000000001010 +
b00000000000000000000000000001011 3
#95000
0#
#100000
1#
b00000000000000000000000000001011 +
b00000000000000000000000000001100 3

View File

@ -0,0 +1,45 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2020 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(simulator => 1);
if (!$Self->have_sc) {
skip("No SystemC installed");
}
else {
top_filename("t_trace_two_a.v");
compile(
make_main => 0,
verilator_make_gmake => 0,
top_filename => 't_trace_two_b.v',
VM_PREFIX => 'Vt_trace_two_b',
verilator_flags2 => ['-sc -trace'],
);
compile(
make_main => 0,
top_filename => 't_trace_two_a.v',
verilator_flags2 => ['-sc', '-exe', '-trace',
"$Self->{t_dir}/t_trace_two_sc.cpp"],
v_flags2 => ['+define+TEST_DUMPPORTS'],
);
execute(
check_finished => 1,
);
if ($Self->{vlt_all}) {
file_grep("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename});
}
}
ok(1);
1;

View File

@ -0,0 +1,83 @@
$date
Sun Mar 1 21:32:04 2020
$end
$version
fstWriter
$end
$timescale
1ns
$end
$scope module topa $end
$var wire 1 ! clk $end
$scope module t $end
$var wire 1 ! clk $end
$var integer 32 " cyc $end
$var integer 32 # c_trace_on $end
$scope module sub $end
$var integer 32 $ inside_sub_a $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
#0
0!
#10
1!
b00000000000000000000000000000011 #
b00000000000000000000000000000010 "
#15
0!
#20
1!
b00000000000000000000000000000011 "
b00000000000000000000000000000100 #
#25
0!
#30
1!
b00000000000000000000000000000101 #
b00000000000000000000000000000100 "
#35
0!
#40
1!
b00000000000000000000000000000101 "
b00000000000000000000000000000110 #
#45
0!
#50
1!
b00000000000000000000000000000111 #
b00000000000000000000000000000110 "
#55
0!
#60
1!
b00000000000000000000000000000111 "
b00000000000000000000000000001000 #
#65
0!
#70
1!
b00000000000000000000000000001001 #
b00000000000000000000000000001000 "
#75
0!
#80
1!
b00000000000000000000000000001001 "
b00000000000000000000000000001010 #
#85
0!
#90
1!
b00000000000000000000000000001011 #
b00000000000000000000000000001010 "
#95
0!
#100
1!
b00000000000000000000000000001011 "
b00000000000000000000000000001100 #

View File

@ -0,0 +1,42 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2020 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.
# Test tracing with two models instanced
scenarios(vlt_all => 1);
top_filename("t_trace_two_a.v");
compile(
make_main => 0,
verilator_make_gmake => 0,
top_filename => 't_trace_two_b.v',
VM_PREFIX => 'Vt_trace_two_b',
verilator_flags2 => ['--trace-fst-thread'],
);
compile(
make_main => 0,
top_filename => 't_trace_two_a.v',
verilator_flags2 => ['-exe', '--trace-fst-thread',
'-DTEST_FST',
"$Self->{t_dir}/t_trace_two_cc.cpp"],
v_flags2 => ['+define+TEST_DUMPPORTS'],
);
execute(
check_finished => 1,
);
if ($Self->{vlt_all}) {
fst2vcd($Self->trace_filename, "$Self->{obj_dir}/simx-fst2vcd.vcd");
vcd_identical("$Self->{obj_dir}/simx-fst2vcd.vcd", $Self->{golden_filename});
}
ok(1);
1;

View File

@ -9,7 +9,9 @@
#include VM_PREFIX_INCLUDE #include VM_PREFIX_INCLUDE
#include "Vt_trace_two_b.h" #include "Vt_trace_two_b.h"
#include "verilated.h" #include "verilated.h"
#include "verilated_vcd_c.h" #ifdef TEST_HDR_TRACE
# include "verilated_vcd_sc.h"
#endif
// Compile in place // Compile in place
#include "Vt_trace_two_b.cpp" #include "Vt_trace_two_b.cpp"
@ -20,7 +22,6 @@
// General headers // General headers
#include "verilated.h" #include "verilated.h"
#include "systemc.h" #include "systemc.h"
#include "verilated_vcd_sc.h"
VM_PREFIX* ap; VM_PREFIX* ap;
Vt_trace_two_b* bp; Vt_trace_two_b* bp;
@ -29,6 +30,7 @@ int sc_main(int argc, char** argv) {
sc_signal<bool> clk; sc_signal<bool> clk;
sc_time sim_time(1100, SC_NS); sc_time sim_time(1100, SC_NS);
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
Verilated::traceEverOn(true);
Verilated::debug(0); Verilated::debug(0);
srand48(5); srand48(5);
ap = new VM_PREFIX("topa"); ap = new VM_PREFIX("topa");
@ -36,8 +38,7 @@ int sc_main(int argc, char** argv) {
ap->clk(clk); ap->clk(clk);
bp->clk(clk); bp->clk(clk);
#if VM_TRACE #ifdef TEST_HDR_TRACE
Verilated::traceEverOn(true);
VerilatedVcdSc* tfp = new VerilatedVcdSc; VerilatedVcdSc* tfp = new VerilatedVcdSc;
ap->trace(tfp, 99); ap->trace(tfp, 99);
bp->trace(tfp, 99); bp->trace(tfp, 99);
@ -64,9 +65,9 @@ int sc_main(int argc, char** argv) {
} }
ap->final(); ap->final();
bp->final(); bp->final();
#if VM_TRACE #ifdef TEST_HDR_TRACE
if (tfp) tfp->close(); if (tfp) tfp->close();
#endif // VM_TRACE #endif
VL_DO_DANGLING(delete ap, ap); VL_DO_DANGLING(delete ap, ap);
VL_DO_DANGLING(delete bp, bp); VL_DO_DANGLING(delete bp, bp);