diff --git a/Changes b/Changes index e2995f9e2..c65e7a197 100644 --- a/Changes +++ b/Changes @@ -11,6 +11,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Skip SystemC tests if not installed. [Iztok Jeras] +**** Fix flushing VCD buffers on $stop. [Ashutosh Das] + **** Fix Mac OS-X compile issues, bug217. [Joshua Wise, Trevor Williams] **** Fix make uninstall, bug216. [Iztok Jeras] diff --git a/include/verilated.cpp b/include/verilated.cpp index 6ac87df77..15bbf9cf0 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -33,7 +33,11 @@ //=========================================================================== // Global variables +// Slow path variables int Verilated::s_randReset = 0; +VerilatedVoidCb Verilated::s_flushCb = NULL; + +// Keep below together in one cache line int Verilated::s_debug = 1; bool Verilated::s_calcUnusedSigs = false; bool Verilated::s_gotFinish = false; @@ -53,6 +57,7 @@ void vl_finish (const char* filename, int linenum, const char* hier) { VL_PRINTF("- %s:%d: Verilog $finish\n", filename, linenum); if (Verilated::gotFinish()) { VL_PRINTF("- %s:%d: Second verilog $finish, exiting\n", filename, linenum); + Verilated::flushCall(); exit(0); } Verilated::gotFinish(true); @@ -62,6 +67,7 @@ void vl_finish (const char* filename, int linenum, const char* hier) { #ifndef VL_USER_STOP // Define this to override this function void vl_stop (const char* filename, int linenum, const char* hier) { Verilated::gotFinish(true); + Verilated::flushCall(); vl_fatal (filename,linenum,hier,"Verilog $stop"); } #endif @@ -71,6 +77,7 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char* if (0 && hier) {} Verilated::gotFinish(true); VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg); + Verilated::flushCall(); abort(); } #endif @@ -971,6 +978,15 @@ const char* Verilated::catName(const char* n1, const char* n2) { return strp; } +void Verilated::flushCb(VerilatedVoidCb cb) { + if (s_flushCb == cb) {} // Ok - don't duplicate + else if (!s_flushCb) { s_flushCb=cb; } + else { + // Someday we may allow multiple callbacks ala atexit(), but until then + vl_fatal("unknown",0,"", "Verilated::flushCb called twice with different callbacks"); + } +} + void Verilated::commandArgs(int argc, const char** argv) { VerilatedImp::commandArgs(argc,argv); } diff --git a/include/verilated.h b/include/verilated.h index 3db874f8b..7983d7d3c 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -62,6 +62,8 @@ typedef vluint32_t WData; ///< Verilated pack data, >64 bits, as an array typedef const WData* WDataInP; ///< Array input to a function typedef WData* WDataOutP; ///< Array output from a function +typedef void (*VerilatedVoidCb)(void); + class SpTraceVcd; class SpTraceVcdCFile; class VerilatedVcd; @@ -182,7 +184,11 @@ public: // But internals only - called from VerilatedModule's struct Verilated { // MEMBERS private: + // Slow path variables static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random + static VerilatedVoidCb s_flushCb; ///< Flush callback function + + // Fast path static int s_debug; ///< See accessors... only when VL_DEBUG set static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated static bool s_gotFinish; ///< A $finish statement executed @@ -224,6 +230,9 @@ public: /// Enable/disable assertions static void assertOn(bool flag) { s_assertOn=flag; } static bool assertOn() { return s_assertOn; } + /// Flush callback for VCD waves + static void flushCb(VerilatedVoidCb cb); + static void flushCall() { if (s_flushCb) (*s_flushCb)(); } /// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs static void commandArgs(int argc, const char** argv); diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index 238e89cb6..94269fb76 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -88,6 +88,11 @@ void VerilatedVcd::open (const char* filename) { m_filename = filename; s_vcdVecp.push_back(this); + // SPDIFF_OFF + // Set callback so an early exit will flush us + Verilated::flushCb(&flush_all); + + // SPDIFF_ON openNext (m_rolloverMB!=0); if (!isOpen()) return;