diff --git a/Changes b/Changes index 558f81a11..b949dba1e 100644 --- a/Changes +++ b/Changes @@ -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] diff --git a/bin/verilator b/bin/verilator index a50add371..1714ed230 100755 --- a/bin/verilator +++ b/bin/verilator @@ -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. -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. 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) diff --git a/examples/make_tracing_c/sim_main.cpp b/examples/make_tracing_c/sim_main.cpp index c8003611e..1e75819f4 100644 --- a/examples/make_tracing_c/sim_main.cpp +++ b/examples/make_tracing_c/sim_main.cpp @@ -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 -#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"); diff --git a/examples/make_tracing_c/top.v b/examples/make_tracing_c/top.v index beae05605..0dc22d9cc 100644 --- a/examples/make_tracing_c/top.v +++ b/examples/make_tracing_c/top.v @@ -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 diff --git a/examples/make_tracing_sc/sc_main.cpp b/examples/make_tracing_sc/sc_main.cpp index b2d704aec..381d321bf 100644 --- a/examples/make_tracing_sc/sc_main.cpp +++ b/examples/make_tracing_sc/sc_main.cpp @@ -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(); diff --git a/include/verilated.cpp b/include/verilated.cpp index 90eecfb25..c242b5ab5 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -1602,6 +1602,25 @@ IData VL_ATOI_N(const std::string& str, int base) VL_PURE { return static_cast(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 diff --git a/include/verilated.h b/include/verilated.h index c039d3878..97becf9c3 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -83,6 +83,7 @@ class VerilatedVar; class VerilatedVarNameMap; class VerilatedVcd; class VerilatedVcdC; +class VerilatedVcdSc; class VerilatedFst; class VerilatedFstC; diff --git a/include/verilated_fst_c.cpp b/include/verilated_fst_c.cpp index 2e2533cbc..5eb69fe04 100644 --- a/include/verilated_fst_c.cpp +++ b/include/verilated_fst_c.cpp @@ -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); diff --git a/include/verilated_fst_c.h b/include/verilated_fst_c.h index 5fc4aeaff..f6de80bb9 100644 --- a/include/verilated_fst_c.h +++ b/include/verilated_fst_c.h @@ -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? diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index c04ee3214..ef9f2b8bc 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -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 diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index 87c4e8baa..c9406686a 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -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; } diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h index 835af7b71..690e3ec31 100644 --- a/include/verilated_vcd_c.h +++ b/include/verilated_vcd_c.h @@ -103,9 +103,9 @@ private: typedef std::vector SigVec; SigVec m_sigs; ///< Pointer to signal information typedef std::vector CallbackVec; - CallbackVec m_callbacks; ///< Routines to perform dumping + CallbackVec m_callbacks; ///< Routines to perform dumping typedef std::map 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? diff --git a/include/verilated_vcd_sc.h b/include/verilated_vcd_sc.h index f5ab1efe1..48c961c8d 100644 --- a/include/verilated_vcd_sc.h +++ b/include/verilated_vcd_sc.h @@ -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() diff --git a/src/V3Ast.h b/src/V3Ast.h index 356df43d3..f877e4056 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -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(_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 { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 448589c9b..7365d6430 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -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 diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index cd424a131..e4efa36e9 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -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(" diff --git a/src/V3EmitCInlines.cpp b/src/V3EmitCInlines.cpp index 0090b880a..39a78e140 100644 --- a/src/V3EmitCInlines.cpp +++ b/src/V3EmitCInlines.cpp @@ -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); diff --git a/src/V3EmitCMake.cpp b/src/V3EmitCMake.cpp index 4d2a2a79d..2de114211 100644 --- a/src/V3EmitCMake.cpp +++ b/src/V3EmitCMake.cpp @@ -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()) { diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 6cdc1c635..8533060a2 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -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 = ','; diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index 284e02bc4..c8a83ce2a 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -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"); } } } diff --git a/src/V3Global.h b/src/V3Global.h index 0011df4ff..da20b88cd 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -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; } }; diff --git a/src/V3Options.h b/src/V3Options.h index dac7c3402..f89ab5a45 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -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(); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 512bb9676..dc4152b46 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -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); diff --git a/src/verilog.l b/src/verilog.l index 23fad9c63..33b791946 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -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; } diff --git a/src/verilog.y b/src/verilog.y index e23427536..8ad3f5fb9 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -553,6 +553,14 @@ class AstSenTree; %token yD_COUNTONES "$countones" %token yD_DIMENSIONS "$dimensions" %token yD_DISPLAY "$display" +%token yD_DUMPALL "$dumpall" +%token yD_DUMPFILE "$dumpfile" +%token yD_DUMPFLUSH "$dumpflush" +%token yD_DUMPLIMIT "$dumplimit" +%token yD_DUMPOFF "$dumpoff" +%token yD_DUMPON "$dumpon" +%token yD_DUMPPORTS "$dumpports" +%token yD_DUMPVARS "$dumpvars" %token yD_ERROR "$error" %token yD_EXP "$exp" %token yD_FATAL "$fatal" @@ -3154,8 +3162,30 @@ system_t_call: // IEEE: system_tf_call (as task) | yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($1, *$1, $3); GRAMMARP->argWrapList(VN_CAST($$, TaskRef)); } // + | yD_DUMPPORTS '(' idDotted ',' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::FILE, $5); DEL($3); + $$->addNext(new AstDumpCtl($1, VDumpCtlType::VARS, + new AstConst($1, 1))); } + | yD_DUMPPORTS '(' ',' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::FILE, $4); + $$->addNext(new AstDumpCtl($1, VDumpCtlType::VARS, + new AstConst($1, 1))); } + | yD_DUMPFILE '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::FILE, $3); } + | yD_DUMPVARS parenE { $$ = new AstDumpCtl($1, VDumpCtlType::VARS, + new AstConst($1, 0)); } + | yD_DUMPVARS '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::VARS, $3); } + | yD_DUMPVARS '(' expr ',' idDotted ')' { $$ = new AstDumpCtl($1, VDumpCtlType::VARS, $3); DEL($5); } + | yD_DUMPALL parenE { $$ = new AstDumpCtl($1, VDumpCtlType::ALL); } + | yD_DUMPALL '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::ALL); DEL($3); } + | yD_DUMPFLUSH parenE { $$ = new AstDumpCtl($1, VDumpCtlType::FLUSH); } + | yD_DUMPFLUSH '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::FLUSH); DEL($3); } + | yD_DUMPLIMIT '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::LIMIT, $3); } + | yD_DUMPLIMIT '(' expr ',' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::LIMIT, $3); DEL($5); } + | yD_DUMPOFF parenE { $$ = new AstDumpCtl($1, VDumpCtlType::OFF); } + | yD_DUMPOFF '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::OFF); DEL($3); } + | yD_DUMPON parenE { $$ = new AstDumpCtl($1, VDumpCtlType::ON); } + | yD_DUMPON '(' expr ')' { $$ = new AstDumpCtl($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++."); } diff --git a/test_regress/t/t_leak.cpp b/test_regress/t/t_leak.cpp index 83db456a1..573286941 100644 --- a/test_regress/t/t_leak.cpp +++ b/test_regress/t/t_leak.cpp @@ -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(); } } diff --git a/test_regress/t/t_trace_dumporder_bad.out b/test_regress/t/t_trace_dumporder_bad.out new file mode 100644 index 000000000..f73b7d67a --- /dev/null +++ b/test_regress/t/t_trace_dumporder_bad.out @@ -0,0 +1,2 @@ +%Warning: $dumpvar ignored as not proceeded by $dumpfile +*-* All Finished *-* diff --git a/test_regress/t/t_trace_dumporder_bad.pl b/test_regress/t/t_trace_dumporder_bad.pl new file mode 100755 index 000000000..cae730749 --- /dev/null +++ b/test_regress/t/t_trace_dumporder_bad.pl @@ -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; diff --git a/test_regress/t/t_trace_dumporder_bad.v b/test_regress/t/t_trace_dumporder_bad.v new file mode 100644 index 000000000..fe443f75e --- /dev/null +++ b/test_regress/t/t_trace_dumporder_bad.v @@ -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 diff --git a/test_regress/t/t_trace_flag_off.out b/test_regress/t/t_trace_flag_off.out new file mode 100644 index 000000000..680eb2bcf --- /dev/null +++ b/test_regress/t/t_trace_flag_off.out @@ -0,0 +1,2 @@ +-Info: t/t_trace_flag_off.v:9: $dumpvar ignored, as Verilated without --trace +*-* All Finished *-* diff --git a/test_regress/t/t_trace_flag_off.pl b/test_regress/t/t_trace_flag_off.pl new file mode 100755 index 000000000..bc3f03af6 --- /dev/null +++ b/test_regress/t/t_trace_flag_off.pl @@ -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; diff --git a/test_regress/t/t_trace_flag_off.v b/test_regress/t/t_trace_flag_off.v new file mode 100644 index 000000000..b8348526f --- /dev/null +++ b/test_regress/t/t_trace_flag_off.v @@ -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 diff --git a/test_regress/t/t_trace_two_a.v b/test_regress/t/t_trace_two_a.v index da58afecc..86533cc90 100644 --- a/test_regress/t/t_trace_two_a.v +++ b/test_regress/t/t_trace_two_a.v @@ -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 diff --git a/test_regress/t/t_trace_two_hdr_cc.cpp b/test_regress/t/t_trace_two_cc.cpp similarity index 72% rename from test_regress/t/t_trace_two_hdr_cc.cpp rename to test_regress/t/t_trace_two_cc.cpp index 9b8bcf395..3eb7c0baa 100644 --- a/test_regress/t/t_trace_two_hdr_cc.cpp +++ b/test_regress/t/t_trace_two_cc.cpp @@ -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); diff --git a/test_regress/t/t_trace_two_dump_cc.out b/test_regress/t/t_trace_two_dump_cc.out new file mode 100644 index 000000000..466b4c432 --- /dev/null +++ b/test_regress/t/t_trace_two_dump_cc.out @@ -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 diff --git a/test_regress/t/t_trace_two_dump_cc.pl b/test_regress/t/t_trace_two_dump_cc.pl new file mode 100755 index 000000000..2d3e34fd4 --- /dev/null +++ b/test_regress/t/t_trace_two_dump_cc.pl @@ -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; diff --git a/test_regress/t/t_trace_two_dump_sc.out b/test_regress/t/t_trace_two_dump_sc.out new file mode 100644 index 000000000..a9f2fe8aa --- /dev/null +++ b/test_regress/t/t_trace_two_dump_sc.out @@ -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 diff --git a/test_regress/t/t_trace_two_dump_sc.pl b/test_regress/t/t_trace_two_dump_sc.pl new file mode 100755 index 000000000..6579e2cec --- /dev/null +++ b/test_regress/t/t_trace_two_dump_sc.pl @@ -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; diff --git a/test_regress/t/t_trace_two_dumpfst_cc.out b/test_regress/t/t_trace_two_dumpfst_cc.out new file mode 100755 index 000000000..9141e9a39 --- /dev/null +++ b/test_regress/t/t_trace_two_dumpfst_cc.out @@ -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 # diff --git a/test_regress/t/t_trace_two_dumpfst_cc.pl b/test_regress/t/t_trace_two_dumpfst_cc.pl new file mode 100755 index 000000000..f19d777c0 --- /dev/null +++ b/test_regress/t/t_trace_two_dumpfst_cc.pl @@ -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; diff --git a/test_regress/t/t_trace_two_hdr_cc.pl b/test_regress/t/t_trace_two_hdr_cc.pl index 3601322e4..1fbe3fd38 100755 --- a/test_regress/t/t_trace_two_hdr_cc.pl +++ b/test_regress/t/t_trace_two_hdr_cc.pl @@ -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( diff --git a/test_regress/t/t_trace_two_hdr_sc.pl b/test_regress/t/t_trace_two_hdr_sc.pl index 3c8de5b0b..7cbd882a0 100755 --- a/test_regress/t/t_trace_two_hdr_sc.pl +++ b/test_regress/t/t_trace_two_hdr_sc.pl @@ -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( diff --git a/test_regress/t/t_trace_two_hdrfst_cc.out b/test_regress/t/t_trace_two_hdrfst_cc.out new file mode 100755 index 000000000..a7289d36e Binary files /dev/null and b/test_regress/t/t_trace_two_hdrfst_cc.out differ diff --git a/test_regress/t/t_trace_two_hdrfst_cc.pl b/test_regress/t/t_trace_two_hdrfst_cc.pl new file mode 100755 index 000000000..514eca86d --- /dev/null +++ b/test_regress/t/t_trace_two_hdrfst_cc.pl @@ -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; diff --git a/test_regress/t/t_trace_two_port_cc.out b/test_regress/t/t_trace_two_port_cc.out new file mode 100644 index 000000000..dd2f3213c --- /dev/null +++ b/test_regress/t/t_trace_two_port_cc.out @@ -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 diff --git a/test_regress/t/t_trace_two_port_cc.pl b/test_regress/t/t_trace_two_port_cc.pl new file mode 100755 index 000000000..31abb926b --- /dev/null +++ b/test_regress/t/t_trace_two_port_cc.pl @@ -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; diff --git a/test_regress/t/t_trace_two_port_sc.out b/test_regress/t/t_trace_two_port_sc.out new file mode 100644 index 000000000..af8668106 --- /dev/null +++ b/test_regress/t/t_trace_two_port_sc.out @@ -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 diff --git a/test_regress/t/t_trace_two_port_sc.pl b/test_regress/t/t_trace_two_port_sc.pl new file mode 100755 index 000000000..177f24f65 --- /dev/null +++ b/test_regress/t/t_trace_two_port_sc.pl @@ -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; diff --git a/test_regress/t/t_trace_two_portfst_cc.out b/test_regress/t/t_trace_two_portfst_cc.out new file mode 100755 index 000000000..ec99d954e --- /dev/null +++ b/test_regress/t/t_trace_two_portfst_cc.out @@ -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 # diff --git a/test_regress/t/t_trace_two_portfst_cc.pl b/test_regress/t/t_trace_two_portfst_cc.pl new file mode 100755 index 000000000..cb21e0f34 --- /dev/null +++ b/test_regress/t/t_trace_two_portfst_cc.pl @@ -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; diff --git a/test_regress/t/t_trace_two_hdr_sc.cpp b/test_regress/t/t_trace_two_sc.cpp similarity index 93% rename from test_regress/t/t_trace_two_hdr_sc.cpp rename to test_regress/t/t_trace_two_sc.cpp index dce33a0e1..c3c1d12ac 100644 --- a/test_regress/t/t_trace_two_hdr_sc.cpp +++ b/test_regress/t/t_trace_two_sc.cpp @@ -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 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);