Add GTKWave FST native tracing, bug1356.

Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
Sergi Granell 2018-10-02 18:42:53 -04:00 committed by Wilson Snyder
parent f8ae08c0c2
commit a5aa0e2b0a
35 changed files with 12674 additions and 22 deletions

View File

@ -2,8 +2,11 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.003 devel
** Add GTKWave FST native tracing, bug1356. [Sergi Granell]
*** Support $past. [Dan Gisselquist]
*** Support restrict, bug1350. [Clifford Wolf]

View File

@ -81,7 +81,7 @@ instead.)
To use Verilator you will need the C<perl>, C<make> (or C<gmake>), and
C<g++> (or C<clang>) packages.
To use Verilator LXT2 tracing you will need the C<gtkwave> and C<libgz> (on
To use Verilator LXT2 or FST tracing you will need the C<gtkwave> and C<libgz> (on
Ubuntu C<zlibc> C<zlib1g> C<zlib1g-dev>) packages installed.
To compile Verilator in addition to the above you need the C<flex>,

View File

@ -356,6 +356,7 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
--threads-max-mtasks <mtasks> Tune maximum mtask partitioning
--top-module <topname> Name of top level input module
--trace Enable waveform creation
--trace-fst Enable FST waveform creation
--trace-lxt2 Enable LXT2 waveform creation
--trace-depth <levels> Depth of tracing
--trace-max-array <depth> Maximum bit width for tracing
@ -1242,7 +1243,7 @@ designs with only one top.
=item --trace
Adds waveform tracing code to the model using VCD format. This overrides
C<--trace-lxt2>.
C<--trace-fst> and C<--trace-lxt2>.
Verilator will generate additional {prefix}__Trace*.cpp files that will
need to be compiled. In addition verilated_vcd_sc.cpp (for SystemC traces)
@ -1254,9 +1255,15 @@ need to add these to your Makefile manually.
Having tracing compiled in may result in some small performance losses,
even when waveforms are not turned on during model execution.
=item --trace-fst
Enable FST waveform tracing in the model. This overrides C<--trace> and C<--trace-lxt2>.
=item --trace-lxt2
Enable LXT2 waveform tracing in the model. This overrides C<--trace>.
Enable LXT2 waveform tracing in the model. This overrides C<--trace> and
C<--trace-fst>. This option is deprecated in favor of FST traces and may
be removed in the near future.
=item --trace-depth I<levels>
@ -4127,6 +4134,23 @@ trace file if you want all data to land in the same output file.
tfp->close();
}
=item How do I generate FST waveforms (traces) in C++?
FST a format by GTKWave.
This version provides a basic FST support.
To dump FST format, add the --trace switch to Verilator and change the include path in the testbench to:
#include "verilated_fst_c.h"
VerilatedFstC* tfp = new VerilatedFstC;
Note that currently supporting both FST and VCD in a single simulation is impossible,
but such requirement could be rare.
=item How do I generate FST waveforms (traces) in SystemC?
The FST library from GTKWave does not currently support SystemC; use VCD
format instead.
=item How do I generate LXT2 waveforms (traces) in C++?
LXT2 a format by GTKWave, which is usually 10x smaller than VCD format.
@ -4146,10 +4170,10 @@ format instead.
=item How do I view waveforms (traces)?
Verilator makes standard VCD (Value Change Dump) and LXT2 files. VCD files are viewable
Verilator makes standard VCD (Value Change Dump), LXT2 and FST files. VCD files are viewable
with the public domain GTKWave (recommended) or Dinotrace (legacy)
programs, or any of the many commercial offerings;
LXT2 is supported by GTKWave only.
LXT2 and FST are supported by GTKWave only.
=item How do I reduce the size of large waveform (trace) files?

547
include/gtkwave/fastlz.c Normal file
View File

@ -0,0 +1,547 @@
/*
FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "fastlz.h"
#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
/*
* Always check for bound when decompressing.
* Generally it is best to leave it defined.
*/
#define FASTLZ_SAFE
/*
* Give hints to the compiler for branch prediction optimization.
*/
#if defined(__GNUC__) && (__GNUC__ > 2)
#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
#else
#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
#endif
/*
* Use inlined functions for supported systems.
*/
#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
#define FASTLZ_INLINE inline
#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
#define FASTLZ_INLINE __inline
#else
#define FASTLZ_INLINE
#endif
/*
* Prevent accessing more than 8-bit at once, except on x86 architectures.
*/
#if !defined(FASTLZ_STRICT_ALIGN)
#define FASTLZ_STRICT_ALIGN
#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__amd64) /* GNU C */
#undef FASTLZ_STRICT_ALIGN
#elif defined(_M_IX86) /* Intel, MSVC */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__386)
#undef FASTLZ_STRICT_ALIGN
#elif defined(_X86_) /* MinGW */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__I86__) /* Digital Mars */
#undef FASTLZ_STRICT_ALIGN
#endif
#endif
/* prototypes */
int fastlz_compress(const void* input, int length, void* output);
int fastlz_compress_level(int level, const void* input, int length, void* output);
int fastlz_decompress(const void* input, int length, void* output, int maxout);
#define MAX_COPY 32
#define MAX_LEN 264 /* 256 + 8 */
#define MAX_DISTANCE 8192
#if !defined(FASTLZ_STRICT_ALIGN)
#define FASTLZ_READU16(p) *((const flzuint16*)(p))
#else
#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
#endif
#define HASH_LOG 13
#define HASH_SIZE (1<< HASH_LOG)
#define HASH_MASK (HASH_SIZE-1)
#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 1
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz1_compress
#define FASTLZ_DECOMPRESSOR fastlz1_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 2
#undef MAX_DISTANCE
#define MAX_DISTANCE 8191
#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz2_compress
#define FASTLZ_DECOMPRESSOR fastlz2_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
int fastlz_compress(const void* input, int length, void* output)
{
/* for short block, choose fastlz1 */
if(length < 65536)
return fastlz1_compress(input, length, output);
/* else... */
return fastlz2_compress(input, length, output);
}
int fastlz_decompress(const void* input, int length, void* output, int maxout)
{
/* magic identifier for compression level */
int level = ((*(const flzuint8*)input) >> 5) + 1;
if(level == 1)
return fastlz1_decompress(input, length, output, maxout);
if(level == 2)
return fastlz2_decompress(input, length, output, maxout);
/* unknown level, trigger error */
return 0;
}
int fastlz_compress_level(int level, const void* input, int length, void* output)
{
if(level == 1)
return fastlz1_compress(input, length, output);
if(level == 2)
return fastlz2_compress(input, length, output);
return 0;
}
#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
{
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_bound = ip + length - 2;
const flzuint8* ip_limit = ip + length - 12;
flzuint8* op = (flzuint8*) output;
const flzuint8* htab[HASH_SIZE];
const flzuint8** hslot;
flzuint32 hval;
flzuint32 copy;
/* sanity check */
if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
{
if(length)
{
/* create literal copy only */
*op++ = length-1;
ip_bound++;
while(ip <= ip_bound)
*op++ = *ip++;
return length+1;
}
else
return 0;
}
/* initializes hash table */
for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
*hslot = ip;
/* we start with literal copy */
copy = 2;
*op++ = MAX_COPY-1;
*op++ = *ip++;
*op++ = *ip++;
/* main loop */
while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
{
const flzuint8* ref;
flzuint32 distance;
/* minimum match length */
flzuint32 len = 3;
/* comparison starting-point */
const flzuint8* anchor = ip;
/* check for a run */
#if FASTLZ_LEVEL==2
if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
{
distance = 1;
/* ip += 3; */ /* scan-build, never used */
ref = anchor - 1 + 3;
goto match;
}
#endif
/* find potential match */
HASH_FUNCTION(hval,ip);
hslot = htab + hval;
ref = htab[hval];
/* calculate distance to the match */
distance = anchor - ref;
/* update hash table */
*hslot = anchor;
/* is this a match? check the first 3 bytes */
if(distance==0 ||
#if FASTLZ_LEVEL==1
(distance >= MAX_DISTANCE) ||
#else
(distance >= MAX_FARDISTANCE) ||
#endif
*ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
goto literal;
#if FASTLZ_LEVEL==2
/* far, needs at least 5-byte match */
if(distance >= MAX_DISTANCE)
{
if(*ip++ != *ref++ || *ip++!= *ref++)
goto literal;
len += 2;
}
match:
#endif
/* last matched byte */
ip = anchor + len;
/* distance is biased */
distance--;
if(!distance)
{
/* zero distance means a run */
flzuint8 x = ip[-1];
while(ip < ip_bound)
if(*ref++ != x) break; else ip++;
}
else
for(;;)
{
/* safe because the outer check against ip limit */
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
while(ip < ip_bound)
if(*ref++ != *ip++) break;
break;
}
/* if we have copied something, adjust the copy count */
if(copy)
/* copy is biased, '0' means 1 byte copy */
*(op-copy-1) = copy-1;
else
/* back, to overwrite the copy count */
op--;
/* reset literal counter */
copy = 0;
/* length is biased, '1' means a match of 3 bytes */
ip -= 3;
len = ip - anchor;
/* encode the match */
#if FASTLZ_LEVEL==2
if(distance < MAX_DISTANCE)
{
if(len < 7)
{
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
}
else
{
*op++ = (7 << 5) + (distance >> 8);
for(len-=7; len >= 255; len-= 255)
*op++ = 255;
*op++ = len;
*op++ = (distance & 255);
}
}
else
{
/* far away, but not yet in the another galaxy... */
if(len < 7)
{
distance -= MAX_DISTANCE;
*op++ = (len << 5) + 31;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
else
{
distance -= MAX_DISTANCE;
*op++ = (7 << 5) + 31;
for(len-=7; len >= 255; len-= 255)
*op++ = 255;
*op++ = len;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
}
#else
if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
while(len > MAX_LEN-2)
{
*op++ = (7 << 5) + (distance >> 8);
*op++ = MAX_LEN - 2 - 7 -2;
*op++ = (distance & 255);
len -= MAX_LEN-2;
}
if(len < 7)
{
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
}
else
{
*op++ = (7 << 5) + (distance >> 8);
*op++ = len - 7;
*op++ = (distance & 255);
}
#endif
/* update the hash at match boundary */
HASH_FUNCTION(hval,ip);
htab[hval] = ip++;
HASH_FUNCTION(hval,ip);
htab[hval] = ip++;
/* assuming literal copy */
*op++ = MAX_COPY-1;
continue;
literal:
*op++ = *anchor++;
ip = anchor;
copy++;
if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
{
copy = 0;
*op++ = MAX_COPY-1;
}
}
/* left-over as literal copy */
ip_bound++;
while(ip <= ip_bound)
{
*op++ = *ip++;
copy++;
if(copy == MAX_COPY)
{
copy = 0;
*op++ = MAX_COPY-1;
}
}
/* if we have copied something, adjust the copy length */
if(copy)
*(op-copy-1) = copy-1;
else
op--;
#if FASTLZ_LEVEL==2
/* marker for fastlz2 */
*(flzuint8*)output |= (1 << 5);
#endif
return op - (flzuint8*)output;
}
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
{
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_limit = ip + length;
flzuint8* op = (flzuint8*) output;
flzuint8* op_limit = op + maxout;
flzuint32 ctrl = (*ip++) & 31;
int loop = 1;
do
{
const flzuint8* ref = op;
flzuint32 len = ctrl >> 5;
flzuint32 ofs = (ctrl & 31) << 8;
if(ctrl >= 32)
{
#if FASTLZ_LEVEL==2
flzuint8 code;
#endif
len--;
ref -= ofs;
if (len == 7-1)
#if FASTLZ_LEVEL==1
len += *ip++;
ref -= *ip++;
#else
do
{
code = *ip++;
len += code;
} while (code==255);
code = *ip++;
ref -= code;
/* match from 16-bit distance */
if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
{
ofs = (*ip++) << 8;
ofs += *ip++;
ref = op - ofs - MAX_DISTANCE;
}
#endif
#ifdef FASTLZ_SAFE
if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
return 0;
if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
return 0;
#endif
if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
ctrl = *ip++;
else
loop = 0;
if(ref == op)
{
/* optimize copy for a run */
flzuint8 b = ref[-1];
*op++ = b;
*op++ = b;
*op++ = b;
for(; len; --len)
*op++ = b;
}
else
{
#if !defined(FASTLZ_STRICT_ALIGN)
const flzuint16* p;
flzuint16* q;
#endif
/* copy from reference */
ref--;
*op++ = *ref++;
*op++ = *ref++;
*op++ = *ref++;
#if !defined(FASTLZ_STRICT_ALIGN)
/* copy a byte, so that now it's word aligned */
if(len & 1)
{
*op++ = *ref++;
len--;
}
/* copy 16-bit at once */
q = (flzuint16*) op;
op += len;
p = (const flzuint16*) ref;
for(len>>=1; len > 4; len-=4)
{
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
}
for(; len; --len)
*q++ = *p++;
#else
for(; len; --len)
*op++ = *ref++;
#endif
}
}
else
{
ctrl++;
#ifdef FASTLZ_SAFE
if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
return 0;
if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
return 0;
#endif
*op++ = *ip++;
for(--ctrl; ctrl; ctrl--)
*op++ = *ip++;
loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
if(loop)
ctrl = *ip++;
}
}
while(FASTLZ_EXPECT_CONDITIONAL(loop));
return op - (flzuint8*)output;
}
#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */

107
include/gtkwave/fastlz.h Normal file
View File

@ -0,0 +1,107 @@
/*
FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef FASTLZ_H
#define FASTLZ_H
#include <inttypes.h>
#define flzuint8 uint8_t
#define flzuint16 uint16_t
#define flzuint32 uint32_t
#define FASTLZ_VERSION 0x000100
#define FASTLZ_VERSION_MAJOR 0
#define FASTLZ_VERSION_MINOR 0
#define FASTLZ_VERSION_REVISION 0
#define FASTLZ_VERSION_STRING "0.1.0"
#if defined (__cplusplus)
extern "C" {
#endif
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
*/
int fastlz_compress(const void* input, int length, void* output);
/**
Decompress a block of compressed data and returns the size of the
decompressed block. If error occurs, e.g. the compressed data is
corrupted or the output buffer is not large enough, then 0 (zero)
will be returned instead.
The input buffer and the output buffer can not overlap.
Decompression is memory safe and guaranteed not to write the output buffer
more than what is specified in maxout.
*/
int fastlz_decompress(const void* input, int length, void* output, int maxout);
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
Compression level can be specified in parameter level. At the moment,
only level 1 and level 2 are supported.
Level 1 is the fastest compression and generally useful for short data.
Level 2 is slightly slower but it gives better compression ratio.
Note that the compressed data, regardless of the level, can always be
decompressed using the function fastlz_decompress above.
*/
int fastlz_compress_level(int level, const void* input, int length, void* output);
#if defined (__cplusplus)
}
#endif
#endif /* FASTLZ_H */

View File

@ -0,0 +1,12 @@
/* This file specifically for FST usage */
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). */
#define HAVE_ALLOCA_H 1
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#define HAVE_FSEEKO 1

6606
include/gtkwave/fstapi.c Normal file

File diff suppressed because it is too large Load Diff

432
include/gtkwave/fstapi.h Normal file
View File

@ -0,0 +1,432 @@
/*
* Copyright (c) 2009-2017 Tony Bybell.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef FST_API_H
#define FST_API_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <zlib.h>
#include <inttypes.h>
#include <unistd.h>
#include <time.h>
#define FST_RDLOAD "FSTLOAD | "
typedef uint32_t fstHandle;
enum fstWriterPackType {
FST_WR_PT_ZLIB = 0,
FST_WR_PT_FASTLZ = 1,
FST_WR_PT_LZ4 = 2
};
enum fstFileType {
FST_FT_MIN = 0,
FST_FT_VERILOG = 0,
FST_FT_VHDL = 1,
FST_FT_VERILOG_VHDL = 2,
FST_FT_MAX = 2
};
enum fstBlockType {
FST_BL_HDR = 0,
FST_BL_VCDATA = 1,
FST_BL_BLACKOUT = 2,
FST_BL_GEOM = 3,
FST_BL_HIER = 4,
FST_BL_VCDATA_DYN_ALIAS = 5,
FST_BL_HIER_LZ4 = 6,
FST_BL_HIER_LZ4DUO = 7,
FST_BL_VCDATA_DYN_ALIAS2 = 8,
FST_BL_ZWRAPPER = 254, /* indicates that whole trace is gz wrapped */
FST_BL_SKIP = 255 /* used while block is being written */
};
enum fstScopeType {
FST_ST_MIN = 0,
FST_ST_VCD_MODULE = 0,
FST_ST_VCD_TASK = 1,
FST_ST_VCD_FUNCTION = 2,
FST_ST_VCD_BEGIN = 3,
FST_ST_VCD_FORK = 4,
FST_ST_VCD_GENERATE = 5,
FST_ST_VCD_STRUCT = 6,
FST_ST_VCD_UNION = 7,
FST_ST_VCD_CLASS = 8,
FST_ST_VCD_INTERFACE = 9,
FST_ST_VCD_PACKAGE = 10,
FST_ST_VCD_PROGRAM = 11,
FST_ST_VHDL_ARCHITECTURE = 12,
FST_ST_VHDL_PROCEDURE = 13,
FST_ST_VHDL_FUNCTION = 14,
FST_ST_VHDL_RECORD = 15,
FST_ST_VHDL_PROCESS = 16,
FST_ST_VHDL_BLOCK = 17,
FST_ST_VHDL_FOR_GENERATE = 18,
FST_ST_VHDL_IF_GENERATE = 19,
FST_ST_VHDL_GENERATE = 20,
FST_ST_VHDL_PACKAGE = 21,
FST_ST_MAX = 21,
FST_ST_GEN_ATTRBEGIN = 252,
FST_ST_GEN_ATTREND = 253,
FST_ST_VCD_SCOPE = 254,
FST_ST_VCD_UPSCOPE = 255
};
enum fstVarType {
FST_VT_MIN = 0, /* start of vartypes */
FST_VT_VCD_EVENT = 0,
FST_VT_VCD_INTEGER = 1,
FST_VT_VCD_PARAMETER = 2,
FST_VT_VCD_REAL = 3,
FST_VT_VCD_REAL_PARAMETER = 4,
FST_VT_VCD_REG = 5,
FST_VT_VCD_SUPPLY0 = 6,
FST_VT_VCD_SUPPLY1 = 7,
FST_VT_VCD_TIME = 8,
FST_VT_VCD_TRI = 9,
FST_VT_VCD_TRIAND = 10,
FST_VT_VCD_TRIOR = 11,
FST_VT_VCD_TRIREG = 12,
FST_VT_VCD_TRI0 = 13,
FST_VT_VCD_TRI1 = 14,
FST_VT_VCD_WAND = 15,
FST_VT_VCD_WIRE = 16,
FST_VT_VCD_WOR = 17,
FST_VT_VCD_PORT = 18,
FST_VT_VCD_SPARRAY = 19, /* used to define the rownum (index) port for a sparse array */
FST_VT_VCD_REALTIME = 20,
FST_VT_GEN_STRING = 21, /* generic string type (max len is defined dynamically via fstWriterEmitVariableLengthValueChange) */
FST_VT_SV_BIT = 22,
FST_VT_SV_LOGIC = 23,
FST_VT_SV_INT = 24, /* declare as size = 32 */
FST_VT_SV_SHORTINT = 25, /* declare as size = 16 */
FST_VT_SV_LONGINT = 26, /* declare as size = 64 */
FST_VT_SV_BYTE = 27, /* declare as size = 8 */
FST_VT_SV_ENUM = 28, /* declare as appropriate type range */
FST_VT_SV_SHORTREAL = 29, /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted as double, not a float) */
FST_VT_MAX = 29 /* end of vartypes */
};
enum fstVarDir {
FST_VD_MIN = 0,
FST_VD_IMPLICIT = 0,
FST_VD_INPUT = 1,
FST_VD_OUTPUT = 2,
FST_VD_INOUT = 3,
FST_VD_BUFFER = 4,
FST_VD_LINKAGE = 5,
FST_VD_MAX = 5
};
enum fstHierType {
FST_HT_MIN = 0,
FST_HT_SCOPE = 0,
FST_HT_UPSCOPE = 1,
FST_HT_VAR = 2,
FST_HT_ATTRBEGIN = 3,
FST_HT_ATTREND = 4,
/* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other formats */
FST_HT_TREEBEGIN = 5,
FST_HT_TREEEND = 6,
FST_HT_MAX = 6
};
enum fstAttrType {
FST_AT_MIN = 0,
FST_AT_MISC = 0, /* self-contained: does not need matching FST_HT_ATTREND */
FST_AT_ARRAY = 1,
FST_AT_ENUM = 2,
FST_AT_PACK = 3,
FST_AT_MAX = 3
};
enum fstMiscType {
FST_MT_MIN = 0,
FST_MT_COMMENT = 0, /* use fstWriterSetComment() to emit */
FST_MT_ENVVAR = 1, /* use fstWriterSetEnvVar() to emit */
FST_MT_SUPVAR = 2, /* use fstWriterCreateVar2() to emit */
FST_MT_PATHNAME = 3, /* reserved for fstWriterSetSourceStem() string -> number management */
FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */
FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
FST_MT_VALUELIST = 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
FST_MT_UNKNOWN = 7,
FST_MT_MAX = 7
};
enum fstArrayType {
FST_AR_MIN = 0,
FST_AR_NONE = 0,
FST_AR_UNPACKED = 1,
FST_AR_PACKED = 2,
FST_AR_SPARSE = 3,
FST_AR_MAX = 3
};
enum fstEnumValueType {
FST_EV_SV_INTEGER = 0,
FST_EV_SV_BIT = 1,
FST_EV_SV_LOGIC = 2,
FST_EV_SV_INT = 3,
FST_EV_SV_SHORTINT = 4,
FST_EV_SV_LONGINT = 5,
FST_EV_SV_BYTE = 6,
FST_EV_SV_UNSIGNED_INTEGER = 7,
FST_EV_SV_UNSIGNED_BIT = 8,
FST_EV_SV_UNSIGNED_LOGIC = 9,
FST_EV_SV_UNSIGNED_INT = 10,
FST_EV_SV_UNSIGNED_SHORTINT = 11,
FST_EV_SV_UNSIGNED_LONGINT = 12,
FST_EV_SV_UNSIGNED_BYTE = 13,
FST_EV_MAX = 13
};
enum fstPackType {
FST_PT_NONE = 0,
FST_PT_UNPACKED = 1,
FST_PT_PACKED = 2,
FST_PT_TAGGED_PACKED = 3,
FST_PT_MAX = 3
};
enum fstSupplementalVarType {
FST_SVT_MIN = 0,
FST_SVT_NONE = 0,
FST_SVT_VHDL_SIGNAL = 1,
FST_SVT_VHDL_VARIABLE = 2,
FST_SVT_VHDL_CONSTANT = 3,
FST_SVT_VHDL_FILE = 4,
FST_SVT_VHDL_MEMORY = 5,
FST_SVT_MAX = 5
};
enum fstSupplementalDataType {
FST_SDT_MIN = 0,
FST_SDT_NONE = 0,
FST_SDT_VHDL_BOOLEAN = 1,
FST_SDT_VHDL_BIT = 2,
FST_SDT_VHDL_BIT_VECTOR = 3,
FST_SDT_VHDL_STD_ULOGIC = 4,
FST_SDT_VHDL_STD_ULOGIC_VECTOR = 5,
FST_SDT_VHDL_STD_LOGIC = 6,
FST_SDT_VHDL_STD_LOGIC_VECTOR = 7,
FST_SDT_VHDL_UNSIGNED = 8,
FST_SDT_VHDL_SIGNED = 9,
FST_SDT_VHDL_INTEGER = 10,
FST_SDT_VHDL_REAL = 11,
FST_SDT_VHDL_NATURAL = 12,
FST_SDT_VHDL_POSITIVE = 13,
FST_SDT_VHDL_TIME = 14,
FST_SDT_VHDL_CHARACTER = 15,
FST_SDT_VHDL_STRING = 16,
FST_SDT_MAX = 16,
FST_SDT_SVT_SHIFT_COUNT = 10, /* FST_SVT_* is ORed in by fstWriterCreateVar2() to the left after shifting FST_SDT_SVT_SHIFT_COUNT */
FST_SDT_ABS_MAX = ((1<<(FST_SDT_SVT_SHIFT_COUNT))-1)
};
struct fstHier
{
unsigned char htyp;
union {
/* if htyp == FST_HT_SCOPE */
struct fstHierScope {
unsigned char typ; /* FST_ST_MIN ... FST_ST_MAX */
const char *name;
const char *component;
uint32_t name_length; /* strlen(u.scope.name) */
uint32_t component_length; /* strlen(u.scope.component) */
} scope;
/* if htyp == FST_HT_VAR */
struct fstHierVar {
unsigned char typ; /* FST_VT_MIN ... FST_VT_MAX */
unsigned char direction; /* FST_VD_MIN ... FST_VD_MAX */
unsigned char svt_workspace; /* zeroed out by FST reader, for client code use */
unsigned char sdt_workspace; /* zeroed out by FST reader, for client code use */
unsigned int sxt_workspace; /* zeroed out by FST reader, for client code use */
const char *name;
uint32_t length;
fstHandle handle;
uint32_t name_length; /* strlen(u.var.name) */
unsigned is_alias : 1;
} var;
/* if htyp == FST_HT_ATTRBEGIN */
struct fstHierAttr {
unsigned char typ; /* FST_AT_MIN ... FST_AT_MAX */
unsigned char subtype; /* from fstMiscType, fstArrayType, fstEnumValueType, fstPackType */
const char *name;
uint64_t arg; /* number of array elements, struct members, or some other payload (possibly ignored) */
uint64_t arg_from_name; /* for when name is overloaded as a variable-length integer (FST_AT_MISC + FST_MT_SOURCESTEM) */
uint32_t name_length; /* strlen(u.attr.name) */
} attr;
} u;
};
/*
* writer functions
*/
void fstWriterClose(void *ctx);
void * fstWriterCreate(const char *nam, int use_compressed_hier);
/* used for Verilog/SV */
fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd,
uint32_t len, const char *nam, fstHandle aliasHandle);
/* future expansion for VHDL and other languages. The variable type, data type, etc map onto
the current Verilog/SV one. The "type" string is optional for a more verbose or custom description */
fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd,
uint32_t len, const char *nam, fstHandle aliasHandle,
const char *type, enum fstSupplementalVarType svt, enum fstSupplementalDataType sdt);
void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val);
void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len);
void fstWriterEmitDumpActive(void *ctx, int enable);
void fstWriterEmitTimeChange(void *ctx, uint64_t tim);
void fstWriterFlushContext(void *ctx);
int fstWriterGetDumpSizeLimitReached(void *ctx);
int fstWriterGetFseekFailed(void *ctx);
void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype,
const char *attrname, uint64_t arg);
void fstWriterSetAttrEnd(void *ctx);
void fstWriterSetComment(void *ctx, const char *comm);
void fstWriterSetDate(void *ctx, const char *dat);
void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes);
void fstWriterSetEnvVar(void *ctx, const char *envvar);
void fstWriterSetFileType(void *ctx, enum fstFileType filetype);
void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ);
void fstWriterSetParallelMode(void *ctx, int enable);
void fstWriterSetRepackOnClose(void *ctx, int enable); /* type = 0 (none), 1 (libz) */
void fstWriterSetScope(void *ctx, enum fstScopeType scopetype,
const char *scopename, const char *scopecomp);
void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
void fstWriterSetSourceStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
void fstWriterSetTimescale(void *ctx, int ts);
void fstWriterSetTimescaleFromString(void *ctx, const char *s);
void fstWriterSetTimezero(void *ctx, int64_t tim);
void fstWriterSetUpscope(void *ctx);
void fstWriterSetValueList(void *ctx, const char *vl);
void fstWriterSetVersion(void *ctx, const char *vers);
/*
* reader functions
*/
void fstReaderClose(void *ctx);
void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx);
void fstReaderClrFacProcessMaskAll(void *ctx);
uint64_t fstReaderGetAliasCount(void *ctx);
const char * fstReaderGetCurrentFlatScope(void *ctx);
void * fstReaderGetCurrentScopeUserInfo(void *ctx);
int fstReaderGetCurrentScopeLen(void *ctx);
const char * fstReaderGetDateString(void *ctx);
int fstReaderGetDoubleEndianMatchState(void *ctx);
uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx);
unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx);
uint64_t fstReaderGetEndTime(void *ctx);
int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx);
int fstReaderGetFileType(void *ctx);
int fstReaderGetFseekFailed(void *ctx);
fstHandle fstReaderGetMaxHandle(void *ctx);
uint64_t fstReaderGetMemoryUsedByWriter(void *ctx);
uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx);
uint64_t fstReaderGetScopeCount(void *ctx);
uint64_t fstReaderGetStartTime(void *ctx);
signed char fstReaderGetTimescale(void *ctx);
int64_t fstReaderGetTimezero(void *ctx);
uint64_t fstReaderGetValueChangeSectionCount(void *ctx);
char * fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf);
uint64_t fstReaderGetVarCount(void *ctx);
const char * fstReaderGetVersionString(void *ctx);
struct fstHier *fstReaderIterateHier(void *ctx);
int fstReaderIterateHierRewind(void *ctx);
int fstReaderIterBlocks(void *ctx,
void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value),
void *user_callback_data_pointer, FILE *vcdhandle);
int fstReaderIterBlocks2(void *ctx,
void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value),
void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value, uint32_t len),
void *user_callback_data_pointer, FILE *vcdhandle);
void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable);
void * fstReaderOpen(const char *nam);
void * fstReaderOpenForUtilitiesOnly(void);
const char * fstReaderPopScope(void *ctx);
int fstReaderProcessHier(void *ctx, FILE *vcdhandle);
const char * fstReaderPushScope(void *ctx, const char *nam, void *user_info);
void fstReaderResetScope(void *ctx);
void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx);
void fstReaderSetFacProcessMaskAll(void *ctx);
void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time);
void fstReaderSetUnlimitedTimeRange(void *ctx);
void fstReaderSetVcdExtensions(void *ctx, int enable);
/*
* utility functions
*/
int fstUtilityBinToEsc(unsigned char *d, unsigned char *s, int len);
int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -27,6 +27,7 @@
#include "lxt2_config.h"
#include "lxt2_write.h"
static char *lxt2_wr_vcd_truncate_bitvec(char *s)
{
char l, r;
@ -96,7 +97,7 @@ if (lo<hi)
static void wave_msort(struct lxt2_wr_symbol **a, int num)
{
struct lxt2_wr_symbol **b = (lxt2_wr_symbol**)malloc(((num/2)+1) * sizeof(struct lxt2_wr_symbol *));
struct lxt2_wr_symbol **b = (struct lxt2_wr_symbol**)malloc(((num/2)+1) * sizeof(struct lxt2_wr_symbol *));
wave_mergesort(a, b, 0, num-1);
@ -582,7 +583,7 @@ unsigned int i;
if((lt)&&(lt->numfacs))
{
struct lxt2_wr_symbol *s = lt->symchain;
struct lxt2_wr_symbol **aliascache = (lxt2_wr_symbol**)calloc(lt->numalias ? lt->numalias : 1, sizeof(struct lxt2_wr_symbol *));
struct lxt2_wr_symbol **aliascache = (struct lxt2_wr_symbol**)calloc(lt->numalias ? lt->numalias : 1, sizeof(struct lxt2_wr_symbol *));
unsigned int aliases_encountered, facs_encountered;
lt->sorted_facs = (struct lxt2_wr_symbol **)calloc(lt->numfacs, sizeof(struct lxt2_wr_symbol *));
@ -2100,7 +2101,7 @@ if((lt)&&(lt->blackout))
{
if((!(s->flags&LXT2_WR_SYM_F_ALIAS))&&(s->rows<2))
{
char tmp[16]; // To get rid of the warning
char tmp[16]; /* To get rid of the warning */
if(!(s->flags&(LXT2_WR_SYM_F_DOUBLE|LXT2_WR_SYM_F_STRING)))
{
strcpy(tmp, "x");

1519
include/gtkwave/lz4.c Normal file

File diff suppressed because it is too large Load Diff

360
include/gtkwave/lz4.h Normal file
View File

@ -0,0 +1,360 @@
/*
LZ4 - Fast LZ compression algorithm
Header File
Copyright (C) 2011-2015, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 source repository : https://github.com/Cyan4973/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#pragma once
#if defined (__cplusplus)
extern "C" {
#endif
/*
* lz4.h provides block compression functions, and gives full buffer control to programmer.
* If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
* and can let the library handle its own memory, please use lz4frame.h instead.
*/
/**************************************
* Version
**************************************/
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */
#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
int LZ4_versionNumber (void);
/**************************************
* Tuning parameter
**************************************/
/*
* LZ4_MEMORY_USAGE :
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
* Increasing memory usage improves compression ratio
* Reduced memory usage can improve speed, due to cache effect
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
*/
#define LZ4_MEMORY_USAGE 14
/**************************************
* Simple Functions
**************************************/
int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
/*
LZ4_compress_default() :
Compresses 'sourceSize' bytes from buffer 'source'
into already allocated 'dest' buffer of size 'maxDestSize'.
Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
It also runs faster, so it's a recommended setting.
If the function cannot compress 'source' into a more limited 'dest' budget,
compression stops *immediately*, and the function result is zero.
As a consequence, 'dest' content is not valid.
This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
or 0 if compression fails
LZ4_decompress_safe() :
compressedSize : is the precise full size of the compressed block.
maxDecompressedSize : is the size of destination buffer, which must be already allocated.
return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
If destination buffer is not large enough, decoding will stop and output an error code (<0).
If the source stream is detected malformed, the function will stop decoding and return a negative result.
This function is protected against buffer overflow exploits, including malicious data packets.
It never writes outside output buffer, nor reads outside input buffer.
*/
/**************************************
* Advanced Functions
**************************************/
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
/*
LZ4_compressBound() :
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
This function is primarily useful for memory allocation purposes (destination buffer size).
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
return : maximum output size in a "worst case" scenario
or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
*/
int LZ4_compressBound(int inputSize);
/*
LZ4_compress_fast() :
Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
An acceleration value of "1" is the same as regular LZ4_compress_default()
Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
*/
int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
/*
LZ4_compress_fast_extState() :
Same compression function, just using an externally allocated memory space to store compression state.
Use LZ4_sizeofState() to know how much memory must be allocated,
and allocate it on 8-bytes boundaries (using malloc() typically).
Then, provide it as 'void* state' to compression function.
*/
int LZ4_sizeofState(void);
int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
/*
LZ4_compress_destSize() :
Reverse the logic, by compressing as much data as possible from 'source' buffer
into already allocated buffer 'dest' of size 'targetDestSize'.
This function either compresses the entire 'source' content into 'dest' if it's large enough,
or fill 'dest' buffer completely with as much data as possible from 'source'.
*sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
New value is necessarily <= old value.
return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
or 0 if compression fails
*/
int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
/*
LZ4_decompress_fast() :
originalSize : is the original and therefore uncompressed size
return : the number of bytes read from the source buffer (in other words, the compressed size)
If the source stream is detected malformed, the function will stop decoding and return a negative result.
Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
note : This function fully respect memory boundaries for properly formed compressed data.
It is a bit faster than LZ4_decompress_safe().
However, it does not provide any protection against intentionally modified data stream (malicious input).
Use this function in trusted environment only (data to decode comes from a trusted source).
*/
int LZ4_decompress_fast (const char* source, char* dest, int originalSize);
/*
LZ4_decompress_safe_partial() :
This function decompress a compressed block of size 'compressedSize' at position 'source'
into destination buffer 'dest' of size 'maxDecompressedSize'.
The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
reducing decompression time.
return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
Always control how many bytes were decoded.
If the source stream is detected malformed, the function will stop decoding and return a negative result.
This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
*/
int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
/***********************************************
* Streaming Compression Functions
***********************************************/
#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4)
#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long))
/*
* LZ4_stream_t
* information structure to track an LZ4 stream.
* important : init this structure content before first use !
* note : only allocated directly the structure if you are statically linking LZ4
* If you are using liblz4 as a DLL, please use below construction methods instead.
*/
typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t;
/*
* LZ4_resetStream
* Use this function to init an allocated LZ4_stream_t structure
*/
void LZ4_resetStream (LZ4_stream_t* streamPtr);
/*
* LZ4_createStream will allocate and initialize an LZ4_stream_t structure
* LZ4_freeStream releases its memory.
* In the context of a DLL (liblz4), please use these methods rather than the static struct.
* They are more future proof, in case of a change of LZ4_stream_t size.
*/
LZ4_stream_t* LZ4_createStream(void);
int LZ4_freeStream (LZ4_stream_t* streamPtr);
/*
* LZ4_loadDict
* Use this function to load a static dictionary into LZ4_stream.
* Any previous data will be forgotten, only 'dictionary' will remain in memory.
* Loading a size of 0 is allowed.
* Return : dictionary size, in bytes (necessarily <= 64 KB)
*/
int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
/*
* LZ4_compress_fast_continue
* Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
* Important : Previous data blocks are assumed to still be present and unmodified !
* 'dst' buffer must be already allocated.
* If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
* If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
*/
int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);
/*
* LZ4_saveDict
* If previously compressed data block is not guaranteed to remain available at its memory location
* save it into a safer place (char* safeBuffer)
* Note : you don't need to call LZ4_loadDict() afterwards,
* dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue()
* Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
*/
int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize);
/************************************************
* Streaming Decompression Functions
************************************************/
#define LZ4_STREAMDECODESIZE_U64 4
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
typedef struct { unsigned long long table[LZ4_STREAMDECODESIZE_U64]; } LZ4_streamDecode_t;
/*
* LZ4_streamDecode_t
* information structure to track an LZ4 stream.
* init this structure content using LZ4_setStreamDecode or memset() before first use !
*
* In the context of a DLL (liblz4) please prefer usage of construction methods below.
* They are more future proof, in case of a change of LZ4_streamDecode_t size in the future.
* LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure
* LZ4_freeStreamDecode releases its memory.
*/
LZ4_streamDecode_t* LZ4_createStreamDecode(void);
int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
/*
* LZ4_setStreamDecode
* Use this function to instruct where to find the dictionary.
* Setting a size of 0 is allowed (same effect as reset).
* Return : 1 if OK, 0 if error
*/
int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
/*
*_continue() :
These decoding functions allow decompression of multiple blocks in "streaming" mode.
Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
In the case of a ring buffers, decoding buffer must be either :
- Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
- Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
In which case, encoding and decoding buffers do not need to be synchronized,
and encoding ring buffer can have any size, including small ones ( < 64 KB).
- _At least_ 64 KB + 8 bytes + maxBlockSize.
In which case, encoding and decoding buffers do not need to be synchronized,
and encoding ring buffer can have any size, including larger than decoding buffer.
Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
and indicate where it is saved using LZ4_setStreamDecode()
*/
int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
/*
Advanced decoding functions :
*_usingDict() :
These decoding functions work the same as
a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue()
They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure.
*/
int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
/**************************************
* Obsolete Functions
**************************************/
/* Deprecate Warnings */
/* Should these warnings messages be a problem,
it is generally possible to disable them,
with -Wno-deprecated-declarations for gcc
or _CRT_SECURE_NO_WARNINGS in Visual for example.
You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */
#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK
# define LZ4_DEPRECATE_WARNING_DEFBLOCK
# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
# if (LZ4_GCC_VERSION >= 405) || defined(__clang__)
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
# elif (LZ4_GCC_VERSION >= 301)
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
# elif defined(_MSC_VER)
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
# else
# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
# define LZ4_DEPRECATED(message)
# endif
#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */
/* Obsolete compression functions */
/* These functions are planned to start generate warnings by r131 approximately */
int LZ4_compress (const char* source, char* dest, int sourceSize);
int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
/* Obsolete decompression functions */
/* These function names are completely deprecated and must no longer be used.
They are only provided here for compatibility with older programs.
- LZ4_uncompress is the same as LZ4_decompress_fast
- LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
These function prototypes are now disabled; uncomment them only if you really need them.
It is highly recommended to stop using these prototypes and migrate to maintained ones */
/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */
/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
/* Obsolete streaming functions; use new streaming interface whenever possible */
LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer);
LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void);
LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer);
LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state);
/* Obsolete streaming decoding functions */
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
#if defined (__cplusplus)
}
#endif

View File

@ -81,6 +81,8 @@ class VerilatedVcd;
class VerilatedVcdC;
class VerilatedLxt2;
class VerilatedLxt2C;
class VerilatedFst;
class VerilatedFstC;
enum VerilatedVarType {
VLVT_UNKNOWN=0,

224
include/verilated_fst_c.cpp Normal file
View File

@ -0,0 +1,224 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2018 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.
//
// This is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
//=============================================================================
///
/// \file
/// \brief C++ Tracing in FST Format
///
//=============================================================================
// SPDIFF_OFF
#include "verilatedos.h"
#include "verilated.h"
#include "verilated_fst_c.h"
// Include the GTKWave implementation directly
#include "gtkwave/fstapi.c"
#include "gtkwave/fastlz.c"
#include "gtkwave/lz4.c"
#include <sys/stat.h>
#include <fcntl.h>
#include <cerrno>
#include <ctime>
#include <algorithm>
#include <sstream>
#include <iterator>
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
# include <io.h>
#else
# include <unistd.h>
#endif
//=============================================================================
class VerilatedFstCallInfo {
protected:
friend class VerilatedFst;
VerilatedFstCallback_t m_initcb; ///< Initialization Callback function
VerilatedFstCallback_t m_fullcb; ///< Full Dumping Callback function
VerilatedFstCallback_t m_changecb; ///< Incremental Dumping Callback function
void* m_userthis; ///< Fake "this" for caller
vluint32_t m_code; ///< Starting code number
// CONSTRUCTORS
VerilatedFstCallInfo(VerilatedFstCallback_t icb, VerilatedFstCallback_t fcb,
VerilatedFstCallback_t changecb,
void* ut, vluint32_t code)
: m_initcb(icb), m_fullcb(fcb), m_changecb(changecb), m_userthis(ut), m_code(code) {};
~VerilatedFstCallInfo() {}
};
//=============================================================================
// VerilatedFst
VerilatedFst::VerilatedFst(void* fst)
: m_fst(fst),
m_fullDump(true),
m_scopeEscape('.') {}
void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
m_assertOne.check();
m_fst = fstWriterCreate(filename, 0);
m_curScope.clear();
for (vluint32_t ent = 0; ent< m_callbacks.size(); ++ent) {
VerilatedFstCallInfo* cip = m_callbacks[ent];
cip->m_code = 1;
(cip->m_initcb)(this, cip->m_userthis, cip->m_code);
}
// Clear the scope stack
std::list<std::string>::iterator it = m_curScope.begin();
while (it != m_curScope.end()) {
fstWriterSetUpscope(m_fst);
it = m_curScope.erase(it);
}
}
void VerilatedFst::module(const std::string& name) {
m_module = name;
}
//=============================================================================
// Decl
void VerilatedFst::declSymbol(vluint32_t code, const char* name, int arraynum, uint32_t len, enum fstVarType vartype) {
std::pair<Code2SymbolType::iterator, bool> p
= m_code2symbol.insert(std::make_pair(code, (fstHandle)(0)));
std::istringstream nameiss(name);
std::istream_iterator<std::string> beg(nameiss), end;
std::list<std::string> tokens(beg, end); // Split name
std::string symbol_name(tokens.back());
tokens.pop_back(); // Remove symbol name from hierarchy
tokens.insert(tokens.begin(), m_module); // Add current module to the hierarchy
// Find point where current and new scope diverge
std::list<std::string>::iterator cur_it = m_curScope.begin();
std::list<std::string>::iterator new_it = tokens.begin();
while (cur_it != m_curScope.end() && new_it != tokens.end()) {
if (*cur_it != *new_it)
break;
++cur_it;
++new_it;
}
// Go back to the common point
while (cur_it != m_curScope.end()) {
fstWriterSetUpscope(m_fst);
cur_it = m_curScope.erase(cur_it);
}
// Follow the hierarchy of the new variable from the common scope point
while (new_it != tokens.end()) {
fstWriterSetScope(m_fst, FST_ST_VCD_SCOPE, new_it->c_str(), NULL);
m_curScope.push_back(*new_it);
new_it = tokens.erase(new_it);
}
std::stringstream name_ss;
name_ss << symbol_name;
if (arraynum >= 0)
name_ss << "(" << arraynum << ")";
std::string name_str = name_ss.str();
if (p.second) { // New
p.first->second = fstWriterCreateVar(m_fst, vartype, FST_VD_IMPLICIT, len, name_str.c_str(), 0);
assert(p.first->second);
} else { // Alias
fstWriterCreateVar(m_fst, vartype, FST_VD_IMPLICIT, len, name_str.c_str(), p.first->second);
}
}
//=============================================================================
// Callbacks
void VerilatedFst::addCallback(
VerilatedFstCallback_t initcb, VerilatedFstCallback_t fullcb,
VerilatedFstCallback_t changecb, void* userthis) VL_MT_UNSAFE_ONE {
m_assertOne.check();
if (VL_UNLIKELY(isOpen())) {
std::string msg = std::string("Internal: ")+__FILE__+"::"+__FUNCTION__+" called with already open file";
VL_FATAL_MT(__FILE__,__LINE__,"",msg.c_str());
}
VerilatedFstCallInfo* vci = new VerilatedFstCallInfo(initcb, fullcb, changecb, userthis, 1);
m_callbacks.push_back(vci);
}
//=============================================================================
// Dumping
void VerilatedFst::dump(vluint64_t timeui) {
if (!isOpen()) return;
if (VL_UNLIKELY(m_fullDump)) {
m_fullDump = false; // No need for more full dumps
for (vluint32_t ent = 0; ent< m_callbacks.size(); ++ent) {
VerilatedFstCallInfo* cip = m_callbacks[ent];
(cip->m_fullcb)(this, cip->m_userthis, cip->m_code);
}
return;
}
fstWriterEmitTimeChange(m_fst, timeui);
for (vluint32_t ent = 0; ent< m_callbacks.size(); ++ent) {
VerilatedFstCallInfo* cip = m_callbacks[ent];
(cip->m_changecb)(this, cip->m_userthis, cip->m_code);
}
}
//=============================================================================
// Helpers
char* VerilatedFst::word2Str(vluint32_t newval, int bits) {
m_valueStrBuffer.resize(bits+1);
char* s = m_valueStrBuffer.data();
for (int i = 0; i < bits; ++i) {
*s = '0' + ((newval>>(bits-i-1))&1);
++s;
}
*s = '\0';
return m_valueStrBuffer.data();
}
char* VerilatedFst::quad2Str(vluint64_t newval, int bits) {
m_valueStrBuffer.resize(bits+1);
char* s = m_valueStrBuffer.data();
for (int i = 0; i < bits; ++i) {
*s = '0' + ((newval>>(bits-i-1))&1);
++s;
}
*s = '\0';
return m_valueStrBuffer.data();
}
char* VerilatedFst::array2Str(const vluint32_t* newval, int bits) {
int bq = bits/32, br = bits%32;
m_valueStrBuffer.resize(bits+1);
char* s = m_valueStrBuffer.data();
for (int w = bq-1; w >= 0; --w) {
for (int i = 0; i < 32; ++i) {
*s = '0' + ((newval[w]>>(32-i-1))&1);
++s;
}
}
for (int i = 0; i < br; ++i) {
*s = '0' + ((newval[bq]>>(br-i-1))&1);
++s;
}
*s = '\0';
return m_valueStrBuffer.data();
}
//********************************************************************
// Local Variables:
// End:

209
include/verilated_fst_c.h Normal file
View File

@ -0,0 +1,209 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2018 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.
//
// This is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
//=============================================================================
///
/// \file
/// \brief C++ Tracing in FST Format
///
//=============================================================================
// SPDIFF_OFF
#ifndef _VERILATED_FST_C_H_
#define _VERILATED_FST_C_H_ 1
#include "verilatedos.h"
#include "verilated.h"
#include "gtkwave/fstapi.h"
#include <string>
#include <vector>
#include <list>
#include <map>
class VerilatedFst;
class VerilatedFstCallInfo;
typedef void (*VerilatedFstCallback_t)(VerilatedFst* vcdp, void* userthis, vluint32_t code);
//=============================================================================
// VerilatedFst
/// Base class to create a Verilator FST dump
/// This is an internally used class - see VerilatedFstC for what to call from applications
class VerilatedFst {
typedef std::map<vluint32_t, fstHandle> Code2SymbolType;
typedef std::vector<VerilatedFstCallInfo*> CallbackVec;
private:
void* m_fst;
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
bool m_fullDump;
char m_scopeEscape;
std::string m_module;
CallbackVec m_callbacks; ///< Routines to perform dumping
Code2SymbolType m_code2symbol;
std::list<std::string> m_curScope;
// CONSTRUCTORS
VL_UNCOPYABLE(VerilatedFst);
void declSymbol(vluint32_t code, const char* name, int arraynum, uint32_t len, fstVarType vartype);
// helpers
std::vector<char> 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); } }
bool isOpen() const { return m_fst != NULL; }
void open(const char* filename) VL_MT_UNSAFE;
void flush() VL_MT_UNSAFE { fstWriterFlushContext(m_fst); }
void close() VL_MT_UNSAFE {
m_assertOne.check();
fstWriterClose(m_fst);
m_fst = NULL;
}
// void set_time_unit(const char* unit); ///< Set time units (s/ms, defaults to ns)
// void set_time_unit(const std::string& unit) { set_time_unit(unit.c_str()); }
// void set_time_resolution(const char* unit); ///< Set time resolution (s/ms, defaults to ns)
// void set_time_resolution(const std::string& unit) { set_time_resolution(unit.c_str()); }
// double timescaleToDouble(const char* unitp);
// std::string doubleToTimescale(double value);
/// Change character that splits scopes. Note whitespace are ALWAYS escapes.
void scopeEscape(char flag) { m_scopeEscape = flag; }
/// Is this an escape?
bool isScopeEscape(char c) { return isspace(c) || c==m_scopeEscape; }
/// Inside dumping routines, called each cycle to make the dump
void dump(vluint64_t timeui);
/// Inside dumping routines, declare callbacks for tracings
void addCallback(VerilatedFstCallback_t init, VerilatedFstCallback_t full,
VerilatedFstCallback_t change,
void* userthis) VL_MT_UNSAFE_ONE;
/// Inside dumping routines, declare a module
void module(const std::string& name);
/// Inside dumping routines, declare a signal
void declBit(vluint32_t code, const char* name, int arraynum) {
this->declSymbol(code, name, arraynum, 1, FST_VT_VCD_WIRE);
}
void declBus(vluint32_t code, const char* name, int arraynum, int msb, int lsb) {
this->declSymbol(code, name, arraynum, msb - lsb + 1, FST_VT_VCD_WIRE);
}
void declDouble(vluint32_t code, const char* name, int arraynum) {
this->declSymbol(code, name, arraynum, 2, FST_VT_VCD_REAL);
}
void declFloat(vluint32_t code, const char* name, int arraynum) {
this->declSymbol(code, name, arraynum, 1, FST_VT_SV_SHORTREAL);
}
void declQuad(vluint32_t code, const char* name, int arraynum, int msb, int lsb) {
this->declSymbol(code, name, arraynum, msb - lsb + 1, FST_VT_VCD_WIRE);
}
void declArray(vluint32_t code, const char* name, int arraynum, int msb, int lsb) {
this->declSymbol(code, name, arraynum, msb - lsb + 1, FST_VT_VCD_WIRE);
}
/// Inside dumping routines, dump one signal if it has changed
void chgBit(vluint32_t code, const vluint32_t newval) {
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));
}
void chgDouble(vluint32_t code, const double newval) {
double val = newval;
fstWriterEmitValueChange(m_fst, m_code2symbol[code], &val);
}
void chgFloat(vluint32_t code, const float newval) {
double val = (double)newval;
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));
}
void chgArray(vluint32_t code, const vluint32_t* newval, int bits) {
fstWriterEmitValueChange(m_fst, m_code2symbol[code], array2Str(newval, bits));
}
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); }
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);
};
//=============================================================================
// VerilatedFstC
/// Create a FST dump file in C standalone (no SystemC) simulations.
/// Also derived for use in SystemC simulations.
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
class VerilatedFstC {
VerilatedFst m_sptrace; ///< Trace file being created
// CONSTRUCTORS
VL_UNCOPYABLE(VerilatedFstC);
public:
explicit VerilatedFstC(void* filep=NULL) : m_sptrace(filep) {}
~VerilatedFstC() {}
public:
// ACCESSORS
/// Is file open?
bool isOpen() const { return m_sptrace.isOpen(); }
// METHODS
/// Open a new FST file
void open(const char* filename) VL_MT_UNSAFE_ONE { m_sptrace.open(filename); }
/// Close dump
void close() VL_MT_UNSAFE_ONE { m_sptrace.close(); }
/// Flush dump
void flush() VL_MT_UNSAFE_ONE { m_sptrace.flush(); }
/// Write one cycle of dump data
void dump(vluint64_t timeui) { m_sptrace.dump(timeui); }
/// Write one cycle of dump data - backward compatible and to reduce
/// conversion warnings. It's better to use a vluint64_t time instead.
void dump(double timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
void dump(vluint32_t timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
void dump(int timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
/// Set time units (s/ms, defaults to ns)
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
void set_time_unit(const char* unit) { /* TODO */ }
void set_time_unit(const std::string& unit) { set_time_unit(unit.c_str()); }
/// Set time resolution (s/ms, defaults to ns)
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
void set_time_resolution(const char* unit) { /* TODO */ }
void set_time_resolution(const std::string& unit) { set_time_resolution(unit.c_str()); }
/// Internal class access
inline VerilatedFst* spTrace() { return &m_sptrace; };
};
#endif // guard

View File

@ -695,6 +695,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( !strcmp (sw, "-sv") ) { m_defaultLanguage = V3LangCode::L1800_2005; }
else if ( onoff (sw, "-threads-coarsen", flag/*ref*/)) { m_threadsCoarsen = flag; } // Undocumented, debug
else if ( onoff (sw, "-trace", flag/*ref*/) ) { m_trace = flag; }
else if ( onoff (sw, "-trace-fst", flag/*ref*/) ) { m_trace = flag; m_traceFormat = TraceFormat::FST; addLdLibs("-lz"); }
else if ( onoff (sw, "-trace-lxt2", flag/*ref*/) ) { m_trace = flag; m_traceFormat = TraceFormat::LXT2; addLdLibs("-lz"); }
else if ( onoff (sw, "-trace-dups", flag/*ref*/) ) { m_traceDups = flag; }
else if ( onoff (sw, "-trace-params", flag/*ref*/) ) { m_traceParams = flag; }

View File

@ -40,7 +40,8 @@ class TraceFormat {
public:
enum en {
VCD = 0,
LXT2
LXT2,
FST
} m_e;
inline TraceFormat(en _e = VCD) : m_e(_e) {}
explicit inline TraceFormat(int _e) : m_e(static_cast<en>(_e)) {}
@ -48,14 +49,16 @@ public:
string classBase() const {
static const char* const names[] = {
"VerilatedVcd",
"VerilatedLxt2"
"VerilatedLxt2",
"VerilatedFst"
};
return names[m_e];
}
string sourceName() const {
static const char* const names[] = {
"verilated_vcd",
"verilated_lxt2"
"verilated_lxt2",
"verilated_fst"
};
return names[m_e];
}

View File

@ -71,13 +71,10 @@ sub process {
next if $line =~ m!^make.*Entering directory !;
next if $line =~ m!^make.*Leaving directory !;
next if $line =~ m!^\s+$!g;
# Specific suppressions
next if $line =~ m!id="missingInclude" .*systemc.h!;
next if $line =~ m!id="missingInclude" .*svdpi.h!;
next if $line =~ m!id="unusedFunction" .*sv! && $line =~ m!verilated_dpi.cpp!;
next if $line =~ m!id="unusedFunction" .*vpi! && $line =~ m!verilated_vpi.cpp!;
next if $line =~ m!id="unusedPrivateFunction" .*::debug!; # Doesn't know UINFO will use it
next if $line =~ m!file=".*obj_dbg/V3ParseBison.c".* id="unreachableCode"!;
# Specific suppressions (see _suppress also)
next if $line =~ m!id="unusedPrivateFunction" .*::debug!; # Doesn't know UINFO will use it
# Output
if ($line =~ /^cppcheck --/) {
print $line if $Debug;
@ -136,6 +133,15 @@ sub _suppress {
return undef if $filename eq "*";
# Specific suppressions
return 1 if $id eq "missingInclude" && $filename =~ m!systemc.h!;
return 1 if $id eq "missingInclude" && $filename =~ m!svdpi.h!;
return 1 if $id eq "unusedFunction" && $filename =~ m!verilated_dpi.cpp!;
return 1 if $id eq "unusedFunction" && $filename =~ m!verilated_vpi.cpp!;
return 1 if $id eq "unreachableCode" && $filename =~ /V3ParseBison.c/;
return 1 if $id eq 'variableScope' && $filename =~ /fstapi.c/;
return 1 if $id eq 'variableScope' && $filename =~ /lxt2_write.c/;
my $fh = IO::File->new("<$filename");
if (!$fh) {
warn "%Warning: $! $filename,";

View File

@ -587,8 +587,11 @@ sub compile_vlt_flags {
@{$param{verilator_flags2}},
@{$param{verilator_flags3}});
$self->{sc} = 1 if ($checkflags =~ /-sc\b/);
$self->{trace} = ($opt_trace || $checkflags =~ /-trace\b/ || $checkflags =~ /-trace-lxt2\b/);
$self->{trace_format} = (($checkflags =~ /-trace-lxt2\b/ && 'lxt2-c')
$self->{trace} = ($opt_trace || $checkflags =~ /-trace\b/
|| $checkflags =~ /-trace-fst\b/
|| $checkflags =~ /-trace-lxt2\b/);
$self->{trace_format} = (($checkflags =~ /-trace-fst\b/ && 'fst-c')
|| ($checkflags =~ /-trace-lxt2\b/ && 'lxt2-c')
|| ($self->{sc} && 'vcd-sc')
|| (!$self->{sc} && 'vcd-c'));
$self->{savable} = 1 if ($checkflags =~ /-savable\b/);
@ -1016,6 +1019,7 @@ sub have_sc {
sub trace_filename {
my $self = shift;
return "$self->{obj_dir}/simx.fst" if $self->{trace_format} =~ /^fst/;
return "$self->{obj_dir}/simx.lxt2" if $self->{trace_format} =~ /^lxt2/;
return "$self->{obj_dir}/simx.vcd";
}
@ -1185,6 +1189,7 @@ sub _make_main {
print $fh "// General headers\n";
print $fh "#include \"verilated.h\"\n";
print $fh "#include \"systemc.h\"\n" if $self->sc;
print $fh "#include \"verilated_fst_c.h\"\n" if $self->{trace} && $self->{trace_format} eq 'fst-c';
print $fh "#include \"verilated_lxt2_c.h\"\n" if $self->{trace} && $self->{trace_format} eq 'lxt2-c';
print $fh "#include \"verilated_vcd_c.h\"\n" if $self->{trace} && $self->{trace_format} eq 'vcd-c';
print $fh "#include \"verilated_vcd_sc.h\"\n" if $self->{trace} && $self->{trace_format} eq 'vcd-sc';
@ -1249,9 +1254,10 @@ sub _make_main {
$fh->print("\n");
$fh->print("#if VM_TRACE\n");
$fh->print(" Verilated::traceEverOn(true);\n");
$fh->print(" VerilatedFstC* tfp = new VerilatedFstC;\n") if $self->{trace_format} eq 'fst-c';
$fh->print(" VerilatedLxt2C* tfp = new VerilatedLxt2C;\n") if $self->{trace_format} eq 'lxt2-c';
$fh->print(" VerilatedVcdC* tfp = new VerilatedVcdC;\n") if $self->{trace_format} eq 'vcd-c';
$fh->print(" VerilatedVcdSc* tfp = new VerilatedVcdSc;\n") if $self->{trace_format} eq 'vcd-sc';
$fh->print(" VerilatedLxt2C* tfp = new VerilatedLxt2C;\n") if $self->{trace_format} eq 'lxt2-c';
$fh->print(" topp->trace(tfp, 99);\n");
$fh->print(" tfp->open(\"".$self->trace_filename."\");\n");
if ($self->{trace} && !$self->sc) {
@ -1604,6 +1610,22 @@ sub vcd_identical {
return 1;
}
sub fst2vcd {
my $self = (ref $_[0]? shift : $Self);
my $fn1 = shift;
my $fn2 = shift;
if (!-r $fn1) { $self->error("File does not exist $fn1\n"); return 0; }
my $cmd = qq{fst2vcd --help};
print "\t$cmd\n" if $::Debug;
my $out = `$cmd`;
if ($out !~ /Usage:/) { $self->skip("No fst2vcd installed\n"); return 0; }
$cmd = qq{fst2vcd "$fn1" -o "$fn2"};
print "\t$cmd\n" if $::Debug;
$out = `$cmd`;
return 1;
}
sub lxt2vcd {
my $self = (ref $_[0]? shift : $Self);
my $fn1 = shift;
@ -1620,7 +1642,6 @@ sub lxt2vcd {
return 1;
}
sub _vcd_read {
my $self = (ref $_[0]? shift : $Self);
my $filename = shift;

View File

@ -0,0 +1,57 @@
$date
Tue Aug 28 17:08:13 2018
$end
$version
lxt2vcd
$end
$timescale 1ns $end
$scope module top $end
$var wire 1 ! clk $end
$scope module t $end
$scope module biggie $end
$var wire 1048577 " d [1048576:0] $end
$upscope $end
$var wire 32 # cyc [31:0] $end
$var wire 1 ! clk $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
#0
0!
b0 "
b0 #
#10
b1 #
b111111101110110111111010110011100 "
1!
#15
0!
#20
1!
b1111111011101101111110101100111000 "
b10 #
#25
0!
#30
1!
b11 #
b11111110111011011111101011001110000 "
#35
0!
#40
1!
b111111101110110111111010110011100000 "
b100 #
#45
0!
#50
1!
b101 #
b1111111011101101111110101100111000000 "
#55
0!
#60
1!
b11111110111011011111101011001110000000 "
b110 #

View File

@ -0,0 +1,26 @@
#!/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.
scenarios(vlt => 1);
top_filename("t/t_trace_array.v");
compile(
verilator_flags2 => ['--cc --trace-fst --trace-structs'],
);
execute(
check_finished => 1,
);
fst2vcd($Self->trace_filename, "$Self->{obj_dir}/simx-fst2vcd.vcd");
vcd_identical("$Self->{obj_dir}/simx-fst2vcd.vcd", "t/$Self->{name}.out");
ok(1);
1;

View File

@ -0,0 +1,205 @@
$date
Tue Oct 2 18:35:11 2018
$end
$version
fstWriter
$end
$timescale
1ns
$end
$scope module top $end
$var wire 1 ! clk $end
$scope module t $end
$var wire 1 ! clk $end
$var wire 32 " cyc $end
$var wire 2 # v_strp $end
$var wire 4 $ v_strp_strp $end
$var wire 2 % v_unip_strp $end
$var wire 2 & v_arrp $end
$var wire 4 ' v_arrp_arrp $end
$var wire 4 ( v_arrp_strp $end
$var wire 1 ) v_arru(1) $end
$var wire 1 * v_arru(2) $end
$var wire 1 + v_arru_arru(3)(1) $end
$var wire 1 , v_arru_arru(3)(2) $end
$var wire 1 - v_arru_arru(4)(1) $end
$var wire 1 . v_arru_arru(4)(2) $end
$var wire 2 / v_arru_arrp(3) $end
$var wire 2 0 v_arru_arrp(4) $end
$var wire 2 1 v_arru_strp(3) $end
$var wire 2 2 v_arru_strp(4) $end
$var real 64 3 v_real $end
$var real 64 4 v_arr_real(0) $end
$var real 64 5 v_arr_real(1) $end
$var wire 64 6 v_str32x2 $end
$scope module unnamedblk1 $end
$var wire 32 7 b $end
$scope module unnamedblk2 $end
$var wire 32 8 a $end
$upscope $end
$upscope $end
$scope module p2 $end
$var wire 32 9 PARAM $end
$upscope $end
$scope module p3 $end
$var wire 32 : PARAM $end
$upscope $end
$upscope $end
$scope module $unit $end
$var wire 1 ; global_bit $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
0!
b00000000000000000000000000000000 "
b00 #
b0000 $
b00 %
b00 &
b0000 '
b0000 (
0)
0*
0+
0,
0-
0.
b00 /
b00 0
b00 1
b00 2
r0 3
r0 4
r0 5
b0000000000000000000000000000000000000000000000000000000011111111 6
b00000000000000000000000000000000 7
b00000000000000000000000000000000 8
b00000000000000000000000000000010 9
b00000000000000000000000000000011 :
1;
#10
b00000000000000000000000000000101 8
b00000000000000000000000000000101 7
b0000000000000000000000000000000100000000000000000000000011111110 6
r0.3 5
r0.2 4
r0.1 3
b11 2
b11 1
b11 0
b11 /
b1111 (
b1111 '
b11 &
b11 %
b1111 $
b11 #
b00000000000000000000000000000001 "
1!
#15
0!
#20
1!
b00000000000000000000000000000010 "
b00 #
b0000 $
b00 %
b00 &
b0000 '
b0000 (
b00 /
b00 0
b00 1
b00 2
r0.2 3
r0.4 4
r0.6 5
b0000000000000000000000000000001000000000000000000000000011111101 6
b00000000000000000000000000000101 7
b00000000000000000000000000000101 8
#25
0!
#30
1!
b00000000000000000000000000000101 8
b00000000000000000000000000000101 7
b0000000000000000000000000000001100000000000000000000000011111100 6
r0.8999999999999999 5
r0.6000000000000001 4
r0.3 3
b11 2
b11 1
b11 0
b11 /
b1111 (
b1111 '
b11 &
b11 %
b1111 $
b11 #
b00000000000000000000000000000011 "
#35
0!
#40
1!
b00000000000000000000000000000100 "
b00 #
b0000 $
b00 %
b00 &
b0000 '
b0000 (
b00 /
b00 0
b00 1
b00 2
r0.4 3
r0.8 4
r1.2 5
b0000000000000000000000000000010000000000000000000000000011111011 6
b00000000000000000000000000000101 7
b00000000000000000000000000000101 8
#45
0!
#50
1!
b00000000000000000000000000000101 8
b00000000000000000000000000000101 7
b0000000000000000000000000000010100000000000000000000000011111010 6
r1.5 5
r1 4
r0.5 3
b11 2
b11 1
b11 0
b11 /
b1111 (
b1111 '
b11 &
b11 %
b1111 $
b11 #
b00000000000000000000000000000101 "
#55
0!
#60
1!
b00000000000000000000000000000110 "
b00 #
b0000 $
b00 %
b00 &
b0000 '
b0000 (
b00 /
b00 0
b00 1
b00 2
r0.6 3
r1.2 4
r1.8 5
b0000000000000000000000000000011000000000000000000000000011111001 6
b00000000000000000000000000000101 7
b00000000000000000000000000000101 8

View File

@ -0,0 +1,26 @@
#!/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.
scenarios(simulator => 1);
top_filename("t/t_trace_complex.v");
compile(
verilator_flags2 => ['--cc --trace-fst'],
);
execute(
check_finished => 1,
);
fst2vcd($Self->trace_filename, "$Self->{obj_dir}/simx-fst2vcd.vcd");
vcd_identical("$Self->{obj_dir}/simx-fst2vcd.vcd", "t/$Self->{name}.out");
ok(1);
1;

View File

@ -0,0 +1,205 @@
$date
Tue Oct 2 18:35:13 2018
$end
$version
fstWriter
$end
$timescale
1ns
$end
$scope module top $end
$var wire 1 ! clk $end
$scope module t $end
$var wire 1 ! clk $end
$var wire 32 " cyc $end
$var wire 2 # v_strp $end
$var wire 4 $ v_strp_strp $end
$var wire 2 % v_unip_strp $end
$var wire 2 & v_arrp $end
$var wire 4 ' v_arrp_arrp $end
$var wire 4 ( v_arrp_strp $end
$var wire 1 ) v_arru(1) $end
$var wire 1 * v_arru(2) $end
$var wire 1 + v_arru_arru(3)(1) $end
$var wire 1 , v_arru_arru(3)(2) $end
$var wire 1 - v_arru_arru(4)(1) $end
$var wire 1 . v_arru_arru(4)(2) $end
$var wire 2 / v_arru_arrp(3) $end
$var wire 2 0 v_arru_arrp(4) $end
$var wire 2 1 v_arru_strp(3) $end
$var wire 2 2 v_arru_strp(4) $end
$var real 64 3 v_real $end
$var real 64 4 v_arr_real(0) $end
$var real 64 5 v_arr_real(1) $end
$var wire 64 6 v_str32x2 $end
$scope module unnamedblk1 $end
$var wire 32 7 b $end
$scope module unnamedblk2 $end
$var wire 32 8 a $end
$upscope $end
$upscope $end
$scope module p2 $end
$var wire 32 9 PARAM $end
$upscope $end
$scope module p3 $end
$var wire 32 : PARAM $end
$upscope $end
$upscope $end
$scope module $unit $end
$var wire 1 ; global_bit $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
0!
b00000000000000000000000000000000 "
b00 #
b0000 $
b00 %
b00 &
b0000 '
b0000 (
0)
0*
0+
0,
0-
0.
b00 /
b00 0
b00 1
b00 2
r0 3
r0 4
r0 5
b0000000000000000000000000000000000000000000000000000000011111111 6
b00000000000000000000000000000000 7
b00000000000000000000000000000000 8
b00000000000000000000000000000010 9
b00000000000000000000000000000011 :
1;
#10
b00000000000000000000000000000101 8
b00000000000000000000000000000101 7
b0000000000000000000000000000000100000000000000000000000011111110 6
r0.3 5
r0.2 4
r0.1 3
b11 2
b11 1
b11 0
b11 /
b1111 (
b1111 '
b11 &
b11 %
b1111 $
b11 #
b00000000000000000000000000000001 "
1!
#15
0!
#20
1!
b00000000000000000000000000000010 "
b00 #
b0000 $
b00 %
b00 &
b0000 '
b0000 (
b00 /
b00 0
b00 1
b00 2
r0.2 3
r0.4 4
r0.6 5
b0000000000000000000000000000001000000000000000000000000011111101 6
b00000000000000000000000000000101 7
b00000000000000000000000000000101 8
#25
0!
#30
1!
b00000000000000000000000000000101 8
b00000000000000000000000000000101 7
b0000000000000000000000000000001100000000000000000000000011111100 6
r0.8999999999999999 5
r0.6000000000000001 4
r0.3 3
b11 2
b11 1
b11 0
b11 /
b1111 (
b1111 '
b11 &
b11 %
b1111 $
b11 #
b00000000000000000000000000000011 "
#35
0!
#40
1!
b00000000000000000000000000000100 "
b00 #
b0000 $
b00 %
b00 &
b0000 '
b0000 (
b00 /
b00 0
b00 1
b00 2
r0.4 3
r0.8 4
r1.2 5
b0000000000000000000000000000010000000000000000000000000011111011 6
b00000000000000000000000000000101 7
b00000000000000000000000000000101 8
#45
0!
#50
1!
b00000000000000000000000000000101 8
b00000000000000000000000000000101 7
b0000000000000000000000000000010100000000000000000000000011111010 6
r1.5 5
r1 4
r0.5 3
b11 2
b11 1
b11 0
b11 /
b1111 (
b1111 '
b11 &
b11 %
b1111 $
b11 #
b00000000000000000000000000000101 "
#55
0!
#60
1!
b00000000000000000000000000000110 "
b00 #
b0000 $
b00 %
b00 &
b0000 '
b0000 (
b00 /
b00 0
b00 1
b00 2
r0.6 3
r1.2 4
r1.8 5
b0000000000000000000000000000011000000000000000000000000011111001 6
b00000000000000000000000000000101 7
b00000000000000000000000000000101 8

View File

@ -0,0 +1,26 @@
#!/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.
scenarios(simulator => 1);
top_filename("t_trace_complex.v");
compile(
verilator_flags2 => ['--cc --trace-fst --no-trace-structs --trace-params'],
);
execute(
check_finished => 1,
);
fst2vcd($Self->trace_filename, "$Self->{obj_dir}/simx-fst2vcd.vcd");
vcd_identical("$Self->{obj_dir}/simx-fst2vcd.vcd", "t/$Self->{name}.out");
ok(1);
1;

View File

@ -0,0 +1,321 @@
$date
Tue Oct 2 18:35:16 2018
$end
$version
fstWriter
$end
$timescale
1ns
$end
$scope module top $end
$var wire 1 ! clk $end
$scope module t $end
$var wire 1 ! clk $end
$var wire 32 " cyc $end
$scope module v_strp $end
$var wire 1 # b1 $end
$var wire 1 $ b0 $end
$upscope $end
$scope module v_strp_strp $end
$scope module x1 $end
$var wire 1 % b1 $end
$var wire 1 & b0 $end
$upscope $end
$scope module x0 $end
$var wire 1 ' b1 $end
$var wire 1 ( b0 $end
$upscope $end
$upscope $end
$scope module v_unip_strp $end
$scope module x1 $end
$var wire 1 ) b1 $end
$var wire 1 * b0 $end
$upscope $end
$scope module x0 $end
$var wire 1 ) b1 $end
$var wire 1 * b0 $end
$upscope $end
$upscope $end
$var wire 2 + v_arrp $end
$var wire 2 , v_arrp_arrp(3) $end
$var wire 2 - v_arrp_arrp(4) $end
$scope module v_arrp_strp(3) $end
$var wire 1 . b1 $end
$var wire 1 / b0 $end
$upscope $end
$scope module v_arrp_strp(4) $end
$var wire 1 0 b1 $end
$var wire 1 1 b0 $end
$upscope $end
$var wire 1 2 v_arru(1) $end
$var wire 1 3 v_arru(2) $end
$var wire 1 4 v_arru_arru(3)(1) $end
$var wire 1 5 v_arru_arru(3)(2) $end
$var wire 1 6 v_arru_arru(4)(1) $end
$var wire 1 7 v_arru_arru(4)(2) $end
$var wire 2 8 v_arru_arrp(3) $end
$var wire 2 9 v_arru_arrp(4) $end
$scope module v_arru_strp(3) $end
$var wire 1 : b1 $end
$var wire 1 ; b0 $end
$upscope $end
$scope module v_arru_strp(4) $end
$var wire 1 < b1 $end
$var wire 1 = b0 $end
$upscope $end
$var real 64 > v_real $end
$var real 64 ? v_arr_real(0) $end
$var real 64 @ v_arr_real(1) $end
$scope module v_str32x2(0) $end
$var wire 32 A data $end
$upscope $end
$scope module v_str32x2(1) $end
$var wire 32 B data $end
$upscope $end
$scope module unnamedblk1 $end
$var wire 32 C b $end
$scope module unnamedblk2 $end
$var wire 32 D a $end
$upscope $end
$upscope $end
$upscope $end
$scope module $unit $end
$var wire 1 E global_bit $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
0!
b00000000000000000000000000000000 "
0#
0$
0%
0&
0'
0(
0)
0*
b00 +
b00 ,
b00 -
0.
0/
00
01
02
03
04
05
06
07
b00 8
b00 9
0:
0;
0<
0=
r0 >
r0 ?
r0 @
b00000000000000000000000011111111 A
b00000000000000000000000000000000 B
b00000000000000000000000000000000 C
b00000000000000000000000000000000 D
1E
#10
b00000000000000000000000000000101 D
b00000000000000000000000000000101 C
b00000000000000000000000000000001 B
b00000000000000000000000011111110 A
r0.3 @
r0.2 ?
r0.1 >
1=
1<
1;
1:
b11 9
b11 8
11
10
1/
1.
b11 -
b11 ,
b11 +
1*
1)
1(
1'
1&
1%
1$
1#
b00000000000000000000000000000001 "
1!
#15
0!
#20
1!
b00000000000000000000000000000010 "
0#
0$
0%
0&
0'
0(
0)
0*
b00 +
b00 ,
b00 -
0.
0/
00
01
b00 8
b00 9
0:
0;
0<
0=
r0.2 >
r0.4 ?
r0.6 @
b00000000000000000000000011111101 A
b00000000000000000000000000000010 B
b00000000000000000000000000000101 C
b00000000000000000000000000000101 D
#25
0!
#30
1!
b00000000000000000000000000000101 D
b00000000000000000000000000000101 C
b00000000000000000000000000000011 B
b00000000000000000000000011111100 A
r0.8999999999999999 @
r0.6000000000000001 ?
r0.3 >
1=
1<
1;
1:
b11 9
b11 8
11
10
1/
1.
b11 -
b11 ,
b11 +
1*
1)
1(
1'
1&
1%
1$
1#
b00000000000000000000000000000011 "
#35
0!
#40
1!
b00000000000000000000000000000100 "
0#
0$
0%
0&
0'
0(
0)
0*
b00 +
b00 ,
b00 -
0.
0/
00
01
b00 8
b00 9
0:
0;
0<
0=
r0.4 >
r0.8 ?
r1.2 @
b00000000000000000000000011111011 A
b00000000000000000000000000000100 B
b00000000000000000000000000000101 C
b00000000000000000000000000000101 D
#45
0!
#50
1!
b00000000000000000000000000000101 D
b00000000000000000000000000000101 C
b00000000000000000000000000000101 B
b00000000000000000000000011111010 A
r1.5 @
r1 ?
r0.5 >
1=
1<
1;
1:
b11 9
b11 8
11
10
1/
1.
b11 -
b11 ,
b11 +
1*
1)
1(
1'
1&
1%
1$
1#
b00000000000000000000000000000101 "
#55
0!
#60
1!
b00000000000000000000000000000110 "
0#
0$
0%
0&
0'
0(
0)
0*
b00 +
b00 ,
b00 -
0.
0/
00
01
b00 8
b00 9
0:
0;
0<
0=
r0.6 >
r1.2 ?
r1.8 @
b00000000000000000000000011111001 A
b00000000000000000000000000000110 B
b00000000000000000000000000000101 C
b00000000000000000000000000000101 D

View File

@ -0,0 +1,26 @@
#!/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.
scenarios(simulator => 1);
top_filename("t_trace_complex.v");
compile(
verilator_flags2 => ['--cc --trace-fst --trace-structs --no-trace-params'],
);
execute(
check_finished => 1,
);
fst2vcd($Self->trace_filename, "$Self->{obj_dir}/simx-fst2vcd.vcd");
vcd_identical("$Self->{obj_dir}/simx-fst2vcd.vcd", "t/$Self->{name}.out");
ok(1);
1;

File diff suppressed because it is too large Load Diff

22
test_regress/t/t_trace_fst.pl Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/perl
# This file ONLY is placed into the Public Domain, for any use,
# Author: Yu-Sheng Lin johnjohnlys@media.ee.ntu.edu.tw
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
scenarios(vlt_all => 1);
compile(
v_flags2 => ["--trace-fst"],
);
execute(
check_finished => 1,
);
fst2vcd($Self->trace_filename, "$Self->{obj_dir}/simx-fst2vcd.vcd");
vcd_identical("$Self->{obj_dir}/simx-fst2vcd.vcd", "t/$Self->{name}.out");
ok(1);
1;

View File

@ -0,0 +1,76 @@
// This file ONLY is placed into the Public Domain, for any use,
// Author: Yu-Sheng Lin johnjohnlys@media.ee.ntu.edu.tw
module t (/*AUTOARG*/
// Outputs
state,
// Inputs
clk
);
input clk;
int cyc;
reg rstn;
output [4:0] state;
Test test (/*AUTOINST*/
// Outputs
.state (state[4:0]),
// Inputs
.clk (clk),
.rstn (rstn));
// Test loop
always @ (posedge clk) begin
cyc <= cyc + 1;
if (cyc==0) begin
// Setup
rstn <= ~'1;
end
else if (cyc<10) begin
rstn <= ~'1;
end
else if (cyc<90) begin
rstn <= ~'0;
end
else if (cyc==99) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module Test (
input clk,
input rstn,
output logic [4:0] state
);
logic [4:0] state_w;
logic [4:0] state_array [3];
assign state = state_array[0];
always_comb begin
state_w[4] = state_array[2][0];
state_w[3] = state_array[2][4];
state_w[2] = state_array[2][3] ^ state_array[2][0];
state_w[1] = state_array[2][2];
state_w[0] = state_array[2][1];
end
always_ff @(posedge clk or negedge rstn) begin
if (!rstn) begin
for (int i = 0; i < 3; i++)
state_array[i] <= 'b1;
end
else begin
for (int i = 0; i < 2; i++)
state_array[i] <= state_array[i+1];
state_array[2] <= state_w;
end
end
endmodule

View File

@ -0,0 +1,45 @@
$date
Tue Oct 2 18:35:19 2018
$end
$version
fstWriter
$end
$timescale
1ns
$end
$scope module top $end
$var wire 1 ! clk $end
$scope module t $end
$var wire 1 ! clk $end
$var wire 32 " cnt $end
$var wire 96 # v(0) $end
$var wire 96 $ v(1) $end
$var wire 96 % v(2) $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
0!
b00000000000000000000000000000000 "
b001100000000000000000000000000100011000000000000000000000000000100110000000000000000000000000000 #
b001000000000000000000000000000100010000000000000000000000000000100100000000000000000000000000000 $
b000100000000000000000000000000100001000000000000000000000000000100010000000000000000000000000000 %
#10
b00000000000000000000000000000001 "
1!
#15
0!
#20
1!
b00000000000000000000000000000010 "
#25
0!
#30
1!
b00000000000000000000000000000011 "
#35
0!
#40
1!
b00000000000000000000000000000011 "

View File

@ -0,0 +1,26 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
top_filename("t/t_trace_packed_struct.v");
compile(
v_flags2 => ["--trace-fst"]
);
execute(
check_finished => 1,
);
fst2vcd($Self->trace_filename, "$Self->{obj_dir}/simx-fst2vcd.vcd");
vcd_identical("$Self->{obj_dir}/simx-fst2vcd.vcd", "t/$Self->{name}.out");
ok(1);
1;

View File

@ -0,0 +1,23 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(vlt_all => 1);
top_filename("t/t_trace_param.v");
compile(
v_flags2 => ["--trace-fst"],
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,23 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
top_filename("t/t_trace_primitive.v");
compile(
v_flags2 => ["--trace-fst"],
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,23 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
top_filename("t/t_trace_string.v");
compile(
verilator_flags2 => ['--cc --trace'],
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -50,6 +50,7 @@ foreach my $file (sort keys %hit) {
if (!$hit{$file}
&& $file !~ /_sc/
&& $file !~ /_lxt2/
&& $file !~ /_fst/
&& ($file !~ /_thread/ || $Self->cfg_with_threaded)) {
error("Include file not covered by t_verilated_all test: ",$file);
}