diff --git a/Changes b/Changes index 2c5a606f9..55b980a8e 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.871 devel +*** Add VerilatedVcdFile to allow real-time waveforms, bug890. [HyungKi Jeong] + **** Fix comma-instantiations with parameters, bug884. [Franck Jullien] **** Fix SystemC arrayed bit vectors, bug886. [David Poole] diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index 04c6cf376..528df83aa 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -76,11 +76,48 @@ protected: : m_initcb(icb), m_fullcb(fcb), m_changecb(changecb), m_userthis(ut), m_code(code) {}; }; +//============================================================================= +//============================================================================= +//============================================================================= +// VerilatedVcdFile + +bool VerilatedVcdFile::open(const string& name) { + m_fd = ::open(name.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK, 0666); + return (m_fd>=0); +} + +void VerilatedVcdFile::close() { + ::close(m_fd); +} + +ssize_t VerilatedVcdFile::write(const char* bufp, ssize_t len) { + return ::write(m_fd, bufp, len); +} + //============================================================================= //============================================================================= //============================================================================= // Opening/Closing +VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep) + : 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; + m_namemapp = NULL; + m_timeRes = m_timeUnit = 1e-9; + m_timeLastDump = 0; + m_sigs_oldvalp = NULL; + m_evcd = false; + m_scopeEscape = '.'; // Backward compatibility + m_fullDump = true; + m_wrChunkSize = 8*1024; + m_wrBufp = new char [m_wrChunkSize*8]; + m_wrFlushp = m_wrBufp + m_wrChunkSize * 6; + m_writep = m_wrBufp; + m_wroteBytes = 0; +} + void VerilatedVcd::open (const char* filename) { if (isOpen()) return; @@ -142,9 +179,7 @@ void VerilatedVcd::openNext (bool incFilename) { assert(0); // Not supported yet. } else { // cppcheck-suppress duplicateExpression - m_fd = ::open (m_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK - , 0666); - if (m_fd<0) { + if (!m_filep->open(m_filename)) { // User code can check isOpen() m_isOpen = false; return; @@ -199,6 +234,7 @@ VerilatedVcd::~VerilatedVcd() { if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; } if (m_sigs_oldvalp) { delete[] m_sigs_oldvalp; m_sigs_oldvalp=NULL; } deleteNameMap(); + if (m_filep && m_fileNewed) { delete m_filep; m_filep = NULL; } // Remove from list of traces vector::iterator pos = find(s_vcdVecp.begin(), s_vcdVecp.end(), this); if (pos != s_vcdVecp.end()) { s_vcdVecp.erase(pos); } @@ -209,7 +245,7 @@ void VerilatedVcd::closePrev () { bufferFlush(); m_isOpen = false; - ::close(m_fd); + m_filep->close(); } void VerilatedVcd::closeErr () { @@ -219,7 +255,7 @@ void VerilatedVcd::closeErr () { // No buffer flush, just fclose m_isOpen = false; - ::close(m_fd); // May get error, just ignore it + m_filep->close(); // May get error, just ignore it } void VerilatedVcd::close() { @@ -285,7 +321,7 @@ void VerilatedVcd::bufferFlush () { ssize_t remaining = (m_writep - wp); if (remaining==0) break; errno = 0; - ssize_t got = write (m_fd, wp, remaining); + ssize_t got = m_filep->write(wp, remaining); if (got>0) { wp += got; m_wroteBytes += got; diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h index a2d9ca8d7..76f7be70b 100644 --- a/include/verilated_vcd_c.h +++ b/include/verilated_vcd_c.h @@ -36,6 +36,22 @@ class VerilatedVcd; class VerilatedVcdCallInfo; // SPDIFF_ON +//============================================================================= +// VerilatedFile +/// File handling routines, which can be overrode for e.g. socket I/O + +class VerilatedVcdFile { +private: + int m_fd; ///< File descriptor we're writing to +public: + // METHODS + VerilatedVcdFile() : m_fd(0) {} + virtual ~VerilatedVcdFile() {} + virtual bool open(const string& name); + virtual void close(); + virtual ssize_t write(const char* bufp, ssize_t len); +}; + //============================================================================= // VerilatedVcdSig /// Internal data on one signal being traced. @@ -62,9 +78,10 @@ typedef void (*VerilatedVcdCallback_t)(VerilatedVcd* vcdp, void* userthis, vluin class VerilatedVcd { private: + VerilatedVcdFile* m_filep; ///< File we're writing to + bool m_fileNewed; ///< m_filep needs destruction bool m_isOpen; ///< True indicates open file bool m_evcd; ///< True for evcd format - int m_fd; ///< File descriptor we're writing to string m_filename; ///< Filename we're writing to (if open) vluint64_t m_rolloverMB; ///< MB of file size to rollover at char m_scopeEscape; ///< Character to separate scope components @@ -135,21 +152,7 @@ protected: public: // CREATORS - VerilatedVcd () : m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) { - m_namemapp = NULL; - m_timeRes = m_timeUnit = 1e-9; - m_timeLastDump = 0; - m_sigs_oldvalp = NULL; - m_evcd = false; - m_scopeEscape = '.'; // Backward compatibility - m_fd = 0; - m_fullDump = true; - m_wrChunkSize = 8*1024; - m_wrBufp = new char [m_wrChunkSize*8]; - m_wrFlushp = m_wrBufp + m_wrChunkSize * 6; - m_writep = m_wrBufp; - m_wroteBytes = 0; - } + VerilatedVcd(VerilatedVcdFile* filep=NULL); ~VerilatedVcd(); // ACCESSORS diff --git a/test_regress/t/t_vpi_get.cpp b/test_regress/t/t_vpi_get.cpp index c6bc3ac93..a6f6cee74 100644 --- a/test_regress/t/t_vpi_get.cpp +++ b/test_regress/t/t_vpi_get.cpp @@ -245,10 +245,10 @@ int main(int argc, char **argv, char **env) { # endif #endif - Verilated::traceEverOn(true); - VerilatedVcdC* tfp = new VerilatedVcdC; #if VM_TRACE + Verilated::traceEverOn(true); VL_PRINTF("Enabling waves...\n"); + VerilatedVcdC* tfp = new VerilatedVcdC; topp->trace (tfp, 99); tfp->open ("obj_dir/t_vpi_var/simx.vcd"); #endif diff --git a/test_regress/t/t_vpi_memory.cpp b/test_regress/t/t_vpi_memory.cpp index 57c7bd41f..e5234d69f 100644 --- a/test_regress/t/t_vpi_memory.cpp +++ b/test_regress/t/t_vpi_memory.cpp @@ -228,10 +228,10 @@ int main(int argc, char **argv, char **env) { # endif #endif - Verilated::traceEverOn(true); - VerilatedVcdC* tfp = new VerilatedVcdC; #if VM_TRACE + Verilated::traceEverOn(true); VL_PRINTF("Enabling waves...\n"); + VerilatedVcdC* tfp = new VerilatedVcdC; topp->trace (tfp, 99); tfp->open ("obj_dir/t_vpi_var/simx.vcd"); #endif diff --git a/test_regress/t/t_vpi_unimpl.cpp b/test_regress/t/t_vpi_unimpl.cpp index 4fb396590..4fa1a6546 100644 --- a/test_regress/t/t_vpi_unimpl.cpp +++ b/test_regress/t/t_vpi_unimpl.cpp @@ -159,10 +159,10 @@ int main(int argc, char **argv, char **env) { # endif #endif - Verilated::traceEverOn(true); - VerilatedVcdC* tfp = new VerilatedVcdC; #if VM_TRACE + Verilated::traceEverOn(true); VL_PRINTF("Enabling waves...\n"); + VerilatedVcdC* tfp = new VerilatedVcdC; topp->trace (tfp, 99); tfp->open ("obj_dir/t_vpi_var/simx.vcd"); #endif diff --git a/test_regress/t/t_vpi_var.cpp b/test_regress/t/t_vpi_var.cpp index ce8996615..5c21fa592 100644 --- a/test_regress/t/t_vpi_var.cpp +++ b/test_regress/t/t_vpi_var.cpp @@ -660,10 +660,10 @@ int main(int argc, char **argv, char **env) { # endif #endif - Verilated::traceEverOn(true); - VerilatedVcdC* tfp = new VerilatedVcdC; #if VM_TRACE + Verilated::traceEverOn(true); VL_PRINTF("Enabling waves...\n"); + VerilatedVcdC* tfp = new VerilatedVcdC; topp->trace (tfp, 99); tfp->open ("obj_dir/t_vpi_var/simx.vcd"); #endif