For --trace-fst, save enum decoding information, bug1358.
This commit is contained in:
parent
870918a788
commit
cc45a3dd72
5
Changes
5
Changes
|
|
@ -5,6 +5,11 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||||
|
|
||||||
* Verilator 4.005 devel
|
* Verilator 4.005 devel
|
||||||
|
|
||||||
|
*** For --trace-fst, save enum decoding information, bug1358. [Sergi Granell]
|
||||||
|
(To visualize enumeration data you must use GTKwave 3.3.95 or newer.)
|
||||||
|
|
||||||
|
*** For --trace-fst, instead of *.fst.hier, put data into *.fst. [Tony Bybell]
|
||||||
|
|
||||||
|
|
||||||
* Verilator 4.004 2018-10-6
|
* Verilator 4.004 2018-10-6
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -795,6 +795,8 @@ char *geom_handle_nam;
|
||||||
char *valpos_handle_nam;
|
char *valpos_handle_nam;
|
||||||
char *curval_handle_nam;
|
char *curval_handle_nam;
|
||||||
char *tchn_handle_nam;
|
char *tchn_handle_nam;
|
||||||
|
|
||||||
|
fstEnumHandle max_enumhandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2305,7 +2307,7 @@ if(xc && path && path[0])
|
||||||
const unsigned char *path2 = (const unsigned char *)path;
|
const unsigned char *path2 = (const unsigned char *)path;
|
||||||
PPvoid_t pv;
|
PPvoid_t pv;
|
||||||
#else
|
#else
|
||||||
char *path2 = alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */
|
char *path2 = (char *)alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */
|
||||||
PPvoid_t pv;
|
PPvoid_t pv;
|
||||||
strcpy(path2, path);
|
strcpy(path2, path);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2726,6 +2728,111 @@ if(xc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits, const char **literal_arr, const char **val_arr)
|
||||||
|
{
|
||||||
|
fstEnumHandle handle = 0;
|
||||||
|
unsigned int *literal_lens = NULL;
|
||||||
|
unsigned int *val_lens = NULL;
|
||||||
|
int lit_len_tot = 0;
|
||||||
|
int val_len_tot = 0;
|
||||||
|
int name_len;
|
||||||
|
char elem_count_buf[16];
|
||||||
|
int elem_count_len;
|
||||||
|
int total_len;
|
||||||
|
int pos = 0;
|
||||||
|
char *attr_str = NULL;
|
||||||
|
|
||||||
|
if(ctx && name && literal_arr && val_arr && (elem_count != 0))
|
||||||
|
{
|
||||||
|
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
name_len = strlen(name);
|
||||||
|
elem_count_len = sprintf(elem_count_buf, "%" PRIu32, elem_count);
|
||||||
|
|
||||||
|
literal_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int));
|
||||||
|
val_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int));
|
||||||
|
|
||||||
|
for(i=0;i<elem_count;i++)
|
||||||
|
{
|
||||||
|
literal_lens[i] = strlen(literal_arr[i]);
|
||||||
|
lit_len_tot += fstUtilityBinToEscConvertedLen((unsigned char*)literal_arr[i], literal_lens[i]);
|
||||||
|
|
||||||
|
val_lens[i] = strlen(val_arr[i]);
|
||||||
|
val_len_tot += fstUtilityBinToEscConvertedLen((unsigned char*)val_arr[i], val_lens[i]);
|
||||||
|
|
||||||
|
if(min_valbits > 0)
|
||||||
|
{
|
||||||
|
if(val_lens[i] < min_valbits)
|
||||||
|
{
|
||||||
|
val_len_tot += (min_valbits - val_lens[i]); /* additional converted len is same for '0' character */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
total_len = name_len + 1 + elem_count_len + 1 + lit_len_tot + elem_count + val_len_tot + elem_count;
|
||||||
|
|
||||||
|
attr_str = (char*)malloc(total_len);
|
||||||
|
pos = 0;
|
||||||
|
|
||||||
|
memcpy(attr_str+pos, name, name_len);
|
||||||
|
pos += name_len;
|
||||||
|
attr_str[pos++] = ' ';
|
||||||
|
|
||||||
|
memcpy(attr_str+pos, elem_count_buf, elem_count_len);
|
||||||
|
pos += elem_count_len;
|
||||||
|
attr_str[pos++] = ' ';
|
||||||
|
|
||||||
|
for(i=0;i<elem_count;i++)
|
||||||
|
{
|
||||||
|
pos += fstUtilityBinToEsc((unsigned char*)attr_str+pos, (unsigned char*)literal_arr[i], literal_lens[i]);
|
||||||
|
attr_str[pos++] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;i<elem_count;i++)
|
||||||
|
{
|
||||||
|
if(min_valbits > 0)
|
||||||
|
{
|
||||||
|
if(val_lens[i] < min_valbits)
|
||||||
|
{
|
||||||
|
memset(attr_str+pos, '0', min_valbits - val_lens[i]);
|
||||||
|
pos += (min_valbits - val_lens[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += fstUtilityBinToEsc((unsigned char*)attr_str+pos, (unsigned char*)val_arr[i], val_lens[i]);
|
||||||
|
attr_str[pos++] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
attr_str[pos-1] = 0;
|
||||||
|
|
||||||
|
#ifdef FST_DEBUG
|
||||||
|
fprintf(stderr, FST_APIMESS"fstWriterCreateEnumTable() total_len: %d, pos: %d\n", total_len, pos);
|
||||||
|
fprintf(stderr, FST_APIMESS"*%s*\n", attr_str);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, attr_str, handle = ++xc->max_enumhandle);
|
||||||
|
|
||||||
|
free(attr_str);
|
||||||
|
free(val_lens);
|
||||||
|
free(literal_lens);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle)
|
||||||
|
{
|
||||||
|
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||||
|
if(xc && handle)
|
||||||
|
{
|
||||||
|
fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, NULL, handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* value and time change emission
|
* value and time change emission
|
||||||
*/
|
*/
|
||||||
|
|
@ -6503,9 +6610,46 @@ if(base && *base)
|
||||||
/*** ***/
|
/*** ***/
|
||||||
/************************/
|
/************************/
|
||||||
|
|
||||||
int fstUtilityBinToEsc(unsigned char *d, unsigned char *s, int len)
|
int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len)
|
||||||
{
|
{
|
||||||
unsigned char *src = s;
|
const unsigned char *src = s;
|
||||||
|
int dlen = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0;i<len;i++)
|
||||||
|
{
|
||||||
|
switch(src[i])
|
||||||
|
{
|
||||||
|
case '\a': /* fallthrough */
|
||||||
|
case '\b': /* fallthrough */
|
||||||
|
case '\f': /* fallthrough */
|
||||||
|
case '\n': /* fallthrough */
|
||||||
|
case '\r': /* fallthrough */
|
||||||
|
case '\t': /* fallthrough */
|
||||||
|
case '\v': /* fallthrough */
|
||||||
|
case '\'': /* fallthrough */
|
||||||
|
case '\"': /* fallthrough */
|
||||||
|
case '\\': /* fallthrough */
|
||||||
|
case '\?': dlen += 2; break;
|
||||||
|
default: if((src[i] > ' ') && (src[i] <= '~')) /* no white spaces in output */
|
||||||
|
{
|
||||||
|
dlen++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dlen += 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(dlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len)
|
||||||
|
{
|
||||||
|
const unsigned char *src = s;
|
||||||
unsigned char *dst = d;
|
unsigned char *dst = d;
|
||||||
unsigned char val;
|
unsigned char val;
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -6604,3 +6748,76 @@ for(i=0;i<len;i++)
|
||||||
|
|
||||||
return(dst - s);
|
return(dst - s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct fstETab *fstUtilityExtractEnumTableFromString(const char *s)
|
||||||
|
{
|
||||||
|
struct fstETab *et = NULL;
|
||||||
|
int num_spaces = 0;
|
||||||
|
int i;
|
||||||
|
int newlen;
|
||||||
|
|
||||||
|
if(s)
|
||||||
|
{
|
||||||
|
const char *csp = strchr(s, ' ');
|
||||||
|
int cnt = atoi(csp+1);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
csp = strchr(csp+1, ' ');
|
||||||
|
if(csp) { num_spaces++; } else { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if(num_spaces == (2*cnt))
|
||||||
|
{
|
||||||
|
char *sp, *sp2;
|
||||||
|
|
||||||
|
et = (struct fstETab*)calloc(1, sizeof(struct fstETab));
|
||||||
|
et->elem_count = cnt;
|
||||||
|
et->name = strdup(s);
|
||||||
|
et->literal_arr = (char**)calloc(cnt, sizeof(char *));
|
||||||
|
et->val_arr = (char**)calloc(cnt, sizeof(char *));
|
||||||
|
|
||||||
|
sp = strchr(et->name, ' ');
|
||||||
|
*sp = 0;
|
||||||
|
|
||||||
|
sp = strchr(sp+1, ' ');
|
||||||
|
|
||||||
|
for(i=0;i<cnt;i++)
|
||||||
|
{
|
||||||
|
sp2 = strchr(sp+1, ' ');
|
||||||
|
*(char*)sp2 = 0;
|
||||||
|
et->literal_arr[i] = sp+1;
|
||||||
|
sp = sp2;
|
||||||
|
|
||||||
|
newlen = fstUtilityEscToBin(NULL, (unsigned char*)et->literal_arr[i], strlen(et->literal_arr[i]));
|
||||||
|
et->literal_arr[i][newlen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;i<cnt;i++)
|
||||||
|
{
|
||||||
|
sp2 = strchr(sp+1, ' ');
|
||||||
|
if(sp2) { *sp2 = 0; }
|
||||||
|
et->val_arr[i] = sp+1;
|
||||||
|
sp = sp2;
|
||||||
|
|
||||||
|
newlen = fstUtilityEscToBin(NULL, (unsigned char*)et->val_arr[i], strlen(et->val_arr[i]));
|
||||||
|
et->val_arr[i][newlen] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(et);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void fstUtilityFreeEnumTable(struct fstETab *etab)
|
||||||
|
{
|
||||||
|
if(etab)
|
||||||
|
{
|
||||||
|
free(etab->literal_arr);
|
||||||
|
free(etab->val_arr);
|
||||||
|
free(etab->name);
|
||||||
|
free(etab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2017 Tony Bybell.
|
* Copyright (c) 2009-2018 Tony Bybell.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
|
@ -39,6 +39,7 @@ extern "C" {
|
||||||
#define FST_RDLOAD "FSTLOAD | "
|
#define FST_RDLOAD "FSTLOAD | "
|
||||||
|
|
||||||
typedef uint32_t fstHandle;
|
typedef uint32_t fstHandle;
|
||||||
|
typedef uint32_t fstEnumHandle;
|
||||||
|
|
||||||
enum fstWriterPackType {
|
enum fstWriterPackType {
|
||||||
FST_WR_PT_ZLIB = 0,
|
FST_WR_PT_ZLIB = 0,
|
||||||
|
|
@ -196,9 +197,10 @@ enum fstMiscType {
|
||||||
FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */
|
FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */
|
||||||
FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
|
FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
|
||||||
FST_MT_VALUELIST = 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
|
FST_MT_VALUELIST = 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
|
||||||
FST_MT_UNKNOWN = 7,
|
FST_MT_ENUMTABLE = 7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */
|
||||||
|
FST_MT_UNKNOWN = 8,
|
||||||
|
|
||||||
FST_MT_MAX = 7
|
FST_MT_MAX = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstArrayType {
|
enum fstArrayType {
|
||||||
|
|
@ -228,7 +230,10 @@ enum fstEnumValueType {
|
||||||
FST_EV_SV_UNSIGNED_LONGINT = 12,
|
FST_EV_SV_UNSIGNED_LONGINT = 12,
|
||||||
FST_EV_SV_UNSIGNED_BYTE = 13,
|
FST_EV_SV_UNSIGNED_BYTE = 13,
|
||||||
|
|
||||||
FST_EV_MAX = 13
|
FST_EV_REG = 14,
|
||||||
|
FST_EV_TIME = 15,
|
||||||
|
|
||||||
|
FST_EV_MAX = 15
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstPackType {
|
enum fstPackType {
|
||||||
|
|
@ -324,11 +329,21 @@ union {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct fstETab
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
uint32_t elem_count;
|
||||||
|
char **literal_arr;
|
||||||
|
char **val_arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* writer functions
|
* writer functions
|
||||||
*/
|
*/
|
||||||
void fstWriterClose(void *ctx);
|
void fstWriterClose(void *ctx);
|
||||||
void * fstWriterCreate(const char *nam, int use_compressed_hier);
|
void * fstWriterCreate(const char *nam, int use_compressed_hier);
|
||||||
|
fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits, const char **literal_arr, const char **val_arr);
|
||||||
/* used for Verilog/SV */
|
/* used for Verilog/SV */
|
||||||
fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd,
|
fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd,
|
||||||
uint32_t len, const char *nam, fstHandle aliasHandle);
|
uint32_t len, const char *nam, fstHandle aliasHandle);
|
||||||
|
|
@ -337,9 +352,10 @@ fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir
|
||||||
fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd,
|
fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd,
|
||||||
uint32_t len, const char *nam, fstHandle aliasHandle,
|
uint32_t len, const char *nam, fstHandle aliasHandle,
|
||||||
const char *type, enum fstSupplementalVarType svt, enum fstSupplementalDataType sdt);
|
const char *type, enum fstSupplementalVarType svt, enum fstSupplementalDataType sdt);
|
||||||
|
void fstWriterEmitDumpActive(void *ctx, int enable);
|
||||||
|
void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle);
|
||||||
void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val);
|
void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val);
|
||||||
void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len);
|
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 fstWriterEmitTimeChange(void *ctx, uint64_t tim);
|
||||||
void fstWriterFlushContext(void *ctx);
|
void fstWriterFlushContext(void *ctx);
|
||||||
int fstWriterGetDumpSizeLimitReached(void *ctx);
|
int fstWriterGetDumpSizeLimitReached(void *ctx);
|
||||||
|
|
@ -422,8 +438,12 @@ void fstReaderSetVcdExtensions(void *ctx, int enable);
|
||||||
/*
|
/*
|
||||||
* utility functions
|
* utility functions
|
||||||
*/
|
*/
|
||||||
int fstUtilityBinToEsc(unsigned char *d, unsigned char *s, int len);
|
int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len); /* used for mallocs for fstUtilityBinToEsc() */
|
||||||
|
int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len);
|
||||||
int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len);
|
int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len);
|
||||||
|
struct fstETab *fstUtilityExtractEnumTableFromString(const char *s);
|
||||||
|
void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,16 @@ void VerilatedFst::module(const std::string& name) {
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// Decl
|
// Decl
|
||||||
|
|
||||||
void VerilatedFst::declSymbol(vluint32_t code, const char* name, fstVarDir vardir,
|
void VerilatedFst::declDTypeEnum(int dtypenum, const char* name, vluint32_t elements,
|
||||||
fstVarType vartype,
|
unsigned int minValbits,
|
||||||
|
const char** itemNamesp, const char** itemValuesp) {
|
||||||
|
fstEnumHandle enumNum = fstWriterCreateEnumTable(m_fst, name, elements,
|
||||||
|
minValbits, itemNamesp, itemValuesp);
|
||||||
|
m_local2fstdtype[dtypenum] = enumNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedFst::declSymbol(vluint32_t code, const char* name,
|
||||||
|
int dtypenum, fstVarDir vardir, fstVarType vartype,
|
||||||
int arraynum, vluint32_t len) {
|
int arraynum, vluint32_t len) {
|
||||||
std::pair<Code2SymbolType::iterator, bool> p
|
std::pair<Code2SymbolType::iterator, bool> p
|
||||||
= m_code2symbol.insert(std::make_pair(code, (fstHandle)(0)));
|
= m_code2symbol.insert(std::make_pair(code, (fstHandle)(0)));
|
||||||
|
|
@ -135,6 +143,10 @@ void VerilatedFst::declSymbol(vluint32_t code, const char* name, fstVarDir vardi
|
||||||
name_ss << "(" << arraynum << ")";
|
name_ss << "(" << arraynum << ")";
|
||||||
std::string name_str = name_ss.str();
|
std::string name_str = name_ss.str();
|
||||||
|
|
||||||
|
if (dtypenum > 0) {
|
||||||
|
fstEnumHandle enumNum = m_local2fstdtype[dtypenum];
|
||||||
|
fstWriterEmitEnumTableRef(m_fst, enumNum);
|
||||||
|
}
|
||||||
if (p.second) { // New
|
if (p.second) { // New
|
||||||
p.first->second = fstWriterCreateVar(m_fst, vartype, vardir, len, name_str.c_str(), 0);
|
p.first->second = fstWriterCreateVar(m_fst, vartype, vardir, len, name_str.c_str(), 0);
|
||||||
assert(p.first->second);
|
assert(p.first->second);
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ typedef void (*VerilatedFstCallback_t)(VerilatedFst* vcdp, void* userthis, vluin
|
||||||
|
|
||||||
class VerilatedFst {
|
class VerilatedFst {
|
||||||
typedef std::map<vluint32_t, fstHandle> Code2SymbolType;
|
typedef std::map<vluint32_t, fstHandle> Code2SymbolType;
|
||||||
|
typedef std::map<int, fstEnumHandle> Local2FstDtype;
|
||||||
typedef std::vector<VerilatedFstCallInfo*> CallbackVec;
|
typedef std::vector<VerilatedFstCallInfo*> CallbackVec;
|
||||||
private:
|
private:
|
||||||
void* m_fst;
|
void* m_fst;
|
||||||
|
|
@ -52,11 +53,12 @@ private:
|
||||||
std::string m_module;
|
std::string m_module;
|
||||||
CallbackVec m_callbacks; ///< Routines to perform dumping
|
CallbackVec m_callbacks; ///< Routines to perform dumping
|
||||||
Code2SymbolType m_code2symbol;
|
Code2SymbolType m_code2symbol;
|
||||||
|
Local2FstDtype m_local2fstdtype;
|
||||||
std::list<std::string> m_curScope;
|
std::list<std::string> m_curScope;
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VL_UNCOPYABLE(VerilatedFst);
|
VL_UNCOPYABLE(VerilatedFst);
|
||||||
void declSymbol(vluint32_t code, const char* name,
|
void declSymbol(vluint32_t code, const char* name,
|
||||||
fstVarDir vardir, fstVarType vartype,
|
int dtypenum, fstVarDir vardir, fstVarType vartype,
|
||||||
int arraynum, vluint32_t len);
|
int arraynum, vluint32_t len);
|
||||||
// helpers
|
// helpers
|
||||||
std::vector<char> m_valueStrBuffer;
|
std::vector<char> m_valueStrBuffer;
|
||||||
|
|
@ -96,30 +98,40 @@ public:
|
||||||
|
|
||||||
/// Inside dumping routines, declare a module
|
/// Inside dumping routines, declare a module
|
||||||
void module(const std::string& name);
|
void module(const std::string& name);
|
||||||
|
/// Inside dumping routines, declare a data type
|
||||||
|
void declDTypeEnum(int dtypenum, const char* name, vluint32_t elements,
|
||||||
|
unsigned int minValbits,
|
||||||
|
const char** itemNamesp, const char** itemValuesp);
|
||||||
/// Inside dumping routines, declare a signal
|
/// Inside dumping routines, declare a signal
|
||||||
void declBit(vluint32_t code, const char* name, fstVarDir vardir, fstVarType vartype,
|
void declBit(vluint32_t code, const char* name,
|
||||||
|
int dtypenum, fstVarDir vardir, fstVarType vartype,
|
||||||
int arraynum) {
|
int arraynum) {
|
||||||
declSymbol(code, name, vardir, vartype, arraynum, 1);
|
declSymbol(code, name, dtypenum, vardir, vartype, arraynum, 1);
|
||||||
}
|
}
|
||||||
void declBus(vluint32_t code, const char* name, fstVarDir vardir, fstVarType vartype,
|
void declBus(vluint32_t code, const char* name,
|
||||||
|
int dtypenum, fstVarDir vardir, fstVarType vartype,
|
||||||
int arraynum, int msb, int lsb) {
|
int arraynum, int msb, int lsb) {
|
||||||
declSymbol(code, name, vardir, vartype, arraynum, msb - lsb + 1);
|
declSymbol(code, name, dtypenum, vardir, vartype, arraynum, msb - lsb + 1);
|
||||||
}
|
}
|
||||||
void declDouble(vluint32_t code, const char* name, fstVarDir vardir, fstVarType vartype,
|
void declDouble(vluint32_t code, const char* name,
|
||||||
|
int dtypenum, fstVarDir vardir, fstVarType vartype,
|
||||||
int arraynum) {
|
int arraynum) {
|
||||||
declSymbol(code, name, vardir, vartype, arraynum, 2);
|
declSymbol(code, name, dtypenum, vardir, vartype, arraynum, 2);
|
||||||
}
|
}
|
||||||
void declFloat(vluint32_t code, const char* name, fstVarDir vardir, fstVarType vartype,
|
void declFloat(vluint32_t code, const char* name,
|
||||||
|
int dtypenum, fstVarDir vardir, fstVarType vartype,
|
||||||
int arraynum) {
|
int arraynum) {
|
||||||
declSymbol(code, name, vardir, vartype, arraynum, 1);
|
declSymbol(code, name, dtypenum, vardir, vartype, arraynum, 1);
|
||||||
}
|
}
|
||||||
void declQuad(vluint32_t code, const char* name, fstVarDir vardir, fstVarType vartype,
|
void declQuad(vluint32_t code, const char* name,
|
||||||
|
int dtypenum, fstVarDir vardir, fstVarType vartype,
|
||||||
int arraynum, int msb, int lsb) {
|
int arraynum, int msb, int lsb) {
|
||||||
declSymbol(code, name, vardir, vartype, arraynum, msb - lsb + 1);
|
declSymbol(code, name, dtypenum, vardir, vartype, arraynum, msb - lsb + 1);
|
||||||
}
|
}
|
||||||
void declArray(vluint32_t code, const char* name, fstVarDir vardir, fstVarType vartype,
|
void declArray(vluint32_t code, const char* name,
|
||||||
|
int dtypenum, fstVarDir vardir, fstVarType vartype,
|
||||||
int arraynum, int msb, int lsb) {
|
int arraynum, int msb, int lsb) {
|
||||||
declSymbol(code, name, vardir, vartype, arraynum, msb - lsb + 1);
|
declSymbol(code, name, dtypenum, vardir, vartype, arraynum, msb - lsb + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inside dumping routines, dump one signal if it has changed
|
/// Inside dumping routines, dump one signal if it has changed
|
||||||
|
|
|
||||||
|
|
@ -2715,8 +2715,15 @@ void EmitCImp::main(AstNodeModule* modp, bool slow, bool fast) {
|
||||||
// Tracing routines
|
// Tracing routines
|
||||||
|
|
||||||
class EmitCTrace : EmitCStmts {
|
class EmitCTrace : EmitCStmts {
|
||||||
|
// NODE STATE/TYPES
|
||||||
|
// Cleared on netlist
|
||||||
|
// AstNode::user1() -> int. Enum number
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
|
// MEMBERS
|
||||||
AstCFunc* m_funcp; // Function we're in now
|
AstCFunc* m_funcp; // Function we're in now
|
||||||
bool m_slow; // Making slow file
|
bool m_slow; // Making slow file
|
||||||
|
int m_enumNum; // Enumeration number (whole netlist)
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void newOutCFile(int filenum) {
|
void newOutCFile(int filenum) {
|
||||||
|
|
@ -2819,7 +2826,7 @@ class EmitCTrace : EmitCStmts {
|
||||||
return varp->isSc() && varp->isScUint();
|
return varp->isSc() && varp->isScUint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitTraceInitOne(AstTraceDecl* nodep) {
|
void emitTraceInitOne(AstTraceDecl* nodep, int enumNum) {
|
||||||
if (nodep->dtypep()->basicp()->isDouble()) {
|
if (nodep->dtypep()->basicp()->isDouble()) {
|
||||||
puts("vcdp->declDouble");
|
puts("vcdp->declDouble");
|
||||||
} else if (nodep->isWide()) {
|
} else if (nodep->isWide()) {
|
||||||
|
|
@ -2838,6 +2845,7 @@ class EmitCTrace : EmitCStmts {
|
||||||
putsQuoted(nodep->showname());
|
putsQuoted(nodep->showname());
|
||||||
// Direction
|
// Direction
|
||||||
if (v3Global.opt.traceFormat() == TraceFormat::FST) {
|
if (v3Global.opt.traceFormat() == TraceFormat::FST) {
|
||||||
|
puts(","+cvtToStr(enumNum));
|
||||||
// fstVarDir
|
// fstVarDir
|
||||||
if (nodep->declInout()) puts(",FST_VD_INOUT");
|
if (nodep->declInout()) puts(",FST_VD_INOUT");
|
||||||
else if (nodep->declInput()) puts(",FST_VD_INPUT");
|
else if (nodep->declInput()) puts(",FST_VD_INPUT");
|
||||||
|
|
@ -2900,6 +2908,49 @@ class EmitCTrace : EmitCStmts {
|
||||||
puts(");");
|
puts(");");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int emitTraceDeclDType(AstNodeDType* nodep) {
|
||||||
|
// Return enum number or -1 for none
|
||||||
|
if (v3Global.opt.traceFormat() == TraceFormat::FST) {
|
||||||
|
// Skip over refs-to-refs, but stop before final ref so can get data type name
|
||||||
|
// Alternatively back in V3Width we could have push enum names from upper typedefs
|
||||||
|
if (AstEnumDType* enump = VN_CAST(nodep->skipRefToEnump(), EnumDType)) {
|
||||||
|
int enumNum = enump->user1();
|
||||||
|
if (!enumNum) {
|
||||||
|
enumNum = ++m_enumNum;
|
||||||
|
enump->user1(enumNum);
|
||||||
|
int nvals = 0;
|
||||||
|
puts("{\n");
|
||||||
|
puts("const char* __VenumItemNames[]\n");
|
||||||
|
puts("= {");
|
||||||
|
for (AstEnumItem* itemp = enump->itemsp(); itemp;
|
||||||
|
itemp=VN_CAST(itemp->nextp(), EnumItem)) {
|
||||||
|
if (++nvals > 1) puts(", ");
|
||||||
|
putbs("\""+itemp->prettyName()+"\"");
|
||||||
|
}
|
||||||
|
puts("};\n");
|
||||||
|
nvals = 0;
|
||||||
|
puts("const char* __VenumItemValues[]\n");
|
||||||
|
puts("= {");
|
||||||
|
for (AstEnumItem* itemp = enump->itemsp(); itemp;
|
||||||
|
itemp=VN_CAST(itemp->nextp(), EnumItem)) {
|
||||||
|
AstConst* constp = VN_CAST(itemp->valuep(), Const);
|
||||||
|
if (++nvals > 1) puts(", ");
|
||||||
|
putbs("\""+constp->num().displayed(nodep->fileline(), "%0b")+"\"");
|
||||||
|
}
|
||||||
|
puts("};\n");
|
||||||
|
puts("vcdp->declDTypeEnum("+cvtToStr(enumNum)
|
||||||
|
+", \""+enump->prettyName()+"\", "
|
||||||
|
+cvtToStr(nvals)
|
||||||
|
+", "+cvtToStr(enump->widthMin())
|
||||||
|
+", __VenumItemNames, __VenumItemValues);\n");
|
||||||
|
puts("}\n");
|
||||||
|
}
|
||||||
|
return enumNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void emitTraceChangeOne(AstTraceInc* nodep, int arrayindex) {
|
void emitTraceChangeOne(AstTraceInc* nodep, int arrayindex) {
|
||||||
iterateAndNextNull(nodep->precondsp());
|
iterateAndNextNull(nodep->precondsp());
|
||||||
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|
||||||
|
|
@ -3013,12 +3064,13 @@ class EmitCTrace : EmitCStmts {
|
||||||
m_funcp = NULL;
|
m_funcp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstTraceDecl* nodep) {
|
virtual void visit(AstTraceDecl* nodep) {
|
||||||
|
int enumNum = emitTraceDeclDType(nodep->dtypep());
|
||||||
if (nodep->arrayRange().ranged()) {
|
if (nodep->arrayRange().ranged()) {
|
||||||
puts("{int i; for (i=0; i<"+cvtToStr(nodep->arrayRange().elements())+"; i++) {\n");
|
puts("{int i; for (i=0; i<"+cvtToStr(nodep->arrayRange().elements())+"; i++) {\n");
|
||||||
emitTraceInitOne(nodep);
|
emitTraceInitOne(nodep, enumNum);
|
||||||
puts("}}\n");
|
puts("}}\n");
|
||||||
} else {
|
} else {
|
||||||
emitTraceInitOne(nodep);
|
emitTraceInitOne(nodep, enumNum);
|
||||||
puts("\n");
|
puts("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3041,6 +3093,7 @@ public:
|
||||||
explicit EmitCTrace(bool slow) {
|
explicit EmitCTrace(bool slow) {
|
||||||
m_funcp = NULL;
|
m_funcp = NULL;
|
||||||
m_slow = slow;
|
m_slow = slow;
|
||||||
|
m_enumNum = 0;
|
||||||
}
|
}
|
||||||
virtual ~EmitCTrace() {}
|
virtual ~EmitCTrace() {}
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
$date
|
$date
|
||||||
Sun Oct 7 21:45:40 2018
|
Mon Oct 8 07:13:10 2018
|
||||||
|
|
||||||
$end
|
$end
|
||||||
$version
|
$version
|
||||||
|
|
@ -33,7 +33,10 @@ $var real 64 3 v_real $end
|
||||||
$var real 64 4 v_arr_real(0) $end
|
$var real 64 4 v_arr_real(0) $end
|
||||||
$var real 64 5 v_arr_real(1) $end
|
$var real 64 5 v_arr_real(1) $end
|
||||||
$var logic 64 6 v_str32x2 $end
|
$var logic 64 6 v_str32x2 $end
|
||||||
|
$attrbegin misc 07 t.enumed_t 4 ZERO ONE TWO THREE 00000000000000000000000000000000 00000000000000000000000000000001 00000000000000000000000000000010 00000000000000000000000000000011 1 $end
|
||||||
|
$attrbegin misc 07 "" 1 $end
|
||||||
$var logic 32 7 v_enumed $end
|
$var logic 32 7 v_enumed $end
|
||||||
|
$attrbegin misc 07 "" 1 $end
|
||||||
$var logic 32 8 v_enumed2 $end
|
$var logic 32 8 v_enumed2 $end
|
||||||
$scope module unnamedblk1 $end
|
$scope module unnamedblk1 $end
|
||||||
$var integer 32 9 b $end
|
$var integer 32 9 b $end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
$date
|
$date
|
||||||
Sun Oct 7 21:45:42 2018
|
Mon Oct 8 07:13:11 2018
|
||||||
|
|
||||||
$end
|
$end
|
||||||
$version
|
$version
|
||||||
|
|
@ -33,7 +33,10 @@ $var real 64 3 v_real $end
|
||||||
$var real 64 4 v_arr_real(0) $end
|
$var real 64 4 v_arr_real(0) $end
|
||||||
$var real 64 5 v_arr_real(1) $end
|
$var real 64 5 v_arr_real(1) $end
|
||||||
$var logic 64 6 v_str32x2 $end
|
$var logic 64 6 v_str32x2 $end
|
||||||
|
$attrbegin misc 07 t.enumed_t 4 ZERO ONE TWO THREE 00000000000000000000000000000000 00000000000000000000000000000001 00000000000000000000000000000010 00000000000000000000000000000011 1 $end
|
||||||
|
$attrbegin misc 07 "" 1 $end
|
||||||
$var logic 32 7 v_enumed $end
|
$var logic 32 7 v_enumed $end
|
||||||
|
$attrbegin misc 07 "" 1 $end
|
||||||
$var logic 32 8 v_enumed2 $end
|
$var logic 32 8 v_enumed2 $end
|
||||||
$scope module unnamedblk1 $end
|
$scope module unnamedblk1 $end
|
||||||
$var integer 32 9 b $end
|
$var integer 32 9 b $end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
$date
|
$date
|
||||||
Sun Oct 7 21:45:44 2018
|
Mon Oct 8 07:13:12 2018
|
||||||
|
|
||||||
$end
|
$end
|
||||||
$version
|
$version
|
||||||
|
|
@ -72,8 +72,11 @@ $var logic 32 A data $end
|
||||||
$upscope $end
|
$upscope $end
|
||||||
$scope module v_str32x2(1) $end
|
$scope module v_str32x2(1) $end
|
||||||
$var logic 32 B data $end
|
$var logic 32 B data $end
|
||||||
|
$attrbegin misc 07 t.enumed_t 4 ZERO ONE TWO THREE 00000000000000000000000000000000 00000000000000000000000000000001 00000000000000000000000000000010 00000000000000000000000000000011 1 $end
|
||||||
$upscope $end
|
$upscope $end
|
||||||
|
$attrbegin misc 07 "" 1 $end
|
||||||
$var logic 32 C v_enumed $end
|
$var logic 32 C v_enumed $end
|
||||||
|
$attrbegin misc 07 "" 1 $end
|
||||||
$var logic 32 D v_enumed2 $end
|
$var logic 32 D v_enumed2 $end
|
||||||
$scope module unnamedblk1 $end
|
$scope module unnamedblk1 $end
|
||||||
$var integer 32 E b $end
|
$var integer 32 E b $end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue