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 support for $dumpfile and $dumpvars, #2126. [Alexander Grobman]
*** Add +verilator+noassert flag to disable assertion checking. [Tobias Wölfel]
*** Add check for assertOn for asserts, #2162. [Tobias Wölfel]

View File

@ -3782,17 +3782,29 @@ $unsigned, $warning.
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
The sized display functions are rarely used and so not supported. Replace
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
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.
Add the --trace switch to Verilator, and in your top level C code, call
Verilated::traceEverOn(true). Then create a VerilatedVcdC object, and
in your main loop call "trace_object->dump(time)" every time step, and
finally call "trace_object->close()". For an example, see below and the
examples/make_tracing_c/sim_main.cpp file of the distribution.
A. Add the --trace switch to Verilator, and in your top level C code, call
Verilated::traceEverOn(true). Then you may use $dumpfile and $dumpvars to
enable traces, same as with any Verilog simulator. See
C<examples/make_tracing_c>.
You also need to compile verilated_vcd_c.cpp and add it to your link,
preferably by adding the dependencies in $(VK_GLOBAL_OBJS) to your
Makefile's link rule. 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.
B. Or, for finer-grained control, or C++ files with multiple Verilated
modules you may also create the trace purely from C++. Create a
VerilatedVcdC object, and in your main loop call "trace_object->dump(time)"
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
adding the dependencies in $(VK_GLOBAL_OBJS) to your Makefile's link rule.
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"
...
@ -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?
Add the --trace switch to Verilator, and in your top level C sc_main code,
include verilated_vcd_sc.h. Then call Verilated::traceEverOn(true). Then
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.
A. Add the --trace switch to Verilator, and in your top level sc_main, call
Verilated::traceEverOn(true). Then you may use $dumpfile and $dumpvars to
enable traces, same as with any Verilog simulator, see the non-SystemC
example in C<examples/make_tracing_c>. This will trace only the module
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
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++?
FST a format by GTKWave.
This version provides a basic FST support.
To dump FST format, add the --trace-fst switch to Verilator and change the include
path in the testbench to:
FST a format by GTKWave. This version provides a basic FST support. To
dump FST format, add the --trace-fst switch to Verilator and either A. use
$dumpfile/$dumpvars in Verilog as described in the VCD example above, or
B. in C++ change the include described in the VCD example above:
#include "verilated_fst_c.h"
VerilatedFstC* tfp = new VerilatedFstC;
Note that currently supporting both FST and VCD in a single simulation is impossible,
but such requirement could be rare.
Note that currently supporting both FST and VCD in a single simulation is
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
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
with the public domain GTKWave (recommended) or Dinotrace (legacy)

View File

@ -10,11 +10,6 @@
// Include model header, generated from Verilating "top.v"
#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)
vluint64_t main_time = 0;
// Called by $time in Verilog
@ -36,28 +31,19 @@ int main(int argc, char** argv, char** env) {
// May be overridden by commandArgs
Verilated::randReset(2);
// Verilator must compute traced signals
Verilated::traceEverOn(true);
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
// This needs to be called before you create any model
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"
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
top->reset_l = !0;
top->fastclk = 0;
@ -90,13 +76,11 @@ int main(int argc, char** argv, char** env) {
top->in_quad += 0x12;
// 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();
#if VM_TRACE
// Dump trace data for this cycle
if (tfp) tfp->dump(main_time);
#endif
// Read outputs
VL_PRINTF("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
" -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n",
@ -107,11 +91,6 @@ int main(int argc, char** argv, char** env) {
// Final model cleanup
top->final();
// Close trace if opened
#if VM_TRACE
if (tfp) { tfp->close(); tfp = NULL; }
#endif
// Coverage analysis (since test passed)
#if VM_COVERAGE
Verilated::mkdir("logs");

View File

@ -36,6 +36,11 @@ module top
// Print some stuff as an example
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);
end

View File

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

View File

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

View File

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

View File

@ -198,7 +198,7 @@ class VerilatedFstC {
VL_UNCOPYABLE(VerilatedFstC);
public:
explicit VerilatedFstC(void* filep=NULL) : m_sptrace(filep) {}
~VerilatedFstC() {}
~VerilatedFstC() { close(); }
public:
// ACCESSORS
/// 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;
//======================================================================
// Dumping
extern const char* vl_dumpctl_filenamep(bool setit = false,
const std::string& filename = "") VL_MT_SAFE;
#endif // Guard

View File

@ -119,7 +119,7 @@ protected:
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);
return (m_fd>=0);
return m_fd >= 0;
}
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
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
m_fileNewed = (filep == NULL);
m_filep = m_fileNewed ? new VerilatedVcdFile : filep;
@ -156,7 +159,7 @@ VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
void VerilatedVcd::open(const char* filename) {
m_assertOne.check();
if (isOpen()) return;
if (isOpen() || !filename || !*filename) return;
// Set member variables
m_filename = filename;
@ -690,7 +693,7 @@ void VerilatedVcd::dump(vluint64_t timeui) {
m_assertOne.check();
if (!isOpen()) return;
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);
return;
}

View File

@ -103,9 +103,9 @@ private:
typedef std::vector<VerilatedVcdSig> SigVec;
SigVec m_sigs; ///< Pointer to signal information
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;
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
@ -445,7 +445,7 @@ class VerilatedVcdC {
public:
explicit VerilatedVcdC(VerilatedVcdFile* filep = NULL)
: m_sptrace(filep) {}
~VerilatedVcdC() {}
~VerilatedVcdC() { close(); }
public:
// ACCESSORS
/// Is file open?

View File

@ -62,7 +62,7 @@ public:
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
# endif
}
virtual ~VerilatedVcdSc() {}
virtual ~VerilatedVcdSc() { close(); }
// METHODS
/// 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 {
public:
enum en {

View File

@ -3033,6 +3033,31 @@ public:
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 {
// Parents: stmtlist
// Children: SFORMATF to generate print string

View File

@ -402,6 +402,44 @@ public:
if (nodep->addNewline()) text += "\n";
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 {
// For use under AstCCalls for dpiImports. ScopeNames under
// displays are handled in AstDisplay
@ -2110,8 +2148,16 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
void EmitCImp::emitDestructorImp(AstNodeModule* modp) {
puts("\n");
puts(prefixNameProtect(modp) + "::~" + prefixNameProtect(modp) + "() {\n");
if (modp->isTop() && v3Global.opt.mtasks()) {
puts("delete __Vm_threadPoolp; __Vm_threadPoolp = NULL;\n");
if (modp->isTop()) {
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);
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) {
puts("\nvoid " + prefixNameProtect(modp) + "::eval() {\n");
puts("\nvoid " + prefixNameProtect(modp) + "::eval_step() {\n");
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate " + prefixNameProtect(modp)
+ "::eval\\n\"); );\n");
puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
@ -2316,6 +2362,15 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
putsDecoration("// Initialize\n");
puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) "
+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()) {
puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n");
}
@ -2377,6 +2432,21 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
puts("}\n");
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") + "("
+ EmitCBaseVisitor::symClassVar() + ") {\n");
@ -2693,11 +2763,11 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
ofp()->putsPrivate(!modp->isTop()); // private: unless top
puts(symClassName()+"* __VlSymsp; // Symbol table\n");
ofp()->putsPrivate(false); // public:
if (modp->isTop() && v3Global.opt.inhibitSim()) {
puts("bool __Vm_inhibitSim; ///< Set true to disable evaluation of module\n");
}
if (modp->isTop() && v3Global.opt.mtasks()) {
emitMTaskState();
if (modp->isTop()) {
if (v3Global.opt.inhibitSim()) {
puts("bool __Vm_inhibitSim; ///< Set true to disable evaluation of module\n");
}
if (v3Global.opt.mtasks()) emitMTaskState();
}
emitCoverageDecl(modp); // may flip public/private
@ -2775,14 +2845,26 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
if (modp->isTop()) {
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.
else puts("/// Evaluate the model. Application must call when inputs change.\n");
puts("void eval();\n");
if (!optSystemC()) puts("/// Evaluate the model. Application must call when inputs change.\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:
if (!optSystemC()) puts("/// Simulation complete, run final blocks. Application must call on completion.\n");
puts("void final();\n");
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:
puts("static void "+protect("_eval_initial_loop")
+"("+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)) {
@ -2978,14 +3063,43 @@ class EmitCTrace : EmitCStmts {
void emitTraceHeader() {
// Includes
puts("#include \""+v3Global.opt.traceSourceName()+"_c.h\"\n");
puts("#include \""+ symClassName() +".h\"\n");
puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n");
puts("#include \"" + symClassName() + ".h\"\n");
puts("\n");
}
void emitTraceSlow() {
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(v3Global.opt.traceClassBase()+"C* tfp, int, int) {\n");
puts( "tfp->spTrace()->addCallback("

View File

@ -66,6 +66,11 @@ class EmitCInlines : EmitCBaseVisitor {
v3Global.needHeavy(true);
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 {
v3Global.needHeavy(true);
iterateChildren(nodep);

View File

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

View File

@ -417,6 +417,13 @@ void EmitCSyms::emitSymHdr() {
puts("\n// LOCAL STATE\n");
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()) {
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(symClassName()+"::"+symClassName()+"("+topClassName()+"* topp, const char* namep)\n");
puts(" // Setup locals\n");
puts(" : __Vm_namep(namep)\n"); // No leak, as we get destroyed when the top is destroyed
if (v3Global.opt.trace()) {
puts(" , __Vm_activity(false)\n");
}
puts(" : __Vm_namep(namep)\n"); // No leak, as gets destroyed when the top is destroyed
if (v3Global.needTraceDumper()) puts(" , __Vm_dumperp(NULL)\n");
if (v3Global.opt.trace()) puts(" , __Vm_activity(false)\n");
puts(" , __Vm_didInit(false)\n");
puts(" // Setup submodule names\n");
char comma = ',';

View File

@ -85,12 +85,12 @@ public:
putMakeClassEntry(of, "verilated_cov.cpp");
}
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.traceFormat() != TraceFormat::VCD) {
v3error("Unsupported: This trace format is not supported in SystemC, use VCD format.");
} 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 {
// Globals
AstNetlist* m_rootp; // Root of entire netlist
VWidthMinUsage m_widthMinUsage; // What AstNode::widthMin() is used for
AstNetlist* m_rootp; // Root of entire netlist
VWidthMinUsage m_widthMinUsage; // What AstNode::widthMin() is used for
int m_debugFileNumber; // Number to append to debug files created
bool m_assertDTypesResolved; // Tree should have dtypep()'s
bool m_constRemoveXs; // Const needs to strip any Xs
bool m_needHInlines; // Need __Inlines file
bool m_needHeavy; // Need verilated_heavy.h include
bool m_dpi; // Need __Dpi include files
int m_debugFileNumber; // Number to append to debug files created
bool m_assertDTypesResolved; // Tree should have dtypep()'s
bool m_constRemoveXs; // Const needs to strip any Xs
bool m_needTraceDumper; // Need __Vm_dumperp in symbols
bool m_needHInlines; // Need __Inlines file
bool m_needHeavy; // Need verilated_heavy.h include
bool m_dpi; // Need __Dpi include files
public:
// Options
@ -92,6 +93,7 @@ public:
m_widthMinUsage = VWidthMinUsage::LINT_WIDTH;
m_assertDTypesResolved = false;
m_constRemoveXs = false;
m_needTraceDumper = false;
m_needHInlines = false;
m_needHeavy = false;
m_dpi = false;
@ -119,10 +121,12 @@ public:
char digits[100]; sprintf(digits, "%03d", m_debugFileNumber);
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; }
void needHInlines(bool flag) { m_needHInlines=flag; }
void needHInlines(bool flag) { m_needHInlines = flag; }
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; }
void dpi(bool flag) { m_dpi = flag; }
};

View File

@ -467,7 +467,11 @@ class V3Options {
bool oTable() const { return m_oTable; }
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)
static string version();

View File

@ -2872,6 +2872,11 @@ private:
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 {
// Although a system function in IEEE, here a statement which sets the file pointer (MCD)
assertAtStatement(nodep);

View File

@ -197,6 +197,19 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$cos" { FL; return yD_COS; }
"$cosh" { FL; return yD_COSH; }
"$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; }
"$fclose" { FL; return yD_FCLOSE; }
"$fdisplay" { FL; return yD_FDISPLAY; }
@ -208,10 +221,10 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$floor" { FL; return yD_FLOOR; }
"$fopen" { FL; return yD_FOPEN; }
"$fread" { FL; return yD_FREAD; }
"$frewind" { FL; return yD_FREWIND; }
"$fscanf" { FL; return yD_FSCANF; }
"$fseek" { FL; return yD_FSEEK; }
"$ftell" { FL; return yD_FTELL; }
"$frewind" { FL; return yD_FREWIND; }
"$fullskew" { FL; return yaTIMINGSPEC; }
"$fwrite" { FL; return yD_FWRITE; }
"$hold" { FL; return yaTIMINGSPEC; }

View File

@ -553,6 +553,14 @@ class AstSenTree;
%token<fl> yD_COUNTONES "$countones"
%token<fl> yD_DIMENSIONS "$dimensions"
%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_EXP "$exp"
%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);
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_SYSTEM '(' expr ')' { $$ = new AstSystemT($1, $3); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($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++."); }

View File

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

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,
// without warranty, 2020 by Wilson Snyder.
`define CONCAT(a, b) a``b
`define STRINGIFY(x) `"x`"
module t (/*AUTOARG*/
// Inputs
clk
@ -15,11 +18,55 @@ module t (/*AUTOARG*/
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
if (cyc != 0) begin
cyc <= cyc + 1;
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");
$finish;
end

View File

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

View File

@ -26,8 +26,9 @@ else {
compile(
make_main => 0,
top_filename => 't_trace_two_a.v',
make_flags => 'CPPFLAGS_ADD=-DTEST_HDR_TRACE',
verilator_flags2 => ['-sc', '-exe', '-trace',
"$Self->{t_dir}/t_trace_two_hdr_sc.cpp"],
"$Self->{t_dir}/t_trace_two_sc.cpp"],
);
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 "Vt_trace_two_b.h"
#include "verilated.h"
#include "verilated_vcd_c.h"
#ifdef TEST_HDR_TRACE
# include "verilated_vcd_sc.h"
#endif
// Compile in place
#include "Vt_trace_two_b.cpp"
@ -20,7 +22,6 @@
// General headers
#include "verilated.h"
#include "systemc.h"
#include "verilated_vcd_sc.h"
VM_PREFIX* ap;
Vt_trace_two_b* bp;
@ -29,6 +30,7 @@ int sc_main(int argc, char** argv) {
sc_signal<bool> clk;
sc_time sim_time(1100, SC_NS);
Verilated::commandArgs(argc, argv);
Verilated::traceEverOn(true);
Verilated::debug(0);
srand48(5);
ap = new VM_PREFIX("topa");
@ -36,8 +38,7 @@ int sc_main(int argc, char** argv) {
ap->clk(clk);
bp->clk(clk);
#if VM_TRACE
Verilated::traceEverOn(true);
#ifdef TEST_HDR_TRACE
VerilatedVcdSc* tfp = new VerilatedVcdSc;
ap->trace(tfp, 99);
bp->trace(tfp, 99);
@ -64,9 +65,9 @@ int sc_main(int argc, char** argv) {
}
ap->final();
bp->final();
#if VM_TRACE
#ifdef TEST_HDR_TRACE
if (tfp) tfp->close();
#endif // VM_TRACE
#endif
VL_DO_DANGLING(delete ap, ap);
VL_DO_DANGLING(delete bp, bp);