diff --git a/Changes b/Changes index e49f180d7..053cbda98 100644 --- a/Changes +++ b/Changes @@ -15,11 +15,11 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Add error if use SystemC 2.2 and earlier (pre-2011) as is deprecated. -**** Improve FST dump performance, #2244, #2250. [Geza Lore] +**** Greatly improve FST dump performance, #2244, #2250, #2257. [Geza Lore] **** Fix build of fast path tracing code to use OPT_FAST, #2245. [Geza Lore] -**** Improve VCD dump performance, #2246, #2250. [Geza Lore] +**** Improve VCD dump performance, #2246, #2250, #2257. [Geza Lore] * Verilator 4.032 2020-04-04 diff --git a/bin/verilator b/bin/verilator index cd1bfb1e3..d49fc5e08 100755 --- a/bin/verilator +++ b/bin/verilator @@ -4987,6 +4987,12 @@ 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. +When using SystemC 2.3, the SystemC library must have been built with the +experiemntal simulation phase callback based tracing disabled. This is +disabled by default when building SystemC with its configure based build +system, but when building SystemC with CMake, you must pass +-DENABLE_PHASE_CALLBACKS_TRACING=OFF to disable this feature. + #include "verilated_vcd_sc.h" ... int main(int argc, char** argv, char** env) { diff --git a/include/verilated_fst_c.cpp b/include/verilated_fst_c.cpp index bdd2e5d61..5654cf9e8 100644 --- a/include/verilated_fst_c.cpp +++ b/include/verilated_fst_c.cpp @@ -17,6 +17,8 @@ //============================================================================= // SPDIFF_OFF +// clang-format off + #define __STDC_LIMIT_MACROS // UINT64_MAX #include "verilatedos.h" #include "verilated.h" @@ -49,6 +51,8 @@ # include #endif +// clang-format on + //============================================================================= class VerilatedFstCallInfo { @@ -79,13 +83,15 @@ VerilatedFst::VerilatedFst(void* fst) , m_minNextDumpTime(0) , m_nextCode(1) , m_scopeEscape('.') - , m_symbolp(NULL) { + , m_symbolp(NULL) + , m_sigs_oldvalp(NULL) { m_valueStrBuffer.reserve(64 + 1); // Need enough room for quad } VerilatedFst::~VerilatedFst() { if (m_fst) fstWriterClose(m_fst); if (m_symbolp) VL_DO_CLEAR(delete[] m_symbolp, m_symbolp = NULL); + if (m_sigs_oldvalp) VL_DO_CLEAR(delete[] m_sigs_oldvalp, m_sigs_oldvalp = NULL); } void VerilatedFst::open(const char* filename) VL_MT_UNSAFE { @@ -121,6 +127,9 @@ void VerilatedFst::open(const char* filename) VL_MT_UNSAFE { } } m_code2symbol.clear(); + + // Allocate space now we know the number of codes + if (!m_sigs_oldvalp) m_sigs_oldvalp = new vluint32_t[m_nextCode + 10]; } void VerilatedFst::module(const std::string& name) { m_module = name; } @@ -214,9 +223,9 @@ void VerilatedFst::addCallback(VerilatedFstCallback_t initcb, VerilatedFstCallba void VerilatedFst::dump(vluint64_t timeui) { if (!isOpen()) return; if (timeui < m_minNextDumpTime) { - VL_PRINTF_MT("%%Warning: previous dump at t=%" VL_PRI64 "u, requesting t=%" VL_PRI64 "u\n", - m_minNextDumpTime - 1, timeui); - return; + VL_PRINTF_MT("%%Warning: previous dump at t=%" VL_PRI64 "u, requesting t=%" VL_PRI64 "u\n", + m_minNextDumpTime - 1, timeui); + return; } m_minNextDumpTime = timeui + 1; if (VL_UNLIKELY(m_fullDump)) { diff --git a/include/verilated_fst_c.h b/include/verilated_fst_c.h index ffae20875..341514adc 100644 --- a/include/verilated_fst_c.h +++ b/include/verilated_fst_c.h @@ -57,11 +57,11 @@ private: Local2FstDtype m_local2fstdtype; std::list m_curScope; fstHandle* m_symbolp; ///< same as m_code2symbol, but as an array + vluint32_t* m_sigs_oldvalp; // CONSTRUCTORS VL_UNCOPYABLE(VerilatedFst); - void declSymbol(vluint32_t code, const char* name, - int dtypenum, fstVarDir vardir, fstVarType vartype, - bool array, int arraynum, vluint32_t len, vluint32_t bits); + void declSymbol(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir, + fstVarType vartype, bool array, int arraynum, vluint32_t len, vluint32_t bits); // helpers std::vector m_valueStrBuffer; @@ -94,102 +94,108 @@ public: void dump(vluint64_t timeui); /// Inside dumping routines, declare callbacks for tracings void addCallback(VerilatedFstCallback_t initcb, VerilatedFstCallback_t fullcb, - VerilatedFstCallback_t changecb, - void* userthis) VL_MT_UNSAFE_ONE; + VerilatedFstCallback_t changecb, void* userthis) VL_MT_UNSAFE_ONE; /// Inside dumping routines, declare a module void module(const std::string& name); /// Inside dumping routines, declare a data type void declDTypeEnum(int dtypenum, const char* name, vluint32_t elements, - unsigned int minValbits, - const char** itemNamesp, const char** itemValuesp); + unsigned int minValbits, const char** itemNamesp, const char** itemValuesp); /// Inside dumping routines, declare a signal - void declBit(vluint32_t code, const char* name, - int dtypenum, fstVarDir vardir, fstVarType vartype, - bool array, int arraynum) { + void declBit(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir, + fstVarType vartype, bool array, int arraynum) { declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, 1, 1); } - void declBus(vluint32_t code, const char* name, - int dtypenum, fstVarDir vardir, fstVarType vartype, - bool array, int arraynum, int msb, int lsb) { + void declBus(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir, + fstVarType vartype, bool array, int arraynum, int msb, int lsb) { declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, msb - lsb + 1, msb - lsb + 1); } - void declDouble(vluint32_t code, const char* name, - int dtypenum, fstVarDir vardir, fstVarType vartype, - bool array, int arraynum) { - declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, 2, 64); + void declQuad(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir, + fstVarType vartype, bool array, int arraynum, int msb, int lsb) { + declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, msb - lsb + 1, + msb - lsb + 1); } - void declFloat(vluint32_t code, const char* name, - int dtypenum, fstVarDir vardir, fstVarType vartype, - bool array, int arraynum) { + void declArray(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir, + fstVarType vartype, bool array, int arraynum, int msb, int lsb) { + declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, msb - lsb + 1, + msb - lsb + 1); + } + void declFloat(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir, + fstVarType vartype, bool array, int arraynum) { declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, 1, 32); } - void declQuad(vluint32_t code, const char* name, - int dtypenum, fstVarDir vardir, fstVarType vartype, - bool array, int arraynum, int msb, int lsb) { - declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, msb - lsb + 1, - msb - lsb + 1); - } - void declArray(vluint32_t code, const char* name, - int dtypenum, fstVarDir vardir, fstVarType vartype, - bool array, int arraynum, int msb, int lsb) { - declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, msb - lsb + 1, - msb - lsb + 1); + void declDouble(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir, + fstVarType vartype, bool array, int arraynum) { + declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, 2, 64); } - /// Inside dumping routines, dump one signal if it has changed - void chgBit(vluint32_t code, const vluint32_t newval) { - fstWriterEmitValueChange(m_fst, m_symbolp[code], newval ? "1" : "0"); + //========================================================================= + // Inside dumping routines used by Verilator + + vluint32_t* oldp(vluint32_t code) { return m_sigs_oldvalp + code; } + + //========================================================================= + // Write back to previous value buffer value and emit + + void fullBit(vluint32_t* oldp, vluint32_t newval) { + *oldp = newval; + fstWriterEmitValueChange(m_fst, m_symbolp[oldp - m_sigs_oldvalp], newval ? "1" : "0"); } - void chgBus(vluint32_t code, const vluint32_t newval, int bits) { - fstWriterEmitValueChange32(m_fst, m_symbolp[code], bits, newval); + template void fullBus(vluint32_t* oldp, vluint32_t newval) { + *oldp = newval; + fstWriterEmitValueChange32(m_fst, m_symbolp[oldp - m_sigs_oldvalp], T_Bits, newval); } - void chgDouble(vluint32_t code, const double newval) { - double val = newval; - fstWriterEmitValueChange(m_fst, m_symbolp[code], &val); + void fullQuad(vluint32_t* oldp, vluint64_t newval, int bits) { + *reinterpret_cast(oldp) = newval; + fstWriterEmitValueChange64(m_fst, m_symbolp[oldp - m_sigs_oldvalp], bits, newval); } - void chgFloat(vluint32_t code, const float newval) { - double val = (double)newval; - fstWriterEmitValueChange(m_fst, m_symbolp[code], &val); + void fullArray(vluint32_t* oldp, const vluint32_t* newvalp, int bits) { + for (int i = 0; i < (bits + 31) / 32; ++i) oldp[i] = newvalp[i]; + fstWriterEmitValueChangeVec32(m_fst, m_symbolp[oldp - m_sigs_oldvalp], bits, newvalp); } - void chgQuad(vluint32_t code, const vluint64_t newval, int bits) { - fstWriterEmitValueChange64(m_fst, m_symbolp[code], bits, newval); + void fullFloat(vluint32_t* oldp, float newval) { + // cppcheck-suppress invalidPointerCast + *reinterpret_cast(oldp) = newval; + fstWriterEmitValueChange(m_fst, m_symbolp[oldp - m_sigs_oldvalp], oldp); } - void chgArray(vluint32_t code, const vluint32_t* newval, int bits) { - fstWriterEmitValueChangeVec32(m_fst, m_symbolp[code], bits, newval); + void fullDouble(vluint32_t* oldp, double newval) { + // cppcheck-suppress invalidPointerCast + *reinterpret_cast(oldp) = newval; + fstWriterEmitValueChange(m_fst, m_symbolp[oldp - m_sigs_oldvalp], oldp); } - void fullBit(vluint32_t code, const vluint32_t newval) { chgBit(code, newval); } - void fullBus(vluint32_t code, const vluint32_t newval, int bits) { - chgBus(code, newval, bits); - } - void fullDouble(vluint32_t code, const double newval) { chgDouble(code, newval); } - void fullFloat(vluint32_t code, const float newval) { chgFloat(code, newval); } - void fullQuad(vluint32_t code, const vluint64_t newval, int bits) { - chgQuad(code, newval, bits); - } - void fullArray(vluint32_t code, const vluint32_t* newval, int bits) { - chgArray(code, newval, bits); - } + //========================================================================= + // Check previous value and emit if changed - void declTriBit(vluint32_t code, const char* name, int arraynum); - void declTriBus(vluint32_t code, const char* name, int arraynum, int msb, int lsb); - void declTriQuad(vluint32_t code, const char* name, int arraynum, int msb, int lsb); - void declTriArray(vluint32_t code, const char* name, int arraynum, int msb, int lsb); - void fullTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri); - void fullTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits); - void fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits); - void fullTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip, - int bits); - void fullBitX(vluint32_t code); - void fullBusX(vluint32_t code, int bits); - void fullQuadX(vluint32_t code, int bits); - void fullArrayX(vluint32_t code, int bits); - void chgTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri); - void chgTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits); - void chgTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits); - void chgTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip, int bits); + inline void chgBit(vluint32_t* oldp, vluint32_t newval) { + const vluint32_t diff = *oldp ^ newval; + if (VL_UNLIKELY(diff)) fullBit(oldp, newval); + } + template inline void chgBus(vluint32_t* oldp, vluint32_t newval) { + const vluint32_t diff = *oldp ^ newval; + if (VL_UNLIKELY(diff)) fullBus(oldp, newval); + } + inline void chgQuad(vluint32_t* oldp, vluint64_t newval, int bits) { + const vluint64_t diff = *reinterpret_cast(oldp) ^ newval; + if (VL_UNLIKELY(diff)) fullQuad(oldp, newval, bits); + } + inline void chgArray(vluint32_t* oldp, const vluint32_t* newvalp, int bits) { + for (int i = 0; i < (bits + 31) / 32; ++i) { + if (VL_UNLIKELY(oldp[i] ^ newvalp[i])) { + fullArray(oldp, newvalp, bits); + return; + } + } + } + inline void chgFloat(vluint32_t* oldp, float newval) { + // cppcheck-suppress invalidPointerCast + if (VL_UNLIKELY(*reinterpret_cast(oldp) != newval)) fullFloat(oldp, newval); + } + inline void chgDouble(vluint32_t* oldp, double newval) { + // cppcheck-suppress invalidPointerCast + if (VL_UNLIKELY(*reinterpret_cast(oldp) != newval)) fullDouble(oldp, newval); + } }; //============================================================================= diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index 62b6c33cd..d5bde2a92 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -17,6 +17,8 @@ //============================================================================= // SPDIFF_OFF +// clang-format off + #include "verilatedos.h" #include "verilated.h" #include "verilated_vcd_c.h" @@ -45,6 +47,19 @@ # define O_CLOEXEC 0 #endif +// clang-format on + +// This size comes form VCD allowing use of printable ASCII characters between +// '!' and '~' inclusive, which are a total of 94 different values. Encoding a +// 32 bit code hence needs a maximum of ceil(log94(2**32-1)) == 5 bytes. +#define VL_TRACE_MAX_VCD_CODE_SIZE 5 ///< Maximum length of a VCD string code +// We use 8 bytes per code in a suffix buffer array. +// 1 byte optional separator + VL_TRACE_MAX_VCD_CODE_SIZE bytes for code +// + 1 byte '\n' + 1 byte suffix size. This luckily comes out to a power of 2, +// meaning the array can be aligned such that entries never straddle multiple +// cache-lines. +#define VL_TRACE_SUFFIX_ENTRY_SIZE 8 ///< Size of a suffix entry + //============================================================================= // VerilatedVcdImp /// Base class to hold some static state @@ -57,7 +72,10 @@ private: VerilatedMutex s_vcdMutex; ///< Protect the singleton VcdVec s_vcdVecp VL_GUARDED_BY(s_vcdMutex); ///< List of all created traces }; - static Singleton& singleton() { static Singleton s; return s; } + static Singleton& singleton() { + static Singleton s; + return s; + } public: static void pushVcd(VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) { @@ -152,6 +170,7 @@ VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep) m_wrFlushp = m_wrBufp + m_wrChunkSize * 6; m_writep = m_wrBufp; m_wroteBytes = 0; + m_suffixesp = NULL; } void VerilatedVcd::open(const char* filename) { @@ -175,6 +194,9 @@ void VerilatedVcd::open(const char* filename) { // Allocate space now we know the number of codes if (!m_sigs_oldvalp) m_sigs_oldvalp = new vluint32_t[m_nextCode + 10]; + // Get the direct access pointer to the code strings + m_suffixesp = &m_suffixes[0]; // Note: C++11 m_suffixes.data(); + if (m_rolloverMB) { openNext(true); if (!isOpen()) return; @@ -191,10 +213,8 @@ void VerilatedVcd::openNext(bool incFilename) { std::string name = m_filename; size_t pos = name.rfind('.'); if (pos > 8 && 0 == strncmp("_cat", name.c_str() + pos - 8, 4) - && isdigit(name.c_str()[pos - 4]) - && isdigit(name.c_str()[pos - 3]) - && isdigit(name.c_str()[pos - 2]) - && isdigit(name.c_str()[pos - 1])) { + && isdigit(name.c_str()[pos - 4]) && isdigit(name.c_str()[pos - 3]) + && isdigit(name.c_str()[pos - 2]) && isdigit(name.c_str()[pos - 1])) { // Increment code. if ((++(name[pos - 1])) > '9') { name[pos - 1] = '0'; @@ -404,7 +424,8 @@ void VerilatedVcd::set_time_resolution(const char* unitp) { double VerilatedVcd::timescaleToDouble(const char* unitp) { char* endp; double value = strtod(unitp, &endp); - if (value == 0.0 && endp == unitp) value = 1; // On error so we allow just "ns" to return 1e-9. + // On error so we allow just "ns" to return 1e-9. + if (value == 0.0 && endp == unitp) value = 1; unitp = endp; for (; *unitp && isspace(*unitp); unitp++) {} switch (*unitp) { @@ -421,27 +442,41 @@ double VerilatedVcd::timescaleToDouble(const char* unitp) { std::string VerilatedVcd::doubleToTimescale(double value) { const char* suffixp = "s"; - if (value>=1e0) { suffixp="s"; value *= 1e0; } - else if (value>=1e-3 ) { suffixp="ms"; value *= 1e3; } - else if (value>=1e-6 ) { suffixp="us"; value *= 1e6; } - else if (value>=1e-9 ) { suffixp="ns"; value *= 1e9; } - else if (value>=1e-12) { suffixp="ps"; value *= 1e12; } - else if (value>=1e-15) { suffixp="fs"; value *= 1e15; } - else if (value>=1e-18) { suffixp="as"; value *= 1e18; } + // clang-format off + if (value >= 1e0) { suffixp = "s"; value *= 1e0; } + else if (value >= 1e-3 ) { suffixp = "ms"; value *= 1e3; } + else if (value >= 1e-6 ) { suffixp = "us"; value *= 1e6; } + else if (value >= 1e-9 ) { suffixp = "ns"; value *= 1e9; } + else if (value >= 1e-12) { suffixp = "ps"; value *= 1e12; } + else if (value >= 1e-15) { suffixp = "fs"; value *= 1e15; } + else if (value >= 1e-18) { suffixp = "as"; value *= 1e18; } + // clang-format on char valuestr[100]; sprintf(valuestr, "%3.0f%s", value, suffixp); return valuestr; // Gets converted to string, so no ref to stack } +//============================================================================= +// VCD string code + +char* VerilatedVcd::writeCode(char* writep, vluint32_t code) { + *writep++ = static_cast('!' + code % 94); + code /= 94; + while (code) { + code--; + *writep++ = static_cast('!' + code % 94); + code /= 94; + } + return writep; +} + //============================================================================= // Definitions void VerilatedVcd::printIndent(int level_change) { if (level_change < 0) m_modDepth += level_change; assert(m_modDepth >= 0); - for (int i = 0; i < m_modDepth; i++) { - printStr(" "); - } + for (int i = 0; i < m_modDepth; i++) printStr(" "); if (level_change > 0) m_modDepth += level_change; } @@ -539,8 +574,8 @@ void VerilatedVcd::module(const std::string& name) { m_modName = name; } -void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep, - bool array, int arraynum, bool tri, bool bussed, int msb, int lsb) { +void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep, bool array, + int arraynum, bool tri, bool bussed, int msb, int lsb) { if (!code) { VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: internal trace problem, code 0 is illegal"); } @@ -554,6 +589,9 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep, if (m_sigs.capacity() <= m_nextCode) { m_sigs.reserve(m_nextCode * 2); // Power-of-2 allocation speeds things up } + if (m_suffixes.size() <= m_nextCode * VL_TRACE_SUFFIX_ENTRY_SIZE) { + m_suffixes.resize(m_nextCode * VL_TRACE_SUFFIX_ENTRY_SIZE * 2, 0); + } // Make sure write buffer is large enough (one character per bit), plus header bufferResize(bits + 1024); @@ -601,7 +639,21 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep, sprintf(buf, "<%u", code); decl += buf; } else { - decl += stringCode(code); + // Add string code to decl + char* const endp = writeCode(buf, code); + *endp = '\0'; + decl += buf; + // Build suffix array entry + char* const entryp = &m_suffixes[code * VL_TRACE_SUFFIX_ENTRY_SIZE]; + const size_t length = endp - buf; + assert(length <= VL_TRACE_MAX_VCD_CODE_SIZE); + // 1 bit values don't have a ' ' separator between value and string code + const bool isBit = bits == 1; + entryp[0] = ' '; // Separator + std::strcpy(entryp + !isBit, buf); // Code (overwrite separator if isBit) + entryp[length + !isBit] = '\n'; // Replace '\0' with line termination '\n' + // Set length of suffix (used to increment write pointer) + entryp[VL_TRACE_SUFFIX_ENTRY_SIZE - 1] = !isBit + length + 1; } decl += " "; decl += basename; @@ -633,6 +685,13 @@ void VerilatedVcd::declArray(vluint32_t code, const char* name, bool array, int int lsb) { declare(code, name, "wire", array, arraynum, false, true, msb, lsb); } +void VerilatedVcd::declFloat(vluint32_t code, const char* name, bool array, int arraynum) { + declare(code, name, "real", array, arraynum, false, false, 31, 0); +} +void VerilatedVcd::declDouble(vluint32_t code, const char* name, bool array, int arraynum) { + declare(code, name, "real", array, arraynum, false, false, 63, 0); +} +#ifndef VL_TRACE_VCD_OLD_API void VerilatedVcd::declTriBit(vluint32_t code, const char* name, bool array, int arraynum) { declare(code, name, "wire", array, arraynum, true, false, 0, 0); } @@ -648,20 +707,234 @@ void VerilatedVcd::declTriArray(vluint32_t code, const char* name, bool array, i int msb, int lsb) { declare(code, name, "wire", array, arraynum, true, true, msb, lsb); } -void VerilatedVcd::declFloat(vluint32_t code, const char* name, bool array, int arraynum) { - declare(code, name, "real", array, arraynum, false, false, 31, 0); -} -void VerilatedVcd::declDouble(vluint32_t code, const char* name, bool array, int arraynum) { - declare(code, name, "real", array, arraynum, false, false, 63, 0); -} +#endif // VL_TRACE_VCD_OLD_API //============================================================================= +// Trace recording routines + +#ifndef VL_TRACE_VCD_OLD_API + +//============================================================================= +// Pointer based variants used by Verilator + +// Emit suffix, write back write pointer, check buffer +void VerilatedVcd::finishLine(vluint32_t* oldp, char* writep) { + const vluint32_t code = oldp - m_sigs_oldvalp; + const char* const suffixp = m_suffixesp + code * VL_TRACE_SUFFIX_ENTRY_SIZE; + // Copy the whole suffix (this avoid having hard to predict branches which + // helps a lot). Note suffixp could be aligned, so could load it in one go, + // but then we would be endiannes dependent which we don't have a way to + // test right now and probably would make little difference... + // Note: The maximum length of the suffix is + // VL_TRACE_MAX_VCD_CODE_SIZE + 2 == 7, but we unroll this here for speed. + writep[0] = suffixp[0]; + writep[1] = suffixp[1]; + writep[2] = suffixp[2]; + writep[3] = suffixp[3]; + writep[4] = suffixp[4]; + writep[5] = suffixp[5]; + writep[6] = '\n'; // The 6th index is always '\n' if it's relevant, no need to fetch it. + // Now write back the write pointer incremented by the actual size of the + // suffix, which was stored in the last byte of the suffix buffer entry. + m_writep = writep + suffixp[VL_TRACE_SUFFIX_ENTRY_SIZE - 1]; + bufferCheck(); +} + +void VerilatedVcd::fullBit(vluint32_t* oldp, vluint32_t newval) { + *oldp = newval; + char* wp = m_writep; + *wp++ = '0' | static_cast(newval); + finishLine(oldp, wp); +} + +// We do want these functions specialized for sizes to avoid hard to predict +// branches, but we don't want them inlined, so we explicitly create one +// specialization for each size used here here. + +// T_Bits is the number of used bits in the value +template void VerilatedVcd::fullBus(vluint32_t* oldp, vluint32_t newval) { + *oldp = newval; + char* wp = m_writep; + *wp++ = 'b'; + newval <<= 32 - T_Bits; + int bits = T_Bits; + do { + *wp++ = '0' | static_cast(newval >> 31); + newval <<= 1; + } while (--bits); + finishLine(oldp, wp); +} +// Note: No specialization for width 1, covered by 'fullBit' +template void VerilatedVcd::fullBus<2>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<3>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<4>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<5>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<6>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<7>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<8>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<9>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<10>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<11>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<12>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<13>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<14>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<15>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<16>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<17>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<18>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<19>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<20>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<21>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<22>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<23>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<24>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<25>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<26>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<27>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<28>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<29>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<30>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<31>(vluint32_t* oldp, vluint32_t newval); +template void VerilatedVcd::fullBus<32>(vluint32_t* oldp, vluint32_t newval); + +// T_Bits is the number of used bits in the value +void VerilatedVcd::fullQuad(vluint32_t* oldp, vluint64_t newval, int bits) { + *reinterpret_cast(oldp) = newval; + char* wp = m_writep; + *wp++ = 'b'; + newval <<= 64 - bits; + // Handle the top 32 bits within the 64 bit input + const int bitsInTopHalf = bits - 32; + wp += bitsInTopHalf; + // clang-format off + switch (bitsInTopHalf) { + case 32: wp[-32] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 31: wp[-31] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 30: wp[-30] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 29: wp[-29] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 28: wp[-28] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 27: wp[-27] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 26: wp[-26] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 25: wp[-25] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 24: wp[-24] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 23: wp[-23] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 22: wp[-22] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 21: wp[-21] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 20: wp[-20] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 19: wp[-19] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 18: wp[-18] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 17: wp[-17] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 16: wp[-16] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 15: wp[-15] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 14: wp[-14] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 13: wp[-13] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 12: wp[-12] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 11: wp[-11] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 10: wp[-10] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 9: wp[ -9] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 8: wp[ -8] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 7: wp[ -7] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 6: wp[ -6] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 5: wp[ -5] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 4: wp[ -4] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 3: wp[ -3] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 2: wp[ -2] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + case 1: wp[ -1] = '0' | static_cast(newval >> 63); newval<<=1; //FALLTHRU + } + // clang-format on + // Handle the bottom 32 bits within the 64 bit input + int remaining = 32; + do { + *wp++ = '0' | static_cast(newval >> 63); + newval <<= 1; + } while (--remaining); + finishLine(oldp, wp); +} + +void VerilatedVcd::fullArray(vluint32_t* oldp, const vluint32_t* newvalp, int bits) { + int words = (bits + 31) / 32; + for (int i = 0; i < words; ++i) oldp[i] = newvalp[i]; + char* wp = m_writep; + *wp++ = 'b'; + // Handle the most significant word + const int bitsInMSW = bits % 32 == 0 ? 32 : bits % 32; + vluint32_t val = newvalp[--words] << (32 - bitsInMSW); + wp += bitsInMSW; + // clang-format off + switch (bitsInMSW) { + case 32: wp[-32] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 31: wp[-31] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 30: wp[-30] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 29: wp[-29] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 28: wp[-28] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 27: wp[-27] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 26: wp[-26] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 25: wp[-25] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 24: wp[-24] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 23: wp[-23] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 22: wp[-22] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 21: wp[-21] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 20: wp[-20] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 19: wp[-19] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 18: wp[-18] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 17: wp[-17] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 16: wp[-16] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 15: wp[-15] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 14: wp[-14] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 13: wp[-13] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 12: wp[-12] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 11: wp[-11] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 10: wp[-10] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 9: wp[ -9] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 8: wp[ -8] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 7: wp[ -7] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 6: wp[ -6] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 5: wp[ -5] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 4: wp[ -4] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 3: wp[ -3] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 2: wp[ -2] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + case 1: wp[ -1] = '0' | static_cast(val >> 31); val<<=1; //FALLTHRU + } + // clang-format on + // Handle the remaining words + while (words > 0) { + vluint32_t val = newvalp[--words]; + int bits = 32; + do { + *wp++ = '0' | static_cast(val >> 31); + val <<= 1; + } while (--bits); + } + finishLine(oldp, wp); +} + +void VerilatedVcd::fullFloat(vluint32_t* oldp, float newval) { + // cppcheck-suppress invalidPointerCast + *reinterpret_cast(oldp) = newval; + char* wp = m_writep; + // Buffer can't overflow before sprintf; we sized during declaration + sprintf(wp, "r%.16g", static_cast(newval)); + wp += strlen(wp); + finishLine(oldp, wp); +} + +void VerilatedVcd::fullDouble(vluint32_t* oldp, double newval) { + // cppcheck-suppress invalidPointerCast + *reinterpret_cast(oldp) = newval; + char* wp = m_writep; + // Buffer can't overflow before sprintf; we sized during declaration + sprintf(wp, "r%.16g", newval); + wp += strlen(wp); + finishLine(oldp, wp); +} + +#else // VL_TRACE_VCD_OLD_API void VerilatedVcd::fullBit(vluint32_t code, const vluint32_t newval) { // Note the &1, so we don't require clean input -- makes more common no change case faster m_sigs_oldvalp[code] = newval; *m_writep++ = ('0' + static_cast(newval & 1)); - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } @@ -672,7 +945,7 @@ void VerilatedVcd::fullBus(vluint32_t code, const vluint32_t newval, int bits) { *m_writep++ = ((newval & (1L << bit)) ? '1' : '0'); } *m_writep++ = ' '; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } @@ -683,7 +956,7 @@ void VerilatedVcd::fullQuad(vluint32_t code, const vluint64_t newval, int bits) *m_writep++ = ((newval & (VL_ULL(1) << bit)) ? '1' : '0'); } *m_writep++ = ' '; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } @@ -696,7 +969,7 @@ void VerilatedVcd::fullArray(vluint32_t code, const vluint32_t* newval, int bits *m_writep++ = ((newval[(bit / 32)] & (1L << (bit & 0x1f))) ? '1' : '0'); } *m_writep++ = ' '; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } @@ -709,7 +982,7 @@ void VerilatedVcd::fullArray(vluint32_t code, const vluint64_t* newval, int bits *m_writep++ = ((newval[(bit / 64)] & (VL_ULL(1) << (bit & 0x3f))) ? '1' : '0'); } *m_writep++ = ' '; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } @@ -717,11 +990,12 @@ void VerilatedVcd::fullTriBit(vluint32_t code, const vluint32_t newval, const vl m_sigs_oldvalp[code] = newval; m_sigs_oldvalp[code + 1] = newtri; *m_writep++ = "01zz"[m_sigs_oldvalp[code] | (m_sigs_oldvalp[code + 1] << 1)]; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } -void VerilatedVcd::fullTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits) { +void VerilatedVcd::fullTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, + int bits) { m_sigs_oldvalp[code] = newval; m_sigs_oldvalp[code + 1] = newtri; *m_writep++ = 'b'; @@ -729,25 +1003,26 @@ void VerilatedVcd::fullTriBus(vluint32_t code, const vluint32_t newval, const vl *m_writep++ = "01zz"[((newval >> bit) & 1) | (((newtri >> bit) & 1) << 1)]; } *m_writep++ = ' '; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } -void VerilatedVcd::fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits) { +void VerilatedVcd::fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri, + int bits) { (*(reinterpret_cast(&m_sigs_oldvalp[code]))) = newval; (*(reinterpret_cast(&m_sigs_oldvalp[code + 1]))) = newtri; *m_writep++ = 'b'; for (int bit = bits - 1; bit >= 0; --bit) { - *m_writep++ = "01zz"[((newval >> bit) & VL_ULL(1)) - | (((newtri >> bit) & VL_ULL(1)) << VL_ULL(1))]; + *m_writep++ + = "01zz"[((newval >> bit) & VL_ULL(1)) | (((newtri >> bit) & VL_ULL(1)) << VL_ULL(1))]; } *m_writep++ = ' '; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } -void VerilatedVcd::fullTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip, - int bits) { +void VerilatedVcd::fullTriArray(vluint32_t code, const vluint32_t* newvalp, + const vluint32_t* newtrip, int bits) { for (int word = 0; word < (((bits - 1) / 32) + 1); ++word) { m_sigs_oldvalp[code + word * 2] = newvalp[word]; m_sigs_oldvalp[code + word * 2 + 1] = newtrip[word]; @@ -759,7 +1034,7 @@ void VerilatedVcd::fullTriArray(vluint32_t code, const vluint32_t* newvalp, cons *m_writep++ = "01zz"[valbit | (tribit << 1)]; } *m_writep++ = ' '; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } @@ -770,7 +1045,7 @@ void VerilatedVcd::fullDouble(vluint32_t code, const double newval) { sprintf(m_writep, "r%.16g", newval); m_writep += strlen(m_writep); *m_writep++ = ' '; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } @@ -781,29 +1056,29 @@ void VerilatedVcd::fullFloat(vluint32_t code, const float newval) { sprintf(m_writep, "r%.16g", static_cast(newval)); m_writep += strlen(m_writep); *m_writep++ = ' '; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } void VerilatedVcd::fullBitX(vluint32_t code) { *m_writep++ = 'x'; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } void VerilatedVcd::fullBusX(vluint32_t code, int bits) { *m_writep++ = 'b'; - for (int bit = bits - 1; bit >= 0; --bit) { - *m_writep++ = 'x'; - } + for (int bit = bits - 1; bit >= 0; --bit) *m_writep++ = 'x'; *m_writep++ = ' '; - printCode(code); + m_writep = writeCode(m_writep, code); *m_writep++ = '\n'; bufferCheck(); } void VerilatedVcd::fullQuadX(vluint32_t code, int bits) { fullBusX(code, bits); } void VerilatedVcd::fullArrayX(vluint32_t code, int bits) { fullBusX(code, bits); } +#endif // VL_TRACE_VCD_OLD_API + //============================================================================= // Callbacks @@ -867,6 +1142,8 @@ void VerilatedVcd::flush_all() VL_MT_UNSAFE_ONE { VerilatedVcdSingleton::flush_a //====================================================================== //====================================================================== +// clang-format off + #ifdef VERILATED_VCD_TEST #include diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h index 24257e5b6..95128bba6 100644 --- a/include/verilated_vcd_c.h +++ b/include/verilated_vcd_c.h @@ -97,6 +97,9 @@ private: vluint64_t m_wrChunkSize; ///< Output buffer size vluint64_t m_wroteBytes; ///< Number of bytes written to this file + std::vector m_suffixes; ///< VCD line end string codes + metadata + const char* m_suffixesp; ///< Pointer to first element of above + vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values typedef std::vector SigVec; SigVec m_sigs; ///< Pointer to signal information @@ -131,26 +134,9 @@ private: void dumpFull(vluint64_t timeui); // cppcheck-suppress functionConst void dumpDone(); - inline void printCode(vluint32_t code) { - *m_writep++ = static_cast('!' + code % 94); - code /= 94; - while (code) { - code--; - *m_writep++ = static_cast('!' + code % 94); - code /= 94; - } - } - static std::string stringCode(vluint32_t code) VL_PURE { - std::string out; - out += static_cast('!' + code % 94); - code /= 94; - while (code) { - code--; - out += static_cast('!' + code % 94); - code /= 94; - } - return out; - } + char* writeCode(char* writep, vluint32_t code); + + void finishLine(vluint32_t* oldp, char* writep); // CONSTRUCTORS VL_UNCOPYABLE(VerilatedVcd); @@ -206,27 +192,116 @@ public: void declBus(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declQuad(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declArray(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); + void declFloat(vluint32_t code, const char* name, bool array, int arraynum); + void declDouble(vluint32_t code, const char* name, bool array, int arraynum); +#ifndef VL_TRACE_VCD_OLD_API void declTriBit(vluint32_t code, const char* name, bool array, int arraynum); void declTriBus(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declTriQuad(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declTriArray(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); - void declDouble(vluint32_t code, const char* name, bool array, int arraynum); - void declFloat(vluint32_t code, const char* name, bool array, int arraynum); +#endif // VL_TRACE_VCD_OLD_API // ... other module_start for submodules (based on cell name) + //========================================================================= + // Inside dumping routines used by Verilator + + vluint32_t* oldp(vluint32_t code) { return m_sigs_oldvalp + code; } + +#ifndef VL_TRACE_VCD_OLD_API + + //========================================================================= + // Write back to previous value buffer value and emit + + void fullBit(vluint32_t* oldp, vluint32_t newval); + template void fullBus(vluint32_t* oldp, vluint32_t newval); + void fullQuad(vluint32_t* oldp, vluint64_t newval, int bits); + void fullArray(vluint32_t* oldp, const vluint32_t* newvalp, int bits); + void fullFloat(vluint32_t* oldp, float newval); + void fullDouble(vluint32_t* oldp, double newval); + + //========================================================================= + // Check previous value and emit if changed + + inline void chgBit(vluint32_t* oldp, vluint32_t newval) { + const vluint32_t diff = *oldp ^ newval; + if (VL_UNLIKELY(diff)) fullBit(oldp, newval); + } + template inline void chgBus(vluint32_t* oldp, vluint32_t newval) { + const vluint32_t diff = *oldp ^ newval; + if (VL_UNLIKELY(diff)) fullBus(oldp, newval); + } + inline void chgQuad(vluint32_t* oldp, vluint64_t newval, int bits) { + const vluint64_t diff = *reinterpret_cast(oldp) ^ newval; + if (VL_UNLIKELY(diff)) fullQuad(oldp, newval, bits); + } + inline void chgArray(vluint32_t* oldp, const vluint32_t* newvalp, int bits) { + for (int i = 0; i < (bits + 31) / 32; ++i) { + if (VL_UNLIKELY(oldp[i] ^ newvalp[i])) { + fullArray(oldp, newvalp, bits); + return; + } + } + } + inline void chgFloat(vluint32_t* oldp, float newval) { + // cppcheck-suppress invalidPointerCast + if (VL_UNLIKELY(*reinterpret_cast(oldp) != newval)) fullFloat(oldp, newval); + } + inline void chgDouble(vluint32_t* oldp, double newval) { + // cppcheck-suppress invalidPointerCast + if (VL_UNLIKELY(*reinterpret_cast(oldp) != newval)) fullDouble(oldp, newval); + } + +#else // VL_TRACE_VCD_OLD_API + + // Note: These are only for testing for backward compatibility. Verilator + // should use the more efficient versions above. + + //========================================================================= + // Write back to previous value buffer value and emit + + void fullBit(vluint32_t* oldp, vluint32_t newval) { fullBit(oldp - m_sigs_oldvalp, newval); } + template void fullBus(vluint32_t* oldp, vluint32_t newval) { + fullBus(oldp - m_sigs_oldvalp, newval, T_Bits); + } + void fullQuad(vluint32_t* oldp, vluint64_t newval, int bits) { + fullQuad(oldp - m_sigs_oldvalp, newval, bits); + } + void fullArray(vluint32_t* oldp, const vluint32_t* newvalp, int bits) { + fullArray(oldp - m_sigs_oldvalp, newvalp, bits); + } + void fullFloat(vluint32_t* oldp, float newval) { fullFloat(oldp - m_sigs_oldvalp, newval); } + void fullDouble(vluint32_t* oldp, double newval) { fullDouble(oldp - m_sigs_oldvalp, newval); } + + //========================================================================= + // Check previous value and emit if changed + + void chgBit(vluint32_t* oldp, vluint32_t newval) { chgBit(oldp - m_sigs_oldvalp, newval); } + template void chgBus(vluint32_t* oldp, vluint32_t newval) { + chgBus(oldp - m_sigs_oldvalp, newval, T_Bits); + } + void chgQuad(vluint32_t* oldp, vluint64_t newval, int bits) { + chgQuad(oldp - m_sigs_oldvalp, newval, bits); + } + void chgArray(vluint32_t* oldp, const vluint32_t* newvalp, int bits) { + chgArray(oldp - m_sigs_oldvalp, newvalp, bits); + } + void chgFloat(vluint32_t* oldp, float newval) { chgFloat(oldp - m_sigs_oldvalp, newval); } + void chgDouble(vluint32_t* oldp, double newval) { chgDouble(oldp - m_sigs_oldvalp, newval); } + /// Inside dumping routines, dump one signal, faster when not inlined /// due to code size reduction. void fullBit(vluint32_t code, const vluint32_t newval); void fullBus(vluint32_t code, const vluint32_t newval, int bits); void fullQuad(vluint32_t code, const vluint64_t newval, int bits); - void fullArray(vluint32_t code, const vluint32_t* newval, int bits); - void fullArray(vluint32_t code, const vluint64_t* newval, int bits); + void fullArray(vluint32_t code, const vluint32_t* newvalp, int bits); + void fullArray(vluint32_t code, const vluint64_t* newvalp, int bits); void fullTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri); void fullTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits); void fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits); - void fullTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip, int bits); + void fullTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip, + int bits); void fullDouble(vluint32_t code, const double newval); void fullFloat(vluint32_t code, const float newval); @@ -243,9 +318,7 @@ public: /// We do want to inline these to avoid calls when the value did not change. inline void chgBit(vluint32_t code, const vluint32_t newval) { vluint32_t diff = m_sigs_oldvalp[code] ^ newval; - if (VL_UNLIKELY(diff)) { - fullBit(code, newval); - } + if (VL_UNLIKELY(diff)) fullBit(code, newval); } inline void chgBus(vluint32_t code, const vluint32_t newval, int bits) { vluint32_t diff = m_sigs_oldvalp[code] ^ newval; @@ -263,18 +336,18 @@ public: } } } - inline void chgArray(vluint32_t code, const vluint32_t* newval, int bits) { + inline void chgArray(vluint32_t code, const vluint32_t* newvalp, int bits) { for (int word = 0; word < (((bits - 1) / 32) + 1); ++word) { - if (VL_UNLIKELY(m_sigs_oldvalp[code + word] ^ newval[word])) { - fullArray(code, newval, bits); + if (VL_UNLIKELY(m_sigs_oldvalp[code + word] ^ newvalp[word])) { + fullArray(code, newvalp, bits); return; } } } - inline void chgArray(vluint32_t code, const vluint64_t* newval, int bits) { + inline void chgArray(vluint32_t code, const vluint64_t* newvalp, int bits) { for (int word = 0; word < (((bits - 1) / 64) + 1); ++word) { - if (VL_UNLIKELY(m_sigs_oldvalp[code + word] ^ newval[word])) { - fullArray(code, newval, bits); + if (VL_UNLIKELY(m_sigs_oldvalp[code + word] ^ newvalp[word])) { + fullArray(code, newvalp, bits); return; } } @@ -332,6 +405,8 @@ public: } } +#endif // VL_TRACE_VCD_OLD_API + protected: // METHODS void evcd(bool flag) { m_evcd = flag; } diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 46d6bd05e..a55d02d81 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -3100,6 +3100,7 @@ class EmitCTrace : EmitCStmts { AstCFunc* m_funcp; // Function we're in now bool m_slow; // Making slow file int m_enumNum; // Enumeration number (whole netlist) + int m_baseCode; // Code of first AstTraceInc in this function // METHODS void newOutCFile(int filenum) { @@ -3380,28 +3381,24 @@ class EmitCTrace : EmitCStmts { ? "full":"chg"); bool emitWidth = false; if (nodep->dtypep()->basicp()->isDouble()) { - puts("vcdp->"+full+"Double"); + puts("vcdp->" + full + "Double"); } else if (nodep->isWide() || emitTraceIsScBv(nodep) || emitTraceIsScBigUint(nodep)) { - puts("vcdp->"+full+"Array"); + puts("vcdp->" + full + "Array"); emitWidth = true; } else if (nodep->isQuad()) { - puts("vcdp->"+full+"Quad"); - emitWidth = true; - } else if (nodep->declp()->bitRange().ranged() - // 1 element smaller to use Bit dump - && nodep->declp()->bitRange().elements() != 1) { - puts("vcdp->"+full+"Bus"); + puts("vcdp->" + full + "Quad"); emitWidth = true; + } else if (nodep->declp()->widthMin() > 1) { + puts("vcdp->" + full + "Bus<" + cvtToStr(nodep->declp()->widthMin()) + ">"); } else { - puts("vcdp->"+full+"Bit"); + puts("vcdp->" + full + "Bit"); } - puts("(c+"+cvtToStr(nodep->declp()->code() - + ((arrayindex<0) ? 0 : (arrayindex*nodep->declp()->widthWords())))); - puts(","); + + const uint32_t offset = (arrayindex < 0) ? 0 : (arrayindex * nodep->declp()->widthWords()); + const uint32_t code = nodep->declp()->code() + offset; + puts("(oldp+" + cvtToStr(code - m_baseCode) + ","); emitTraceValue(nodep, arrayindex); - if (emitWidth) { - puts(","+cvtToStr(nodep->declp()->widthMin())); - } + if (emitWidth) puts("," + cvtToStr(nodep->declp()->widthMin())); puts(");\n"); } void emitTraceValue(AstTraceInc* nodep, int arrayindex) { @@ -3460,8 +3457,24 @@ class EmitCTrace : EmitCStmts { if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign()+"\n"); - puts("int c = code;\n"); - puts("if (false && vcdp && c) {} // Prevent unused\n"); + m_baseCode = -1; + + if (nodep->funcType() == AstCFuncType::TRACE_FULL_SUB + || nodep->funcType() == AstCFuncType::TRACE_CHANGE_SUB) { + const AstTraceInc* const stmtp = VN_CAST_CONST(nodep->stmtsp(), TraceInc); + if (!stmtp) { + nodep->stmtsp()->v3fatalSrc("Trace sub function should contain AstTraceInc"); + } + m_baseCode = stmtp->declp()->code(); + puts("vluint32_t* oldp = vcdp->oldp(code+" + cvtToStr(m_baseCode) + ");\n"); + puts("if (false && vcdp && oldp) {} // Prevent unused\n"); + } else if (nodep->funcType() == AstCFuncType::TRACE_INIT_SUB) { + puts("int c = code;\n"); + puts("if (false && vcdp && c) {} // Prevent unused\n"); + } else { + puts("if (false && vcdp) {} // Prevent unused\n"); + } + if (nodep->funcType() == AstCFuncType::TRACE_INIT) { puts("vcdp->module(vlSymsp->name()); // Setup signal names\n"); } else if (nodep->funcType() == AstCFuncType::TRACE_INIT_SUB) { diff --git a/test_regress/t/t_trace_complex_fst.out b/test_regress/t/t_trace_complex_fst.out index 57e86c1b7..7ceb73591 100644 --- a/test_regress/t/t_trace_complex_fst.out +++ b/test_regress/t/t_trace_complex_fst.out @@ -1,5 +1,5 @@ $date - Tue Jan 21 18:08:49 2020 + Sun Apr 12 20:15:55 2020 $end $version @@ -101,7 +101,6 @@ b00000000000000000000000000000011 A #10 b00000000000000000000000000000101 ? b00000000000000000000000000000101 > -b000000 : b111 9 b00000000000000000000000000000010 8 b00000000000000000000000000000001 7 @@ -144,14 +143,10 @@ b00000000000000000000000000000010 7 b00000000000000000000000000000100 8 b110 9 b111111 : -b00000000000000000000000000000101 > -b00000000000000000000000000000101 ? #25 0! #30 1! -b00000000000000000000000000000101 ? -b00000000000000000000000000000101 > b110110 : b101 9 b00000000000000000000000000000110 8 @@ -194,14 +189,10 @@ b00000000000000000000000000000100 7 b00000000000000000000000000001000 8 b100 9 b101101 : -b00000000000000000000000000000101 > -b00000000000000000000000000000101 ? #45 0! #50 1! -b00000000000000000000000000000101 ? -b00000000000000000000000000000101 > b100100 : b011 9 b00000000000000000000000000001010 8 @@ -244,5 +235,3 @@ b00000000000000000000000000000110 7 b00000000000000000000000000001100 8 b010 9 b011011 : -b00000000000000000000000000000101 > -b00000000000000000000000000000101 ? diff --git a/test_regress/t/t_trace_complex_old_api.pl b/test_regress/t/t_trace_complex_old_api.pl new file mode 100755 index 000000000..6041f09c2 --- /dev/null +++ b/test_regress/t/t_trace_complex_old_api.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +# Same test as t_trace_complex, but exercising the old VCD tracing API + +scenarios(simulator => 1); + +top_filename("t/t_trace_complex.v"); + +compile( + verilator_flags2 => ['--cc --trace -CFLAGS -DVL_TRACE_VCD_OLD_API'], + ); + +execute( + check_finished => 1, + ); + +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_strp /); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_strp_strp /); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arrp /); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arrp_arrp /); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arrp_strp /); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru\(/); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru_arru\(/); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru_arrp\(/); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru_strp\(/); + +vcd_identical ("$Self->{obj_dir}/simx.vcd", "t/t_trace_complex.out"); + +ok(1); +1; diff --git a/test_regress/t/t_trace_complex_params_fst.out b/test_regress/t/t_trace_complex_params_fst.out index 1dc90cb57..63f837f52 100644 --- a/test_regress/t/t_trace_complex_params_fst.out +++ b/test_regress/t/t_trace_complex_params_fst.out @@ -1,5 +1,5 @@ $date - Tue Jan 21 18:15:28 2020 + Sun Apr 12 20:17:15 2020 $end $version @@ -101,7 +101,6 @@ b00000000000000000000000000000011 A #10 b00000000000000000000000000000101 ? b00000000000000000000000000000101 > -b000000 : b111 9 b00000000000000000000000000000010 8 b00000000000000000000000000000001 7 @@ -144,14 +143,10 @@ b00000000000000000000000000000010 7 b00000000000000000000000000000100 8 b110 9 b111111 : -b00000000000000000000000000000101 > -b00000000000000000000000000000101 ? #25 0! #30 1! -b00000000000000000000000000000101 ? -b00000000000000000000000000000101 > b110110 : b101 9 b00000000000000000000000000000110 8 @@ -194,14 +189,10 @@ b00000000000000000000000000000100 7 b00000000000000000000000000001000 8 b100 9 b101101 : -b00000000000000000000000000000101 > -b00000000000000000000000000000101 ? #45 0! #50 1! -b00000000000000000000000000000101 ? -b00000000000000000000000000000101 > b100100 : b011 9 b00000000000000000000000000001010 8 @@ -244,5 +235,3 @@ b00000000000000000000000000000110 7 b00000000000000000000000000001100 8 b010 9 b011011 : -b00000000000000000000000000000101 > -b00000000000000000000000000000101 ? diff --git a/test_regress/t/t_trace_complex_structs_fst.out b/test_regress/t/t_trace_complex_structs_fst.out index fd26fc14c..8319f05a6 100644 --- a/test_regress/t/t_trace_complex_structs_fst.out +++ b/test_regress/t/t_trace_complex_structs_fst.out @@ -1,5 +1,5 @@ $date - Tue Jan 21 18:55:14 2020 + Sun Apr 12 20:14:19 2020 $end $version @@ -151,8 +151,6 @@ b00000000000000000000000000000000 L #10 b00000000000000000000000000000101 L b00000000000000000000000000000101 K -b000 G -b000 F b111 E b00000000000000000000000000000010 D b00000000000000000000000000000001 C @@ -218,18 +216,14 @@ b00000000000000000000000000000010 B b00000000000000000000000000000010 C b00000000000000000000000000000100 D b110 E -b111 F b111 G -b00000000000000000000000000000101 K -b00000000000000000000000000000101 L +b111 F #25 0! #30 1! -b00000000000000000000000000000101 L -b00000000000000000000000000000101 K -b110 G b110 F +b110 G b101 E b00000000000000000000000000000110 D b00000000000000000000000000000011 C @@ -294,18 +288,14 @@ b00000000000000000000000000000100 B b00000000000000000000000000000100 C b00000000000000000000000000001000 D b100 E -b101 F b101 G -b00000000000000000000000000000101 K -b00000000000000000000000000000101 L +b101 F #45 0! #50 1! -b00000000000000000000000000000101 L -b00000000000000000000000000000101 K -b100 G b100 F +b100 G b011 E b00000000000000000000000000001010 D b00000000000000000000000000000101 C @@ -370,7 +360,5 @@ b00000000000000000000000000000110 B b00000000000000000000000000000110 C b00000000000000000000000000001100 D b010 E -b011 F b011 G -b00000000000000000000000000000101 K -b00000000000000000000000000000101 L +b011 F diff --git a/test_regress/t/t_trace_fst.out b/test_regress/t/t_trace_fst.out index d6453e931..0a3805543 100644 --- a/test_regress/t/t_trace_fst.out +++ b/test_regress/t/t_trace_fst.out @@ -1,5 +1,5 @@ $date - Tue Nov 5 20:18:53 2019 + Sun Apr 12 20:17:58 2020 $end $version @@ -82,1398 +82,947 @@ b00000000000000000000000000000000 : b00000000000000000000000000000000 ; #10 b00000000000000000000000000000011 ; -b00000000000000000000000000000000 : b00001 9 b00001 8 b00001 7 b10100 6 -0$ b00000000000000000000000000000001 # b00001 " 1! #15 0! -b00001 " #20 -b00001 " 1! b00000000000000000000000000000010 # -0$ -b10100 6 -b00001 7 -b00001 8 -b00001 9 -b00000000000000000000000000000000 : -b00000000000000000000000000000011 ; #25 0! -b00001 " #30 -b00001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000000 : -b00001 9 -b00001 8 -b00001 7 -b10100 6 -0$ b00000000000000000000000000000011 # #35 0! -b00001 " #40 -b00001 " 1! b00000000000000000000000000000100 # -0$ -b10100 6 -b00001 7 -b00001 8 -b00001 9 -b00000000000000000000000000000000 : -b00000000000000000000000000000011 ; #45 0! -b00001 " #50 -b00001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000000 : -b00001 9 -b00001 8 -b00001 7 -b10100 6 -0$ b00000000000000000000000000000101 # #55 0! -b00001 " #60 -b00001 " 1! b00000000000000000000000000000110 # -0$ -b10100 6 -b00001 7 -b00001 8 -b00001 9 -b00000000000000000000000000000000 : -b00000000000000000000000000000011 ; #65 0! -b00001 " #70 -b00001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000000 : -b00001 9 -b00001 8 -b00001 7 -b10100 6 -0$ b00000000000000000000000000000111 # #75 0! -b00001 " #80 -b00001 " 1! b00000000000000000000000000001000 # -0$ -b10100 6 -b00001 7 -b00001 8 -b00001 9 -b00000000000000000000000000000000 : -b00000000000000000000000000000011 ; #85 0! -b00001 " #90 -b00001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000000 : -b00001 9 -b00001 8 -b00001 7 -b10100 6 -0$ b00000000000000000000000000001001 # #95 0! -b00001 " #100 -b00001 " 1! b00000000000000000000000000001010 # -0$ -b10100 6 -b00001 7 -b00001 8 -b00001 9 -b00000000000000000000000000000000 : -b00000000000000000000000000000011 ; #105 0! -b00001 " #110 -b00001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000000 : -b00001 9 -b00001 8 -b00001 7 -b10100 6 -1$ b00000000000000000000000000001011 # +1$ #115 0! -b00001 " #120 -b00001 " 1! b00000000000000000000000000001100 # -1$ b01010 6 -b00001 7 -b00001 8 b10100 9 b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; #125 0! -b00001 " #130 -b00001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : b01010 9 -b10100 8 -b00001 7 b00101 6 -1$ b00000000000000000000000000001101 # +b10100 8 #135 0! -b00001 " #140 -b10100 " 1! -b00000000000000000000000000001110 # -1$ -b10110 6 -b10100 7 b01010 8 +b00000000000000000000000000001110 # +b10110 6 b00101 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10100 " +b10100 7 #145 0! -b10100 " #150 -b01010 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10110 9 -b00101 8 b01010 7 +b01010 " +b10110 9 b01011 6 -1$ b00000000000000000000000000001111 # +b00101 8 #155 0! -b01010 " #160 -b00101 " 1! -b00000000000000000000000000010000 # -1$ -b10001 6 -b00101 7 b10110 8 +b00000000000000000000000000010000 # +b10001 6 b01011 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b00101 " +b00101 7 #165 0! -b00101 " #170 -b10110 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10001 9 -b01011 8 b10110 7 +b10110 " +b10001 9 b11100 6 -1$ b00000000000000000000000000010001 # +b01011 8 #175 0! -b10110 " #180 -b01011 " 1! -b00000000000000000000000000010010 # -1$ -b01110 6 -b01011 7 b10001 8 +b00000000000000000000000000010010 # +b01110 6 b11100 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b01011 " +b01011 7 #185 0! -b01011 " #190 -b10001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01110 9 -b11100 8 b10001 7 +b10001 " +b01110 9 b00111 6 -1$ b00000000000000000000000000010011 # +b11100 8 #195 0! -b10001 " #200 -b11100 " 1! -b00000000000000000000000000010100 # -1$ -b10111 6 -b11100 7 b01110 8 +b00000000000000000000000000010100 # +b10111 6 b00111 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11100 " +b11100 7 #205 0! -b11100 " #210 -b01110 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10111 9 -b00111 8 b01110 7 +b01110 " +b10111 9 b11111 6 -1$ b00000000000000000000000000010101 # +b00111 8 #215 0! -b01110 " #220 -b00111 " 1! -b00000000000000000000000000010110 # -1$ -b11011 6 -b00111 7 b10111 8 +b00000000000000000000000000010110 # +b11011 6 b11111 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b00111 " +b00111 7 #225 0! -b00111 " #230 -b10111 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11011 9 -b11111 8 b10111 7 +b10111 " +b11011 9 b11001 6 -1$ b00000000000000000000000000010111 # +b11111 8 #235 0! -b10111 " #240 -b11111 " 1! -b00000000000000000000000000011000 # -1$ -b11000 6 -b11111 7 b11011 8 +b00000000000000000000000000011000 # +b11000 6 b11001 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11111 " +b11111 7 #245 0! -b11111 " #250 -b11011 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11000 9 -b11001 8 b11011 7 +b11011 " +b11000 9 b01100 6 -1$ b00000000000000000000000000011001 # +b11001 8 #255 0! -b11011 " #260 -b11001 " 1! -b00000000000000000000000000011010 # -1$ -b00110 6 -b11001 7 b11000 8 +b00000000000000000000000000011010 # +b00110 6 b01100 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11001 " +b11001 7 #265 0! -b11001 " #270 -b11000 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b00110 9 -b01100 8 b11000 7 +b11000 " +b00110 9 b00011 6 -1$ b00000000000000000000000000011011 # +b01100 8 #275 0! -b11000 " #280 -b01100 " 1! -b00000000000000000000000000011100 # -1$ -b10101 6 -b01100 7 b00110 8 +b00000000000000000000000000011100 # +b10101 6 b00011 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b01100 " +b01100 7 #285 0! -b01100 " #290 -b00110 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10101 9 -b00011 8 b00110 7 +b00110 " +b10101 9 b11110 6 -1$ b00000000000000000000000000011101 # +b00011 8 #295 0! -b00110 " #300 -b00011 " 1! -b00000000000000000000000000011110 # -1$ -b01111 6 -b00011 7 b10101 8 +b00000000000000000000000000011110 # +b01111 6 b11110 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b00011 " +b00011 7 #305 0! -b00011 " #310 -b10101 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01111 9 -b11110 8 b10101 7 +b10101 " +b01111 9 b10011 6 -1$ b00000000000000000000000000011111 # +b11110 8 #315 0! -b10101 " #320 -b11110 " 1! -b00000000000000000000000000100000 # -1$ -b11101 6 -b11110 7 b01111 8 +b00000000000000000000000000100000 # +b11101 6 b10011 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11110 " +b11110 7 #325 0! -b11110 " #330 -b01111 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11101 9 -b10011 8 b01111 7 +b01111 " +b11101 9 b11010 6 -1$ b00000000000000000000000000100001 # +b10011 8 #335 0! -b01111 " #340 -b10011 " 1! -b00000000000000000000000000100010 # -1$ -b01101 6 -b10011 7 b11101 8 +b00000000000000000000000000100010 # +b01101 6 b11010 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10011 " +b10011 7 #345 0! -b10011 " #350 -b11101 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01101 9 -b11010 8 b11101 7 +b11101 " +b01101 9 b10010 6 -1$ b00000000000000000000000000100011 # +b11010 8 #355 0! -b11101 " #360 -b11010 " 1! -b00000000000000000000000000100100 # -1$ -b01001 6 -b11010 7 b01101 8 +b00000000000000000000000000100100 # +b01001 6 b10010 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11010 " +b11010 7 #365 0! -b11010 " #370 -b01101 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01001 9 -b10010 8 b01101 7 +b01101 " +b01001 9 b10000 6 -1$ b00000000000000000000000000100101 # +b10010 8 #375 0! -b01101 " #380 -b10010 " 1! -b00000000000000000000000000100110 # -1$ -b01000 6 -b10010 7 b01001 8 +b00000000000000000000000000100110 # +b01000 6 b10000 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10010 " +b10010 7 #385 0! -b10010 " #390 -b01001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01000 9 -b10000 8 b01001 7 +b01001 " +b01000 9 b00100 6 -1$ b00000000000000000000000000100111 # +b10000 8 #395 0! -b01001 " #400 -b10000 " 1! -b00000000000000000000000000101000 # -1$ -b00010 6 -b10000 7 b01000 8 +b00000000000000000000000000101000 # +b00010 6 b00100 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10000 " +b10000 7 #405 0! -b10000 " #410 -b01000 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b00010 9 -b00100 8 b01000 7 +b01000 " +b00010 9 b00001 6 -1$ b00000000000000000000000000101001 # +b00100 8 #415 0! -b01000 " #420 -b00100 " 1! -b00000000000000000000000000101010 # -1$ -b10100 6 -b00100 7 b00010 8 +b00000000000000000000000000101010 # +b10100 6 b00001 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b00100 " +b00100 7 #425 0! -b00100 " #430 -b00010 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10100 9 -b00001 8 b00010 7 +b00010 " +b10100 9 b01010 6 -1$ b00000000000000000000000000101011 # +b00001 8 #435 0! -b00010 " #440 -b00001 " 1! -b00000000000000000000000000101100 # -1$ -b00101 6 -b00001 7 b10100 8 +b00000000000000000000000000101100 # +b00101 6 b01010 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b00001 " +b00001 7 #445 0! -b00001 " #450 -b10100 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b00101 9 -b01010 8 b10100 7 +b10100 " +b00101 9 b10110 6 -1$ b00000000000000000000000000101101 # +b01010 8 #455 0! -b10100 " #460 -b01010 " 1! -b00000000000000000000000000101110 # -1$ -b01011 6 -b01010 7 b00101 8 +b00000000000000000000000000101110 # +b01011 6 b10110 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b01010 " +b01010 7 #465 0! -b01010 " #470 -b00101 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01011 9 -b10110 8 b00101 7 +b00101 " +b01011 9 b10001 6 -1$ b00000000000000000000000000101111 # +b10110 8 #475 0! -b00101 " #480 -b10110 " 1! -b00000000000000000000000000110000 # -1$ -b11100 6 -b10110 7 b01011 8 +b00000000000000000000000000110000 # +b11100 6 b10001 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10110 " +b10110 7 #485 0! -b10110 " #490 -b01011 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11100 9 -b10001 8 b01011 7 +b01011 " +b11100 9 b01110 6 -1$ b00000000000000000000000000110001 # +b10001 8 #495 0! -b01011 " #500 -b10001 " 1! -b00000000000000000000000000110010 # -1$ -b00111 6 -b10001 7 b11100 8 +b00000000000000000000000000110010 # +b00111 6 b01110 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10001 " +b10001 7 #505 0! -b10001 " #510 -b11100 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b00111 9 -b01110 8 b11100 7 +b11100 " +b00111 9 b10111 6 -1$ b00000000000000000000000000110011 # +b01110 8 #515 0! -b11100 " #520 -b01110 " 1! -b00000000000000000000000000110100 # -1$ -b11111 6 -b01110 7 b00111 8 +b00000000000000000000000000110100 # +b11111 6 b10111 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b01110 " +b01110 7 #525 0! -b01110 " #530 -b00111 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11111 9 -b10111 8 b00111 7 +b00111 " +b11111 9 b11011 6 -1$ b00000000000000000000000000110101 # +b10111 8 #535 0! -b00111 " #540 -b10111 " 1! -b00000000000000000000000000110110 # -1$ -b11001 6 -b10111 7 b11111 8 +b00000000000000000000000000110110 # +b11001 6 b11011 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10111 " +b10111 7 #545 0! -b10111 " #550 -b11111 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11001 9 -b11011 8 b11111 7 +b11111 " +b11001 9 b11000 6 -1$ b00000000000000000000000000110111 # +b11011 8 #555 0! -b11111 " #560 -b11011 " 1! -b00000000000000000000000000111000 # -1$ -b01100 6 -b11011 7 b11001 8 +b00000000000000000000000000111000 # +b01100 6 b11000 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11011 " +b11011 7 #565 0! -b11011 " #570 -b11001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01100 9 -b11000 8 b11001 7 +b11001 " +b01100 9 b00110 6 -1$ b00000000000000000000000000111001 # +b11000 8 #575 0! -b11001 " #580 -b11000 " 1! -b00000000000000000000000000111010 # -1$ -b00011 6 -b11000 7 b01100 8 +b00000000000000000000000000111010 # +b00011 6 b00110 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11000 " +b11000 7 #585 0! -b11000 " #590 -b01100 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b00011 9 -b00110 8 b01100 7 +b01100 " +b00011 9 b10101 6 -1$ b00000000000000000000000000111011 # +b00110 8 #595 0! -b01100 " #600 -b00110 " 1! -b00000000000000000000000000111100 # -1$ -b11110 6 -b00110 7 b00011 8 +b00000000000000000000000000111100 # +b11110 6 b10101 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b00110 " +b00110 7 #605 0! -b00110 " #610 -b00011 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11110 9 -b10101 8 b00011 7 +b00011 " +b11110 9 b01111 6 -1$ b00000000000000000000000000111101 # +b10101 8 #615 0! -b00011 " #620 -b10101 " 1! -b00000000000000000000000000111110 # -1$ -b10011 6 -b10101 7 b11110 8 +b00000000000000000000000000111110 # +b10011 6 b01111 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10101 " +b10101 7 #625 0! -b10101 " #630 -b11110 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10011 9 -b01111 8 b11110 7 +b11110 " +b10011 9 b11101 6 -1$ b00000000000000000000000000111111 # +b01111 8 #635 0! -b11110 " #640 -b01111 " 1! -b00000000000000000000000001000000 # -1$ -b11010 6 -b01111 7 b10011 8 +b00000000000000000000000001000000 # +b11010 6 b11101 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b01111 " +b01111 7 #645 0! -b01111 " #650 -b10011 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11010 9 -b11101 8 b10011 7 +b10011 " +b11010 9 b01101 6 -1$ b00000000000000000000000001000001 # +b11101 8 #655 0! -b10011 " #660 -b11101 " 1! -b00000000000000000000000001000010 # -1$ -b10010 6 -b11101 7 b11010 8 +b00000000000000000000000001000010 # +b10010 6 b01101 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11101 " +b11101 7 #665 0! -b11101 " #670 -b11010 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10010 9 -b01101 8 b11010 7 +b11010 " +b10010 9 b01001 6 -1$ b00000000000000000000000001000011 # +b01101 8 #675 0! -b11010 " #680 -b01101 " 1! -b00000000000000000000000001000100 # -1$ -b10000 6 -b01101 7 b10010 8 +b00000000000000000000000001000100 # +b10000 6 b01001 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b01101 " +b01101 7 #685 0! -b01101 " #690 -b10010 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10000 9 -b01001 8 b10010 7 +b10010 " +b10000 9 b01000 6 -1$ b00000000000000000000000001000101 # +b01001 8 #695 0! -b10010 " #700 -b01001 " 1! -b00000000000000000000000001000110 # -1$ -b00100 6 -b01001 7 b10000 8 +b00000000000000000000000001000110 # +b00100 6 b01000 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b01001 " +b01001 7 #705 0! -b01001 " #710 -b10000 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b00100 9 -b01000 8 b10000 7 +b10000 " +b00100 9 b00010 6 -1$ b00000000000000000000000001000111 # +b01000 8 #715 0! -b10000 " #720 -b01000 " 1! -b00000000000000000000000001001000 # -1$ -b00001 6 -b01000 7 b00100 8 +b00000000000000000000000001001000 # +b00001 6 b00010 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b01000 " +b01000 7 #725 0! -b01000 " #730 -b00100 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b00001 9 -b00010 8 b00100 7 +b00100 " +b00001 9 b10100 6 -1$ b00000000000000000000000001001001 # +b00010 8 #735 0! -b00100 " #740 -b00010 " 1! -b00000000000000000000000001001010 # -1$ -b01010 6 -b00010 7 b00001 8 +b00000000000000000000000001001010 # +b01010 6 b10100 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b00010 " +b00010 7 #745 0! -b00010 " #750 -b00001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01010 9 -b10100 8 b00001 7 +b00001 " +b01010 9 b00101 6 -1$ b00000000000000000000000001001011 # +b10100 8 #755 0! -b00001 " #760 -b10100 " 1! -b00000000000000000000000001001100 # -1$ -b10110 6 -b10100 7 b01010 8 +b00000000000000000000000001001100 # +b10110 6 b00101 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10100 " +b10100 7 #765 0! -b10100 " #770 -b01010 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10110 9 -b00101 8 b01010 7 +b01010 " +b10110 9 b01011 6 -1$ b00000000000000000000000001001101 # +b00101 8 #775 0! -b01010 " #780 -b00101 " 1! -b00000000000000000000000001001110 # -1$ -b10001 6 -b00101 7 b10110 8 +b00000000000000000000000001001110 # +b10001 6 b01011 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b00101 " +b00101 7 #785 0! -b00101 " #790 -b10110 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10001 9 -b01011 8 b10110 7 +b10110 " +b10001 9 b11100 6 -1$ b00000000000000000000000001001111 # +b01011 8 #795 0! -b10110 " #800 -b01011 " 1! -b00000000000000000000000001010000 # -1$ -b01110 6 -b01011 7 b10001 8 +b00000000000000000000000001010000 # +b01110 6 b11100 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b01011 " +b01011 7 #805 0! -b01011 " #810 -b10001 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01110 9 -b11100 8 b10001 7 +b10001 " +b01110 9 b00111 6 -1$ b00000000000000000000000001010001 # +b11100 8 #815 0! -b10001 " #820 -b11100 " 1! -b00000000000000000000000001010010 # -1$ -b10111 6 -b11100 7 b01110 8 +b00000000000000000000000001010010 # +b10111 6 b00111 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11100 " +b11100 7 #825 0! -b11100 " #830 -b01110 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10111 9 -b00111 8 b01110 7 +b01110 " +b10111 9 b11111 6 -1$ b00000000000000000000000001010011 # +b00111 8 #835 0! -b01110 " #840 -b00111 " 1! -b00000000000000000000000001010100 # -1$ -b11011 6 -b00111 7 b10111 8 +b00000000000000000000000001010100 # +b11011 6 b11111 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b00111 " +b00111 7 #845 0! -b00111 " #850 -b10111 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11011 9 -b11111 8 b10111 7 +b10111 " +b11011 9 b11001 6 -1$ b00000000000000000000000001010101 # +b11111 8 #855 0! -b10111 " #860 -b11111 " 1! -b00000000000000000000000001010110 # -1$ -b11000 6 -b11111 7 b11011 8 +b00000000000000000000000001010110 # +b11000 6 b11001 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11111 " +b11111 7 #865 0! -b11111 " #870 -b11011 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11000 9 -b11001 8 b11011 7 +b11011 " +b11000 9 b01100 6 -1$ b00000000000000000000000001010111 # +b11001 8 #875 0! -b11011 " #880 -b11001 " 1! -b00000000000000000000000001011000 # -1$ -b00110 6 -b11001 7 b11000 8 +b00000000000000000000000001011000 # +b00110 6 b01100 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11001 " +b11001 7 #885 0! -b11001 " #890 -b11000 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b00110 9 -b01100 8 b11000 7 +b11000 " +b00110 9 b00011 6 -1$ b00000000000000000000000001011001 # +b01100 8 #895 0! -b11000 " #900 -b01100 " 1! -b00000000000000000000000001011010 # -1$ -b10101 6 -b01100 7 b00110 8 +b00000000000000000000000001011010 # +b10101 6 b00011 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b01100 " +b01100 7 #905 0! -b01100 " #910 -b00110 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b10101 9 -b00011 8 b00110 7 +b00110 " +b10101 9 b11110 6 -1$ b00000000000000000000000001011011 # +b00011 8 #915 0! -b00110 " #920 -b00011 " 1! -b00000000000000000000000001011100 # -1$ -b01111 6 -b00011 7 b10101 8 +b00000000000000000000000001011100 # +b01111 6 b11110 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b00011 " +b00011 7 #925 0! -b00011 " #930 -b10101 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01111 9 -b11110 8 b10101 7 +b10101 " +b01111 9 b10011 6 -1$ b00000000000000000000000001011101 # +b11110 8 #935 0! -b10101 " #940 -b11110 " 1! -b00000000000000000000000001011110 # -1$ -b11101 6 -b11110 7 b01111 8 +b00000000000000000000000001011110 # +b11101 6 b10011 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11110 " +b11110 7 #945 0! -b11110 " #950 -b01111 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b11101 9 -b10011 8 b01111 7 +b01111 " +b11101 9 b11010 6 -1$ b00000000000000000000000001011111 # +b10011 8 #955 0! -b01111 " #960 -b10011 " 1! -b00000000000000000000000001100000 # -1$ -b01101 6 -b10011 7 b11101 8 +b00000000000000000000000001100000 # +b01101 6 b11010 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10011 " +b10011 7 #965 0! -b10011 " #970 -b11101 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01101 9 -b11010 8 b11101 7 +b11101 " +b01101 9 b10010 6 -1$ b00000000000000000000000001100001 # +b11010 8 #975 0! -b11101 " #980 -b11010 " 1! -b00000000000000000000000001100010 # -1$ -b01001 6 -b11010 7 b01101 8 +b00000000000000000000000001100010 # +b01001 6 b10010 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b11010 " +b11010 7 #985 0! -b11010 " #990 -b01101 " 1! -b00000000000000000000000000000011 ; -b00000000000000000000000000000010 : -b01001 9 -b10010 8 b01101 7 +b01101 " +b01001 9 b10000 6 -1$ b00000000000000000000000001100011 # +b10010 8 #995 0! -b01101 " #1000 -b10010 " 1! -b00000000000000000000000001100100 # -1$ -b01000 6 -b10010 7 b01001 8 +b00000000000000000000000001100100 # +b01000 6 b10000 9 -b00000000000000000000000000000010 : -b00000000000000000000000000000011 ; +b10010 " +b10010 7 diff --git a/test_regress/t/t_trace_packed_struct_fst.out b/test_regress/t/t_trace_packed_struct_fst.out index f976eb4d8..6335f7b24 100644 --- a/test_regress/t/t_trace_packed_struct_fst.out +++ b/test_regress/t/t_trace_packed_struct_fst.out @@ -1,5 +1,5 @@ $date - Sun Oct 21 21:56:54 2018 + Sun Apr 12 20:19:35 2020 $end $version @@ -42,4 +42,3 @@ b00000000000000000000000000000011 " 0! #40 1! -b00000000000000000000000000000011 "