diff --git a/Changes b/Changes index af7d0c7c1..254880bea 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Support string compare, icompare, ato* methods, bug1606. [Yutetsu TAKATSUKASA] +**** Update FST trace API for better performance. + * Verilator 4.024 2019-12-08 diff --git a/include/gtkwave/fstapi.c b/include/gtkwave/fstapi.c index aa9f3b975..3f52a7994 100644 --- a/include/gtkwave/fstapi.c +++ b/include/gtkwave/fstapi.c @@ -133,9 +133,9 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 #endif #ifdef __GNUC__ -// Boolean expression more often true than false +/* Boolean expression more often true than false */ #define FST_LIKELY(x) __builtin_expect(!!(x), 1) -// Boolean expression more often false than true +/* Boolean expression more often false than true */ #define FST_UNLIKELY(x) __builtin_expect(!!(x), 0) #else #define FST_LIKELY(x) (!!(x)) @@ -737,6 +737,9 @@ off_t hier_file_len; uint32_t *valpos_mem; unsigned char *curval_mem; +unsigned char *outval_mem; /* for two-state / Verilator-style value changes */ +uint32_t outval_alloc_siz; + char *filename; fstHandle maxhandle; @@ -1944,6 +1947,11 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) } } fstDestroyMmaps(xc, 1); + if(xc->outval_mem) + { + free(xc->outval_mem); xc->outval_mem = NULL; + xc->outval_alloc_siz = 0; + } /* write out geom section */ fflush(xc->geom_handle); @@ -2913,7 +2921,7 @@ if(FST_LIKELY((xc) && (handle <= xc->maxhandle))) { xc->vchg_alloc_siz += (xc->fst_break_add_size + len); /* +len added in the case of extremely long vectors and small break add sizes */ xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz); - if(VL_UNLIKELY(!xc->vchg_mem)) + if(FST_UNLIKELY(!xc->vchg_mem)) { fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitValueChange, exiting.\n"); exit(255); @@ -2998,6 +3006,131 @@ if(FST_LIKELY((xc) && (handle <= xc->maxhandle))) } } +void fstWriterEmitValueChange32(void *ctx, fstHandle handle, + uint32_t bits, uint32_t val) { + char buf[33]; + char *s = buf; + int i; + for (i = 0; i < bits; ++i) + { + *s++ = '0' + ((val >> (bits - i - 1)) & 1); + } + *s = '\0'; + fstWriterEmitValueChange(ctx, handle, buf); +} +void fstWriterEmitValueChange64(void *ctx, fstHandle handle, + uint32_t bits, uint64_t val) { + char buf[65]; + char *s = buf; + int i; + for (i = 0; i < bits; ++i) + { + *s++ = '0' + ((val >> (bits - i - 1)) & 1); + } + *s = '\0'; + fstWriterEmitValueChange(ctx, handle, buf); +} +void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, + uint32_t bits, const uint32_t *val) { + struct fstWriterContext *xc = (struct fstWriterContext *)ctx; + if (FST_UNLIKELY(bits <= 32)) + { + fstWriterEmitValueChange32(ctx, handle, bits, val[0]); + } + else if(FST_LIKELY(xc)) + { + int bq = bits / 32; + int br = bits & 31; + int i; + int w; + uint32_t v; + unsigned char* s; + if (FST_UNLIKELY(bits + 1 > xc->outval_alloc_siz)) + { + xc->outval_alloc_siz = bits*2 + 1; + xc->outval_mem = (unsigned char*)realloc(xc->outval_mem, xc->outval_alloc_siz); + if (FST_UNLIKELY(!xc->outval_mem)) + { + fprintf(stderr, + FST_APIMESS "Could not realloc() in fstWriterEmitValueChangeVec32, exiting.\n"); + exit(255); + } + } + s = xc->outval_mem; + { + w = bq; + v = val[w]; + for (i = 0; i < br; ++i) + { + *s++ = '0' + ((v >> (br - i - 1)) & 1); + } + } + for (w = bq - 1; w >= 0; --w) + { + v = val[w]; + for (i = (32 - 4); i >= 0; i -= 4) { + s[0] = '0' + ((v >> (i + 3)) & 1); + s[1] = '0' + ((v >> (i + 2)) & 1); + s[2] = '0' + ((v >> (i + 1)) & 1); + s[3] = '0' + ((v >> (i + 0)) & 1); + s += 4; + } + } + *s = '\0'; + fstWriterEmitValueChange(ctx, handle, xc->outval_mem); + } +} +void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, + uint32_t bits, const uint64_t *val) { + struct fstWriterContext *xc = (struct fstWriterContext *)ctx; + if (FST_UNLIKELY(bits <= 64)) + { + fstWriterEmitValueChange64(ctx, handle, bits, val[0]); + } + else if(FST_LIKELY(xc)) + { + int bq = bits / 64; + int br = bits & 63; + int i; + int w; + uint32_t v; + unsigned char* s; + if (FST_UNLIKELY(bits + 1 > xc->outval_alloc_siz)) + { + xc->outval_alloc_siz = bits*2 + 1; + xc->outval_mem = (unsigned char*)realloc(xc->outval_mem, xc->outval_alloc_siz); + if (FST_UNLIKELY(!xc->outval_mem)) + { + fprintf(stderr, + FST_APIMESS "Could not realloc() in fstWriterEmitValueChangeVec64, exiting.\n"); + exit(255); + } + } + s = xc->outval_mem; + { + w = bq; + v = val[w]; + for (i = 0; i < br; ++i) + { + *s++ = '0' + ((v >> (br - i - 1)) & 1); + } + } + for (w = bq - 1; w >= 0; --w) { + v = val[w]; + for (i = (64 - 4); i >= 0; i -= 4) + { + s[0] = '0' + ((v >> (i + 3)) & 1); + s[1] = '0' + ((v >> (i + 2)) & 1); + s[2] = '0' + ((v >> (i + 1)) & 1); + s[3] = '0' + ((v >> (i + 0)) & 1); + s += 4; + } + } + *s = '\0'; + fstWriterEmitValueChange(ctx, handle, xc->outval_mem); + } +} + void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len) { diff --git a/include/gtkwave/fstapi.h b/include/gtkwave/fstapi.h index aef6de23b..bbc82c278 100644 --- a/include/gtkwave/fstapi.h +++ b/include/gtkwave/fstapi.h @@ -355,6 +355,14 @@ fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDi void fstWriterEmitDumpActive(void *ctx, int enable); void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle); void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val); +void fstWriterEmitValueChange32(void *ctx, fstHandle handle, + uint32_t bits, uint32_t val); +void fstWriterEmitValueChange64(void *ctx, fstHandle handle, + uint32_t bits, uint64_t val); +void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, + uint32_t bits, const uint32_t *val); +void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, + uint32_t bits, const uint64_t *val); void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len); void fstWriterEmitTimeChange(void *ctx, uint64_t tim); void fstWriterFlushContext(void *ctx); diff --git a/include/verilated_fst_c.cpp b/include/verilated_fst_c.cpp index 56f56d8b6..2c94e53ef 100644 --- a/include/verilated_fst_c.cpp +++ b/include/verilated_fst_c.cpp @@ -205,52 +205,6 @@ void VerilatedFst::dump(vluint64_t timeui) { } } -//============================================================================= -// Helpers - -char* VerilatedFst::word2Str(vluint32_t newval, int bits) { - // Constructor makes sure m_valueStrBuffer.reserve() > 32+1 - char* s = m_valueStrBuffer.data(); - for (int i = 0; i < bits; ++i) { - *s++ = '0' + ((newval>>(bits-i-1))&1); - } - *s = '\0'; - return m_valueStrBuffer.data(); -} - -char* VerilatedFst::quad2Str(vluint64_t newval, int bits) { - // Constructor makes sure m_valueStrBuffer.reserve() > 64+1 - char* s = m_valueStrBuffer.data(); - for (int i = 0; i < bits; ++i) { - *s++ = '0' + ((newval>>(bits-i-1))&1); - } - *s = '\0'; - return m_valueStrBuffer.data(); -} - -char* VerilatedFst::array2Str(const vluint32_t* newval, int bits) { - int bq = bits / 32; - int br = bits & 31; - m_valueStrBuffer.reserve(bits+1); - char* s = m_valueStrBuffer.data(); - vluint32_t v = newval[bq]; - for (int i = 0; i < br; ++i) { - *s++ = '0' + ((v>>(br-i-1))&1); - } - for (int w = bq-1; w >= 0; --w) { - v = newval[w]; - for (int i = (32 - 4); i >= 0; i-=4) { - s[0] = '0' + ((v>>(i+3))&1); - s[1] = '0' + ((v>>(i+2))&1); - s[2] = '0' + ((v>>(i+1))&1); - s[3] = '0' + ((v>>(i+0))&1); - s+=4; - } - } - *s = '\0'; - return m_valueStrBuffer.data(); -} - //******************************************************************** // Local Variables: // End: diff --git a/include/verilated_fst_c.h b/include/verilated_fst_c.h index bda5a66be..786ed6f7b 100644 --- a/include/verilated_fst_c.h +++ b/include/verilated_fst_c.h @@ -63,9 +63,6 @@ private: int arraynum, vluint32_t len); // helpers std::vector m_valueStrBuffer; - char* word2Str(vluint32_t newval, int bits); - char* quad2Str(vluint64_t newval, int bits); - char* array2Str(const vluint32_t* newval, int bits); public: explicit VerilatedFst(void* fst=NULL); ~VerilatedFst() { if (m_fst == NULL) { fstWriterClose(m_fst); } } @@ -140,7 +137,7 @@ public: fstWriterEmitValueChange(m_fst, m_code2symbol[code], newval ? "1" : "0"); } void chgBus(vluint32_t code, const vluint32_t newval, int bits) { - fstWriterEmitValueChange(m_fst, m_code2symbol[code], word2Str(newval, bits)); + fstWriterEmitValueChange32(m_fst, m_code2symbol[code], bits, newval); } void chgDouble(vluint32_t code, const double newval) { double val = newval; @@ -151,10 +148,10 @@ public: fstWriterEmitValueChange(m_fst, m_code2symbol[code], &val); } void chgQuad(vluint32_t code, const vluint64_t newval, int bits) { - fstWriterEmitValueChange(m_fst, m_code2symbol[code], quad2Str(newval, bits)); + fstWriterEmitValueChange64(m_fst, m_code2symbol[code], bits, newval); } void chgArray(vluint32_t code, const vluint32_t* newval, int bits) { - fstWriterEmitValueChange(m_fst, m_code2symbol[code], array2Str(newval, bits)); + fstWriterEmitValueChangeVec32(m_fst, m_code2symbol[code], bits, newval); } void fullBit(vluint32_t code, const vluint32_t newval) {