Internals: clang-format cleanups. No functional change.

This commit is contained in:
Wilson Snyder 2020-04-04 13:45:24 -04:00
parent a13eab55f5
commit e07e9390f6
10 changed files with 398 additions and 350 deletions

View File

@ -10,22 +10,14 @@ be made to a file. The following files are not yet clang-format clean:
clang-format -i include/verilated.h clang-format -i include/verilated.h
clang-format -i include/verilated_dpi.h clang-format -i include/verilated_dpi.h
clang-format -i include/verilated_fst_c.h
clang-format -i include/verilated_heavy.h clang-format -i include/verilated_heavy.h
clang-format -i include/verilated_imp.h clang-format -i include/verilated_imp.h
clang-format -i include/verilated_save.h
clang-format -i include/verilated_sym_props.h
clang-format -i include/verilated_unordered_set_map.h clang-format -i include/verilated_unordered_set_map.h
clang-format -i include/verilated_vcd_c.h
clang-format -i include/verilatedos.h clang-format -i include/verilatedos.h
clang-format -i include/verilated.cpp clang-format -i include/verilated.cpp
clang-format -i include/verilated_cov.cpp clang-format -i include/verilated_cov.cpp
clang-format -i include/verilated_dpi.cpp clang-format -i include/verilated_dpi.cpp
clang-format -i include/verilated_fst_c.cpp
clang-format -i include/verilated_save.cpp
clang-format -i include/verilated_threads.cpp
clang-format -i include/verilated_vcd_c.cpp
clang-format -i include/verilated_vpi.cpp clang-format -i include/verilated_vpi.cpp
clang-format -i src/V3Ast.h clang-format -i src/V3Ast.h

View File

@ -91,7 +91,7 @@ void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
m_curScope.clear(); m_curScope.clear();
m_nextCode = 1; m_nextCode = 1;
for (vluint32_t ent = 0; ent< m_callbacks.size(); ++ent) { for (vluint32_t ent = 0; ent < m_callbacks.size(); ++ent) {
VerilatedFstCallInfo* cip = m_callbacks[ent]; VerilatedFstCallInfo* cip = m_callbacks[ent];
cip->m_code = m_nextCode; cip->m_code = m_nextCode;
// Initialize; callbacks will call decl* which update m_nextCode // Initialize; callbacks will call decl* which update m_nextCode
@ -106,18 +106,16 @@ void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
} }
} }
void VerilatedFst::module(const std::string& name) { void VerilatedFst::module(const std::string& name) { m_module = name; }
m_module = name;
}
//============================================================================= //=============================================================================
// Decl // Decl
void VerilatedFst::declDTypeEnum(int dtypenum, const char* name, vluint32_t elements, void VerilatedFst::declDTypeEnum(int dtypenum, const char* name, vluint32_t elements,
unsigned int minValbits, unsigned int minValbits, const char** itemNamesp,
const char** itemNamesp, const char** itemValuesp) { const char** itemValuesp) {
fstEnumHandle enumNum = fstWriterCreateEnumTable(m_fst, name, elements, fstEnumHandle enumNum
minValbits, itemNamesp, itemValuesp); = fstWriterCreateEnumTable(m_fst, name, elements, minValbits, itemNamesp, itemValuesp);
m_local2fstdtype[dtypenum] = enumNum; m_local2fstdtype[dtypenum] = enumNum;
} }
@ -127,7 +125,7 @@ void VerilatedFst::declSymbol(vluint32_t code, const char* name, int dtypenum, f
// Make sure deduplicate tracking increments for future declarations // Make sure deduplicate tracking increments for future declarations
int codesNeeded = 1 + int(bits / 32); int codesNeeded = 1 + int(bits / 32);
//Not supported: if (tri) codesNeeded *= 2; // Space in change array for __en signals // Not supported: if (tri) codesNeeded *= 2; // Space in change array for __en signals
m_nextCode = std::max(m_nextCode, code + codesNeeded); m_nextCode = std::max(m_nextCode, code + codesNeeded);
std::pair<Code2SymbolType::iterator, bool> p std::pair<Code2SymbolType::iterator, bool> p
@ -143,8 +141,7 @@ void VerilatedFst::declSymbol(vluint32_t code, const char* name, int dtypenum, f
std::list<std::string>::iterator cur_it = m_curScope.begin(); std::list<std::string>::iterator cur_it = m_curScope.begin();
std::list<std::string>::iterator new_it = tokens.begin(); std::list<std::string>::iterator new_it = tokens.begin();
while (cur_it != m_curScope.end() && new_it != tokens.end()) { while (cur_it != m_curScope.end() && new_it != tokens.end()) {
if (*cur_it != *new_it) if (*cur_it != *new_it) break;
break;
++cur_it; ++cur_it;
++new_it; ++new_it;
} }
@ -201,14 +198,14 @@ void VerilatedFst::dump(vluint64_t timeui) {
if (!isOpen()) return; if (!isOpen()) return;
if (VL_UNLIKELY(m_fullDump)) { if (VL_UNLIKELY(m_fullDump)) {
m_fullDump = false; // No more need for next dump to be full m_fullDump = false; // No more need for next dump to be full
for (vluint32_t ent = 0; ent< m_callbacks.size(); ++ent) { for (vluint32_t ent = 0; ent < m_callbacks.size(); ++ent) {
VerilatedFstCallInfo* cip = m_callbacks[ent]; VerilatedFstCallInfo* cip = m_callbacks[ent];
(cip->m_fullcb)(this, cip->m_userthis, cip->m_code); (cip->m_fullcb)(this, cip->m_userthis, cip->m_code);
} }
return; return;
} }
fstWriterEmitTimeChange(m_fst, timeui); fstWriterEmitTimeChange(m_fst, timeui);
for (vluint32_t ent = 0; ent< m_callbacks.size(); ++ent) { for (vluint32_t ent = 0; ent < m_callbacks.size(); ++ent) {
VerilatedFstCallInfo* cip = m_callbacks[ent]; VerilatedFstCallInfo* cip = m_callbacks[ent];
(cip->m_changecb)(this, cip->m_userthis, cip->m_code); (cip->m_changecb)(this, cip->m_userthis, cip->m_code);
} }

View File

@ -43,6 +43,7 @@ class VerilatedFst {
typedef std::map<vluint32_t, fstHandle> Code2SymbolType; typedef std::map<vluint32_t, fstHandle> Code2SymbolType;
typedef std::map<int, fstEnumHandle> Local2FstDtype; typedef std::map<int, fstEnumHandle> Local2FstDtype;
typedef std::vector<VerilatedFstCallInfo*> CallbackVec; typedef std::vector<VerilatedFstCallInfo*> CallbackVec;
private: private:
void* m_fst; void* m_fst;
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
@ -61,9 +62,12 @@ private:
bool array, int arraynum, vluint32_t len, vluint32_t bits); bool array, int arraynum, vluint32_t len, vluint32_t bits);
// helpers // helpers
std::vector<char> m_valueStrBuffer; std::vector<char> m_valueStrBuffer;
public: public:
explicit VerilatedFst(void* fst=NULL); explicit VerilatedFst(void* fst = NULL);
~VerilatedFst() { if (m_fst == NULL) { fstWriterClose(m_fst); } } ~VerilatedFst() {
if (m_fst == NULL) { fstWriterClose(m_fst); }
}
void changeThread() { m_assertOne.changeThread(); } void changeThread() { m_assertOne.changeThread(); }
bool isOpen() const { return m_fst != NULL; } bool isOpen() const { return m_fst != NULL; }
void open(const char* filename) VL_MT_UNSAFE; void open(const char* filename) VL_MT_UNSAFE;
@ -76,7 +80,7 @@ public:
void set_time_unit(const char* unitp) { fstWriterSetTimescaleFromString(m_fst, unitp); } void set_time_unit(const char* unitp) { fstWriterSetTimescaleFromString(m_fst, unitp); }
void set_time_unit(const std::string& unit) { set_time_unit(unit.c_str()); } void set_time_unit(const std::string& unit) { set_time_unit(unit.c_str()); }
void set_time_resolution(const char* unitp) { if (unitp) {} } void set_time_resolution(const char*) {}
void set_time_resolution(const std::string& unit) { set_time_resolution(unit.c_str()); } void set_time_resolution(const std::string& unit) { set_time_resolution(unit.c_str()); }
// double timescaleToDouble(const char* unitp); // double timescaleToDouble(const char* unitp);
@ -156,18 +160,18 @@ public:
fstWriterEmitValueChangeVec32(m_fst, m_code2symbol[code], bits, newval); fstWriterEmitValueChangeVec32(m_fst, m_code2symbol[code], bits, newval);
} }
void fullBit(vluint32_t code, const vluint32_t newval) { void fullBit(vluint32_t code, const vluint32_t newval) { chgBit(code, newval); }
chgBit(code, newval); }
void fullBus(vluint32_t code, const vluint32_t newval, int bits) { void fullBus(vluint32_t code, const vluint32_t newval, int bits) {
chgBus(code, newval, bits); } chgBus(code, newval, bits);
void fullDouble(vluint32_t code, const double newval) { }
chgDouble(code, newval); } void fullDouble(vluint32_t code, const double newval) { chgDouble(code, newval); }
void fullFloat(vluint32_t code, const float newval) { void fullFloat(vluint32_t code, const float newval) { chgFloat(code, newval); }
chgFloat(code, newval); }
void fullQuad(vluint32_t code, const vluint64_t newval, int bits) { void fullQuad(vluint32_t code, const vluint64_t newval, int bits) {
chgQuad(code, newval, bits); } chgQuad(code, newval, bits);
}
void fullArray(vluint32_t code, const vluint32_t* newval, int bits) { void fullArray(vluint32_t code, const vluint32_t* newval, int bits) {
chgArray(code, newval, bits); } chgArray(code, newval, bits);
}
void declTriBit(vluint32_t code, const char* name, int arraynum); 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 declTriBus(vluint32_t code, const char* name, int arraynum, int msb, int lsb);
@ -198,12 +202,14 @@ class VerilatedFstC {
// CONSTRUCTORS // CONSTRUCTORS
VL_UNCOPYABLE(VerilatedFstC); VL_UNCOPYABLE(VerilatedFstC);
public: public:
explicit VerilatedFstC(void* filep=NULL) : m_sptrace(filep) {} explicit VerilatedFstC(void* filep = NULL)
: m_sptrace(filep) {}
~VerilatedFstC() { close(); } ~VerilatedFstC() { close(); }
/// Routines can only be called from one thread; allow next call from different thread /// Routines can only be called from one thread; allow next call from different thread
void changeThread() { spTrace()->changeThread(); } void changeThread() { spTrace()->changeThread(); }
public:
// ACCESSORS // ACCESSORS
/// Is file open? /// Is file open?
bool isOpen() const { return m_sptrace.isOpen(); } bool isOpen() const { return m_sptrace.isOpen(); }

View File

@ -40,7 +40,8 @@
#endif #endif
// CONSTANTS // CONSTANTS
static const char* const VLTSAVE_HEADER_STR = "verilatorsave01\n"; ///< Value of first bytes of each file static const char* const VLTSAVE_HEADER_STR
= "verilatorsave01\n"; ///< Value of first bytes of each file
static const char* const VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file static const char* const VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file
//============================================================================= //=============================================================================
@ -48,22 +49,23 @@ static const char* const VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last b
//============================================================================= //=============================================================================
// Searalization // Searalization
bool VerilatedDeserialize::readDiffers(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE { bool VerilatedDeserialize::readDiffers(const void* __restrict datap,
size_t size) VL_MT_UNSAFE_ONE {
bufferCheck(); bufferCheck();
const vluint8_t* __restrict dp = static_cast<const vluint8_t* __restrict>(datap); const vluint8_t* __restrict dp = static_cast<const vluint8_t* __restrict>(datap);
vluint8_t miss = 0; vluint8_t miss = 0;
while (size--) { while (size--) {
miss |= (*dp++ ^ *m_cp++); miss |= (*dp++ ^ *m_cp++);
} }
return (miss!=0); return (miss != 0);
} }
VerilatedDeserialize& VerilatedDeserialize::readAssert(const void* __restrict datap, VerilatedDeserialize& VerilatedDeserialize::readAssert(const void* __restrict datap,
size_t size) VL_MT_UNSAFE_ONE { size_t size) VL_MT_UNSAFE_ONE {
if (VL_UNLIKELY(readDiffers(datap, size))) { if (VL_UNLIKELY(readDiffers(datap, size))) {
std::string fn = filename(); std::string fn = filename();
std::string msg = "Can't deserialize save-restore file as was made from different model:" std::string msg
+filename(); = "Can't deserialize save-restore file as was made from different model:" + filename();
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str()); VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
close(); close();
} }
@ -84,8 +86,8 @@ void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) { if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
std::string fn = filename(); std::string fn = filename();
std::string msg = std::string("Can't deserialize; file has wrong header signature: ") std::string msg
+filename(); = std::string("Can't deserialize; file has wrong header signature: ") + filename();
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str()); VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
close(); close();
} }
@ -103,7 +105,7 @@ void VerilatedDeserialize::trailer() VL_MT_UNSAFE_ONE {
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) { if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
std::string fn = filename(); std::string fn = filename();
std::string msg = std::string("Can't deserialize; file has wrong end-of-file signature: ") std::string msg = std::string("Can't deserialize; file has wrong end-of-file signature: ")
+filename(); + filename();
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str()); VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
close(); close();
} }
@ -119,13 +121,13 @@ void VerilatedSave::open(const char* filenamep) VL_MT_UNSAFE_ONE {
if (isOpen()) return; if (isOpen()) return;
VL_DEBUG_IF(VL_DBG_MSGF("- save: opening save file %s\n", filenamep);); VL_DEBUG_IF(VL_DBG_MSGF("- save: opening save file %s\n", filenamep););
if (filenamep[0]=='|') { if (filenamep[0] == '|') {
assert(0); // Not supported yet. assert(0); // Not supported yet.
} else { } else {
// cppcheck-suppress duplicateExpression // cppcheck-suppress duplicateExpression
m_fd = ::open(filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK|O_CLOEXEC m_fd = ::open(filenamep,
, 0666); O_CREAT | O_WRONLY | O_TRUNC | O_LARGEFILE | O_NONBLOCK | O_CLOEXEC, 0666);
if (m_fd<0) { if (m_fd < 0) {
// User code can check isOpen() // User code can check isOpen()
m_isOpen = false; m_isOpen = false;
return; return;
@ -142,13 +144,12 @@ void VerilatedRestore::open(const char* filenamep) VL_MT_UNSAFE_ONE {
if (isOpen()) return; if (isOpen()) return;
VL_DEBUG_IF(VL_DBG_MSGF("- restore: opening restore file %s\n", filenamep);); VL_DEBUG_IF(VL_DBG_MSGF("- restore: opening restore file %s\n", filenamep););
if (filenamep[0]=='|') { if (filenamep[0] == '|') {
assert(0); // Not supported yet. assert(0); // Not supported yet.
} else { } else {
// cppcheck-suppress duplicateExpression // cppcheck-suppress duplicateExpression
m_fd = ::open(filenamep, O_CREAT|O_RDONLY|O_LARGEFILE|O_CLOEXEC m_fd = ::open(filenamep, O_CREAT | O_RDONLY | O_LARGEFILE | O_CLOEXEC, 0666);
, 0666); if (m_fd < 0) {
if (m_fd<0) {
// User code can check isOpen() // User code can check isOpen()
m_isOpen = false; m_isOpen = false;
return; return;
@ -186,15 +187,15 @@ void VerilatedSave::flush() VL_MT_UNSAFE_ONE {
vluint8_t* wp = m_bufp; vluint8_t* wp = m_bufp;
while (true) { while (true) {
ssize_t remaining = (m_cp - wp); ssize_t remaining = (m_cp - wp);
if (remaining==0) break; if (remaining == 0) break;
errno = 0; errno = 0;
ssize_t got = ::write(m_fd, wp, remaining); ssize_t got = ::write(m_fd, wp, remaining);
if (got>0) { if (got > 0) {
wp += got; wp += got;
} else if (got < 0) { } else if (got < 0) {
if (errno != EAGAIN && errno != EINTR) { if (errno != EAGAIN && errno != EINTR) {
// write failed, presume error (perhaps out of disk space) // write failed, presume error (perhaps out of disk space)
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno); std::string msg = std::string(__FUNCTION__) + ": " + strerror(errno);
VL_FATAL_MT("", 0, "", msg.c_str()); VL_FATAL_MT("", 0, "", msg.c_str());
close(); close();
break; break;
@ -209,21 +210,21 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
if (VL_UNLIKELY(!isOpen())) return; if (VL_UNLIKELY(!isOpen())) return;
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed) // Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
vluint8_t* rp = m_bufp; vluint8_t* rp = m_bufp;
for (vluint8_t* sp=m_cp; sp < m_endp;) *rp++ = *sp++; // Overlaps for (vluint8_t* sp = m_cp; sp < m_endp; *rp++ = *sp++) {} // Overlaps
m_endp = m_bufp + (m_endp - m_cp); m_endp = m_bufp + (m_endp - m_cp);
m_cp = m_bufp; // Reset buffer m_cp = m_bufp; // Reset buffer
// Read into buffer starting at m_endp // Read into buffer starting at m_endp
while (true) { while (true) {
ssize_t remaining = (m_bufp+bufferSize() - m_endp); ssize_t remaining = (m_bufp + bufferSize() - m_endp);
if (remaining==0) break; if (remaining == 0) break;
errno = 0; errno = 0;
ssize_t got = ::read(m_fd, m_endp, remaining); ssize_t got = ::read(m_fd, m_endp, remaining);
if (got>0) { if (got > 0) {
m_endp += got; m_endp += got;
} else if (got < 0) { } else if (got < 0) {
if (errno != EAGAIN && errno != EINTR) { if (errno != EAGAIN && errno != EINTR) {
// write failed, presume error (perhaps out of disk space) // write failed, presume error (perhaps out of disk space)
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno); std::string msg = std::string(__FUNCTION__) + ": " + strerror(errno);
VL_FATAL_MT("", 0, "", msg.c_str()); VL_FATAL_MT("", 0, "", msg.c_str());
close(); close();
break; break;
@ -231,7 +232,9 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
} else { // got==0, EOF } else { // got==0, EOF
// Fill buffer from here to end with NULLs so reader's don't // Fill buffer from here to end with NULLs so reader's don't
// need to check eof each character. // need to check eof each character.
while (m_endp < m_bufp+bufferSize()) *m_endp++ = '\0'; while (m_endp < m_bufp + bufferSize()) {
*m_endp++ = '\0';
}
break; break;
} }
} }

View File

@ -46,6 +46,7 @@ protected:
// CONSTRUCTORS // CONSTRUCTORS
VL_UNCOPYABLE(VerilatedSerialize); VL_UNCOPYABLE(VerilatedSerialize);
public: public:
VerilatedSerialize() { VerilatedSerialize() {
m_isOpen = false; m_isOpen = false;
@ -65,20 +66,20 @@ public:
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap; const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
while (size) { while (size) {
bufferCheck(); bufferCheck();
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize(); size_t blk = size;
if (blk > bufferInsertSize()) blk = bufferInsertSize();
const vluint8_t* __restrict maxp = dp + blk; const vluint8_t* __restrict maxp = dp + blk;
while (dp < maxp) *m_cp++ = *dp++; for (; dp < maxp; *m_cp++ = *dp++) {}
size -= blk; size -= blk;
} }
return *this; // For function chaining return *this; // For function chaining
} }
private: private:
VerilatedSerialize& bufferCheck() VL_MT_UNSAFE_ONE { VerilatedSerialize& bufferCheck() VL_MT_UNSAFE_ONE {
// Flush the write buffer if there's not enough space left for new information // Flush the write buffer if there's not enough space left for new information
// We only call this once per vector, so we need enough slop for a very wide "b###" line // We only call this once per vector, so we need enough slop for a very wide "b###" line
if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) { if (VL_UNLIKELY(m_cp > (m_bufp + (bufferSize() - bufferInsertSize())))) flush();
flush();
}
return *this; // For function chaining return *this; // For function chaining
} }
}; };
@ -125,12 +126,13 @@ public:
virtual void close() VL_MT_UNSAFE_ONE { flush(); } virtual void close() VL_MT_UNSAFE_ONE { flush(); }
virtual void flush() VL_MT_UNSAFE_ONE {} virtual void flush() VL_MT_UNSAFE_ONE {}
inline VerilatedDeserialize& read(void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE { inline VerilatedDeserialize& read(void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
vluint8_t* __restrict dp = (vluint8_t* __restrict)datap; vluint8_t* __restrict dp = static_cast<vluint8_t* __restrict>(datap);
while (size) { while (size) {
bufferCheck(); bufferCheck();
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize(); size_t blk = size;
if (blk > bufferInsertSize()) blk = bufferInsertSize();
const vluint8_t* __restrict maxp = dp + blk; const vluint8_t* __restrict maxp = dp + blk;
while (dp < maxp) *dp++ = *m_cp++; for (; dp < maxp; *dp++ = *m_cp++);
size -= blk; size -= blk;
} }
return *this; // For function chaining return *this; // For function chaining
@ -138,15 +140,15 @@ public:
// Read a datum and compare with expected value // Read a datum and compare with expected value
VerilatedDeserialize& readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE; VerilatedDeserialize& readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
VerilatedDeserialize& readAssert(vluint64_t data) VL_MT_UNSAFE_ONE { VerilatedDeserialize& readAssert(vluint64_t data) VL_MT_UNSAFE_ONE {
return readAssert(&data, sizeof(data)); } return readAssert(&data, sizeof(data));
}
private: private:
bool readDiffers(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE; bool readDiffers(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
VerilatedDeserialize& bufferCheck() VL_MT_UNSAFE_ONE { VerilatedDeserialize& bufferCheck() VL_MT_UNSAFE_ONE {
// Flush the write buffer if there's not enough space left for new information // Flush the write buffer if there's not enough space left for new information
// We only call this once per vector, so we need enough slop for a very wide "b###" line // We only call this once per vector, so we need enough slop for a very wide "b###" line
if (VL_UNLIKELY((m_cp+bufferInsertSize()) > m_endp)) { if (VL_UNLIKELY((m_cp + bufferInsertSize()) > m_endp)) fill();
fill();
}
return *this; // For function chaining return *this; // For function chaining
} }
}; };
@ -187,7 +189,8 @@ public:
virtual ~VerilatedRestore() VL_OVERRIDE { close(); } virtual ~VerilatedRestore() VL_OVERRIDE { close(); }
// METHODS // METHODS
void open(const char* filenamep) VL_MT_UNSAFE_ONE; ///< Open the file; call isOpen() to see if errors /// Open the file; call isOpen() to see if errors
void open(const char* filenamep) VL_MT_UNSAFE_ONE;
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); } void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
virtual void close() VL_OVERRIDE VL_MT_UNSAFE_ONE; virtual void close() VL_OVERRIDE VL_MT_UNSAFE_ONE;
virtual void flush() VL_OVERRIDE VL_MT_UNSAFE_ONE {} virtual void flush() VL_OVERRIDE VL_MT_UNSAFE_ONE {}

View File

@ -35,14 +35,19 @@
// See also V3Ast::VNumRange // See also V3Ast::VNumRange
class VerilatedRange { class VerilatedRange {
int m_left; int m_left;
int m_right; int m_right;
protected: protected:
friend class VerilatedVarProps; friend class VerilatedVarProps;
friend class VerilatedScope; friend class VerilatedScope;
VerilatedRange() : m_left(0), m_right(0) {} VerilatedRange() : m_left(0), m_right(0) {}
VerilatedRange(int left, int right) : m_left(left), m_right(right) {} VerilatedRange(int left, int right) : m_left(left), m_right(right) {}
void init(int left, int right) { m_left=left; m_right=right; } void init(int left, int right) {
m_left = left;
m_right = right;
}
public: public:
~VerilatedRange() {} ~VerilatedRange() {}
int left() const { return m_left; } int left() const { return m_left; }
@ -50,7 +55,8 @@ public:
int low() const { return (m_left < m_right) ? m_left : m_right; } int low() const { return (m_left < m_right) ? m_left : m_right; }
int high() const { return (m_left > m_right) ? m_left : m_right; } int high() const { return (m_left > m_right) ? m_left : m_right; }
int elements() const { int elements() const {
return (VL_LIKELY(m_left>=m_right) ? (m_left-m_right+1) : (m_right-m_left+1)); } return (VL_LIKELY(m_left >= m_right) ? (m_left - m_right + 1) : (m_right - m_left + 1));
}
int increment() const { return (m_left >= m_right) ? 1 : -1; } int increment() const { return (m_left >= m_right) ? 1 : -1; }
}; };
@ -62,71 +68,86 @@ class VerilatedVarProps {
// TYPES // TYPES
enum { MAGIC = 0xddc4f829 }; enum { MAGIC = 0xddc4f829 };
// MEMBERS // MEMBERS
const vluint32_t m_magic; // Magic number const vluint32_t m_magic; // Magic number
const VerilatedVarType m_vltype; // Data type const VerilatedVarType m_vltype; // Data type
const VerilatedVarFlags m_vlflags; // Direction const VerilatedVarFlags m_vlflags; // Direction
const int m_pdims; // Packed dimensions const int m_pdims; // Packed dimensions
const int m_udims; // Unpacked dimensions const int m_udims; // Unpacked dimensions
VerilatedRange m_packed; // Packed array range VerilatedRange m_packed; // Packed array range
VerilatedRange m_unpacked[3]; // Unpacked array range VerilatedRange m_unpacked[3]; // Unpacked array range
// CONSTRUCTORS // CONSTRUCTORS
protected: protected:
friend class VerilatedScope; friend class VerilatedScope;
VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags, VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags,
int pdims, int udims) int pdims, int udims)
: m_magic(MAGIC), m_vltype(vltype), m_vlflags(vlflags), m_pdims(pdims), m_udims(udims) {} : m_magic(MAGIC), m_vltype(vltype), m_vlflags(vlflags), m_pdims(pdims), m_udims(udims) {}
public: public:
class Unpacked {}; class Unpacked {};
// Without packed // Without packed
VerilatedVarProps(VerilatedVarType vltype, int vlflags) VerilatedVarProps(VerilatedVarType vltype, int vlflags)
: m_magic(MAGIC), m_vltype(vltype), : m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(0) { } m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(0) {}
VerilatedVarProps(VerilatedVarType vltype, int vlflags, VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Unpacked, int u0l, int u0r) Unpacked, int u0l, int u0r)
: m_magic(MAGIC), m_vltype(vltype), : m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(1) { m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(1) {
m_unpacked[0].init(u0l, u0r); } m_unpacked[0].init(u0l, u0r);
}
VerilatedVarProps(VerilatedVarType vltype, int vlflags, VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Unpacked, int u0l, int u0r, int u1l, int u1r) Unpacked, int u0l, int u0r, int u1l, int u1r)
: m_magic(MAGIC), m_vltype(vltype), : m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(2) { m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(2) {
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); } m_unpacked[0].init(u0l, u0r);
m_unpacked[1].init(u1l, u1r);
}
VerilatedVarProps(VerilatedVarType vltype, int vlflags, VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r) Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
: m_magic(MAGIC), m_vltype(vltype), : m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(3) { m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(3) {
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); m_unpacked[2].init(u2l, u2r); } m_unpacked[0].init(u0l, u0r);
m_unpacked[1].init(u1l, u1r);
m_unpacked[2].init(u2l, u2r);
}
// With packed // With packed
class Packed {}; class Packed {};
VerilatedVarProps(VerilatedVarType vltype, int vlflags, VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr) Packed, int pl, int pr)
: m_magic(MAGIC), m_vltype(vltype), : m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(0), m_packed(pl,pr) { } m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(0), m_packed(pl,pr) {}
VerilatedVarProps(VerilatedVarType vltype, int vlflags, VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr, Packed, int pl, int pr,
Unpacked, int u0l, int u0r) Unpacked, int u0l, int u0r)
: m_magic(MAGIC), m_vltype(vltype), : m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(1), m_packed(pl,pr) { m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(1), m_packed(pl,pr) {
m_unpacked[0].init(u0l, u0r); } m_unpacked[0].init(u0l, u0r);
}
VerilatedVarProps(VerilatedVarType vltype, int vlflags, VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr, Packed, int pl, int pr,
Unpacked, int u0l, int u0r, int u1l, int u1r) Unpacked, int u0l, int u0r, int u1l, int u1r)
: m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)), : m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)),
m_pdims(1), m_udims(2), m_packed(pl,pr) { m_pdims(1), m_udims(2), m_packed(pl,pr) {
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); } m_unpacked[0].init(u0l, u0r);
m_unpacked[1].init(u1l, u1r);
}
VerilatedVarProps(VerilatedVarType vltype, int vlflags, VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr, Packed, int pl, int pr,
Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r) Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
: m_magic(MAGIC), m_vltype(vltype), : m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(3), m_packed(pl,pr) { m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(3), m_packed(pl,pr) {
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); m_unpacked[2].init(u2l, u2r); } m_unpacked[0].init(u0l, u0r);
m_unpacked[1].init(u1l, u1r);
m_unpacked[2].init(u2l, u2r);
}
public: public:
~VerilatedVarProps() {} ~VerilatedVarProps() {}
// METHODS // METHODS
bool magicOk() const { return m_magic == MAGIC; } bool magicOk() const { return m_magic == MAGIC; }
VerilatedVarType vltype() const { return m_vltype; } VerilatedVarType vltype() const { return m_vltype; }
VerilatedVarFlags vldir() const { VerilatedVarFlags vldir() const {
return static_cast<VerilatedVarFlags>(static_cast<int>(m_vlflags) & VLVF_MASK_DIR); } return static_cast<VerilatedVarFlags>(static_cast<int>(m_vlflags) & VLVF_MASK_DIR);
}
vluint32_t entSize() const; vluint32_t entSize() const;
bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); } bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); }
/// DPI compatible C standard layout /// DPI compatible C standard layout
@ -137,28 +158,28 @@ public:
const VerilatedRange& unpacked() const { return m_unpacked[0]; } const VerilatedRange& unpacked() const { return m_unpacked[0]; }
// DPI accessors // DPI accessors
int left(int dim) const { int left(int dim) const {
return dim==0 ? m_packed.left() return dim == 0 ? m_packed.left()
: VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].left() : 0; : VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].left() : 0;
} }
int right(int dim) const { int right(int dim) const {
return dim==0 ? m_packed.right() return dim == 0 ? m_packed.right()
: VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].right() : 0; : VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].right() : 0;
} }
int low(int dim) const { int low(int dim) const {
return dim==0 ? m_packed.low() return dim == 0 ? m_packed.low()
: VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].low() : 0; : VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].low() : 0;
} }
int high(int dim) const { int high(int dim) const {
return dim==0 ? m_packed.high() return dim == 0 ? m_packed.high()
: VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].high() : 0; : VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].high() : 0;
} }
int increment(int dim) const { int increment(int dim) const {
return dim==0 ? m_packed.increment() return dim == 0 ? m_packed.increment()
: VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].increment() : 0; : VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].increment() : 0;
} }
int elements(int dim) const { int elements(int dim) const {
return dim==0 ? m_packed.elements() return dim == 0 ? m_packed.elements()
: VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].elements() : 0; : VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].elements() : 0;
} }
/// Total size in bytes (note DPI limited to 4GB) /// Total size in bytes (note DPI limited to 4GB)
size_t totalSize() const; size_t totalSize() const;
@ -199,7 +220,8 @@ public:
int elements(int dim) const { return m_propsp->elements(dim); } int elements(int dim) const { return m_propsp->elements(dim); }
size_t totalSize() const { return m_propsp->totalSize(); } size_t totalSize() const { return m_propsp->totalSize(); }
void* datapAdjustIndex(void* datap, int dim, int indx) const { void* datapAdjustIndex(void* datap, int dim, int indx) const {
return m_propsp->datapAdjustIndex(datap, dim, indx); } return m_propsp->datapAdjustIndex(datap, dim, indx);
}
}; };
//=========================================================================== //===========================================================================
@ -213,10 +235,12 @@ class VerilatedVar : public VerilatedVarProps {
protected: protected:
friend class VerilatedScope; friend class VerilatedScope;
// CONSTRUCTORS // CONSTRUCTORS
VerilatedVar(const char* namep, void* datap, VerilatedVar(const char* namep, void* datap, VerilatedVarType vltype,
VerilatedVarType vltype, VerilatedVarFlags vlflags, int dims) VerilatedVarFlags vlflags, int dims)
: VerilatedVarProps(vltype, vlflags, (dims>0?1:0), ((dims>1)?dims-1:0)) : VerilatedVarProps(vltype, vlflags, (dims > 0 ? 1 : 0), ((dims > 1) ? dims - 1 : 0))
, m_datap(datap), m_namep(namep) {} , m_datap(datap)
, m_namep(namep) {}
public: public:
~VerilatedVar() {} ~VerilatedVar() {}
// ACCESSORS // ACCESSORS

View File

@ -27,8 +27,8 @@ VL_THREAD_LOCAL VlThreadPool::ProfileTrace* VlThreadPool::t_profilep = NULL;
// VlMTaskVertex // VlMTaskVertex
VlMTaskVertex::VlMTaskVertex(vluint32_t upstreamDepCount) VlMTaskVertex::VlMTaskVertex(vluint32_t upstreamDepCount)
: m_upstreamDepsDone(0), : m_upstreamDepsDone(0)
m_upstreamDepCount(upstreamDepCount) { , m_upstreamDepCount(upstreamDepCount) {
assert(atomic_is_lock_free(&m_upstreamDepsDone)); assert(atomic_is_lock_free(&m_upstreamDepsDone));
} }
@ -41,7 +41,7 @@ VlWorkerThread::VlWorkerThread(VlThreadPool* poolp, bool profiling)
, m_poolp(poolp) , m_poolp(poolp)
, m_profiling(profiling) , m_profiling(profiling)
, m_exiting(false) , m_exiting(false)
// Must init this last -- after setting up fields that it might read: // Must init this last -- after setting up fields that it might read:
, m_cthread(startWorker, this) {} , m_cthread(startWorker, this) {}
VlWorkerThread::~VlWorkerThread() { VlWorkerThread::~VlWorkerThread() {
@ -52,17 +52,13 @@ VlWorkerThread::~VlWorkerThread() {
} }
void VlWorkerThread::workerLoop() { void VlWorkerThread::workerLoop() {
if (VL_UNLIKELY(m_profiling)) { if (VL_UNLIKELY(m_profiling)) m_poolp->setupProfilingClientThread();
m_poolp->setupProfilingClientThread();
}
ExecRec work; ExecRec work;
work.m_fnp = NULL; work.m_fnp = NULL;
while (true) { while (true) {
if (VL_LIKELY(!work.m_fnp)) { if (VL_LIKELY(!work.m_fnp)) dequeWork(&work);
dequeWork(&work);
}
// Do this here, not above, to avoid a race with the destructor. // Do this here, not above, to avoid a race with the destructor.
if (VL_UNLIKELY(m_exiting.load(std::memory_order_acquire))) if (VL_UNLIKELY(m_exiting.load(std::memory_order_acquire)))
@ -74,14 +70,10 @@ void VlWorkerThread::workerLoop() {
} }
} }
if (VL_UNLIKELY(m_profiling)) { if (VL_UNLIKELY(m_profiling)) m_poolp->tearDownProfilingClientThread();
m_poolp->tearDownProfilingClientThread();
}
} }
void VlWorkerThread::startWorker(VlWorkerThread* workerp) { void VlWorkerThread::startWorker(VlWorkerThread* workerp) { workerp->workerLoop(); }
workerp->workerLoop();
}
//============================================================================= //=============================================================================
// VlThreadPool // VlThreadPool
@ -90,23 +82,22 @@ VlThreadPool::VlThreadPool(int nThreads, bool profiling)
: m_profiling(profiling) { : m_profiling(profiling) {
// --threads N passes nThreads=N-1, as the "main" threads counts as 1 // --threads N passes nThreads=N-1, as the "main" threads counts as 1
unsigned cpus = std::thread::hardware_concurrency(); unsigned cpus = std::thread::hardware_concurrency();
if (cpus < nThreads+1) { if (cpus < nThreads + 1) {
static int warnedOnce = 0; static int warnedOnce = 0;
if (!warnedOnce++) { if (!warnedOnce++) {
VL_PRINTF_MT("%%Warning: System has %u CPUs but model Verilated with" VL_PRINTF_MT("%%Warning: System has %u CPUs but model Verilated with"
" --threads %d; may run slow.\n", cpus, nThreads+1); " --threads %d; may run slow.\n",
cpus, nThreads + 1);
} }
} }
// Create'em // Create'em
for (int i=0; i<nThreads; ++i) { for (int i = 0; i < nThreads; ++i) {
m_workers.push_back(new VlWorkerThread(this, profiling)); m_workers.push_back(new VlWorkerThread(this, profiling));
} }
// Set up a profile buffer for the current thread too -- on the // Set up a profile buffer for the current thread too -- on the
// assumption that it's the same thread that calls eval and may be // assumption that it's the same thread that calls eval and may be
// donated to run mtasks during the eval. // donated to run mtasks during the eval.
if (VL_UNLIKELY(m_profiling)) { if (VL_UNLIKELY(m_profiling)) setupProfilingClientThread();
setupProfilingClientThread();
}
} }
VlThreadPool::~VlThreadPool() { VlThreadPool::~VlThreadPool() {
@ -114,9 +105,7 @@ VlThreadPool::~VlThreadPool() {
// Each ~WorkerThread will wait for its thread to exit. // Each ~WorkerThread will wait for its thread to exit.
delete m_workers[i]; delete m_workers[i];
} }
if (VL_UNLIKELY(m_profiling)) { if (VL_UNLIKELY(m_profiling)) tearDownProfilingClientThread();
tearDownProfilingClientThread();
}
} }
void VlThreadPool::tearDownProfilingClientThread() { void VlThreadPool::tearDownProfilingClientThread() {
@ -159,14 +148,11 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
// TODO Perhaps merge with verilated_coverage output format, so can // TODO Perhaps merge with verilated_coverage output format, so can
// have a common merging and reporting tool, etc. // have a common merging and reporting tool, etc.
fprintf(fp, "VLPROFTHREAD 1.0 # Verilator thread profile dump version 1.0\n"); fprintf(fp, "VLPROFTHREAD 1.0 # Verilator thread profile dump version 1.0\n");
fprintf(fp, "VLPROF arg --threads %" VL_PRI64 "u\n", fprintf(fp, "VLPROF arg --threads %" VL_PRI64 "u\n", vluint64_t(m_workers.size() + 1));
vluint64_t(m_workers.size()+1));
fprintf(fp, "VLPROF arg +verilator+prof+threads+start+%" VL_PRI64 "u\n", fprintf(fp, "VLPROF arg +verilator+prof+threads+start+%" VL_PRI64 "u\n",
Verilated::profThreadsStart()); Verilated::profThreadsStart());
fprintf(fp, "VLPROF arg +verilator+prof+threads+window+%u\n", fprintf(fp, "VLPROF arg +verilator+prof+threads+window+%u\n", Verilated::profThreadsWindow());
Verilated::profThreadsWindow()); fprintf(fp, "VLPROF stat yields %" VL_PRI64 "u\n", VlMTaskVertex::yields());
fprintf(fp, "VLPROF stat yields %" VL_PRI64 "u\n",
VlMTaskVertex::yields());
vluint32_t thread_id = 0; vluint32_t thread_id = 0;
for (ProfileSet::const_iterator pit = m_allProfiles.begin(); for (ProfileSet::const_iterator pit = m_allProfiles.begin();
@ -174,31 +160,26 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
++thread_id; ++thread_id;
bool printing = false; // False while in warmup phase bool printing = false; // False while in warmup phase
for (ProfileTrace::const_iterator eit = (*pit)->begin(); for (ProfileTrace::const_iterator eit = (*pit)->begin(); eit != (*pit)->end(); ++eit) {
eit != (*pit)->end(); ++eit) {
switch (eit->m_type) { switch (eit->m_type) {
case VlProfileRec::TYPE_BARRIER: case VlProfileRec::TYPE_BARRIER:
printing = true; printing = true;
break; break;
case VlProfileRec::TYPE_MTASK_RUN: case VlProfileRec::TYPE_MTASK_RUN:
if (!printing) break; if (!printing) break;
fprintf(fp, "VLPROF mtask %d" fprintf(fp,
" start %" VL_PRI64"u end %" VL_PRI64"u elapsed %" VL_PRI64 "u" "VLPROF mtask %d"
" start %" VL_PRI64 "u end %" VL_PRI64 "u elapsed %" VL_PRI64 "u"
" predict_time %u cpu %u on thread %u\n", " predict_time %u cpu %u on thread %u\n",
eit->m_mtaskId, eit->m_mtaskId, eit->m_startTime, eit->m_endTime,
eit->m_startTime, (eit->m_endTime - eit->m_startTime), eit->m_predictTime, eit->m_cpu,
eit->m_endTime,
(eit->m_endTime - eit->m_startTime),
eit->m_predictTime,
eit->m_cpu,
thread_id); thread_id);
break; break;
default: assert(false); break; // LCOV_EXCL_LINE default: assert(false); break; // LCOV_EXCL_LINE
} }
} }
} }
fprintf(fp, "VLPROF stat ticks %" VL_PRI64 "u\n", fprintf(fp, "VLPROF stat ticks %" VL_PRI64 "u\n", ticksElapsed);
ticksElapsed);
fclose(fp); fclose(fp);
} }

View File

@ -284,6 +284,7 @@ public:
// this once to setup profiling state: // this once to setup profiling state:
void setupProfilingClientThread(); void setupProfilingClientThread();
void tearDownProfilingClientThread(); void tearDownProfilingClientThread();
private: private:
VL_UNCOPYABLE(VlThreadPool); VL_UNCOPYABLE(VlThreadPool);
}; };

View File

@ -58,6 +58,7 @@ private:
VcdVec s_vcdVecp VL_GUARDED_BY(s_vcdMutex); ///< List of all created traces VcdVec s_vcdVecp VL_GUARDED_BY(s_vcdMutex); ///< List of all created traces
}; };
static Singleton& singleton() { static Singleton s; return s; } static Singleton& singleton() { static Singleton s; return s; }
public: public:
static void pushVcd(VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) { static void pushVcd(VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
VerilatedLockGuard lock(singleton().s_vcdMutex); VerilatedLockGuard lock(singleton().s_vcdMutex);
@ -65,8 +66,8 @@ public:
} }
static void removeVcd(const VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) { static void removeVcd(const VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
VerilatedLockGuard lock(singleton().s_vcdMutex); VerilatedLockGuard lock(singleton().s_vcdMutex);
VcdVec::iterator pos = find(singleton().s_vcdVecp.begin(), VcdVec::iterator pos
singleton().s_vcdVecp.end(), vcdp); = find(singleton().s_vcdVecp.begin(), singleton().s_vcdVecp.end(), vcdp);
if (pos != singleton().s_vcdVecp.end()) { singleton().s_vcdVecp.erase(pos); } if (pos != singleton().s_vcdVecp.end()) { singleton().s_vcdVecp.erase(pos); }
} }
static void flush_all() VL_EXCLUDES(singleton().s_vcdMutex) VL_MT_UNSAFE_ONE { static void flush_all() VL_EXCLUDES(singleton().s_vcdMutex) VL_MT_UNSAFE_ONE {
@ -115,13 +116,12 @@ protected:
// VerilatedVcdFile // VerilatedVcdFile
bool VerilatedVcdFile::open(const std::string& name) VL_MT_UNSAFE { bool VerilatedVcdFile::open(const std::string& name) VL_MT_UNSAFE {
m_fd = ::open(name.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK|O_CLOEXEC, 0666); m_fd = ::open(name.c_str(),
O_CREAT | O_WRONLY | O_TRUNC | O_LARGEFILE | O_NONBLOCK | O_CLOEXEC, 0666);
return m_fd >= 0; return m_fd >= 0;
} }
void VerilatedVcdFile::close() VL_MT_UNSAFE { void VerilatedVcdFile::close() VL_MT_UNSAFE { ::close(m_fd); }
::close(m_fd);
}
ssize_t VerilatedVcdFile::write(const char* bufp, ssize_t len) VL_MT_UNSAFE { ssize_t VerilatedVcdFile::write(const char* bufp, ssize_t len) VL_MT_UNSAFE {
return ::write(m_fd, bufp, len); return ::write(m_fd, bufp, len);
@ -147,8 +147,8 @@ VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
m_evcd = false; m_evcd = false;
m_scopeEscape = '.'; // Backward compatibility m_scopeEscape = '.'; // Backward compatibility
m_fullDump = true; m_fullDump = true;
m_wrChunkSize = 8*1024; m_wrChunkSize = 8 * 1024;
m_wrBufp = new char [m_wrChunkSize*8]; m_wrBufp = new char[m_wrChunkSize * 8];
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6; m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
m_writep = m_wrBufp; m_writep = m_wrBufp;
m_wroteBytes = 0; m_wroteBytes = 0;
@ -167,15 +167,13 @@ void VerilatedVcd::open(const char* filename) {
Verilated::flushCb(&flush_all); Verilated::flushCb(&flush_all);
// SPDIFF_ON // SPDIFF_ON
openNext(m_rolloverMB!=0); openNext(m_rolloverMB != 0);
if (!isOpen()) return; if (!isOpen()) return;
dumpHeader(); dumpHeader();
// Allocate space now we know the number of codes // Allocate space now we know the number of codes
if (!m_sigs_oldvalp) { if (!m_sigs_oldvalp) m_sigs_oldvalp = new vluint32_t[m_nextCode + 10];
m_sigs_oldvalp = new vluint32_t [m_nextCode+10];
}
if (m_rolloverMB) { if (m_rolloverMB) {
openNext(true); openNext(true);
@ -192,28 +190,29 @@ void VerilatedVcd::openNext(bool incFilename) {
// Find _0000.{ext} in filename // Find _0000.{ext} in filename
std::string name = m_filename; std::string name = m_filename;
size_t pos = name.rfind('.'); size_t pos = name.rfind('.');
if (pos>8 && 0==strncmp("_cat",name.c_str()+pos-8,4) if (pos > 8 && 0 == strncmp("_cat", name.c_str() + pos - 8, 4)
&& isdigit(name.c_str()[pos-4]) && isdigit(name.c_str()[pos - 4])
&& isdigit(name.c_str()[pos-3]) && isdigit(name.c_str()[pos - 3])
&& isdigit(name.c_str()[pos-2]) && isdigit(name.c_str()[pos - 2])
&& isdigit(name.c_str()[pos-1])) { && isdigit(name.c_str()[pos - 1])) {
// Increment code. // Increment code.
if ((++(name[pos-1])) > '9') { if ((++(name[pos - 1])) > '9') {
name[pos-1] = '0'; name[pos - 1] = '0';
if ((++(name[pos-2])) > '9') { if ((++(name[pos - 2])) > '9') {
name[pos-2] = '0'; name[pos - 2] = '0';
if ((++(name[pos-3])) > '9') { if ((++(name[pos - 3])) > '9') {
name[pos-3] = '0'; name[pos - 3] = '0';
if ((++(name[pos-4])) > '9') { if ((++(name[pos - 4])) > '9') { name[pos - 4] = '0'; }
name[pos-4] = '0'; }
}}}} }
}
} else { } else {
// Append _cat0000 // Append _cat0000
name.insert(pos,"_cat0000"); name.insert(pos, "_cat0000");
} }
m_filename = name; m_filename = name;
} }
if (m_filename[0]=='|') { if (m_filename[0] == '|') {
assert(0); // Not supported yet. assert(0); // Not supported yet.
} else { } else {
// cppcheck-suppress duplicateExpression // cppcheck-suppress duplicateExpression
@ -245,19 +244,19 @@ void VerilatedVcd::makeNameMap() {
// If no scope was specified, prefix everything with a "top" // If no scope was specified, prefix everything with a "top"
// This comes from user instantiations with no name - IE Vtop(""). // This comes from user instantiations with no name - IE Vtop("").
bool nullScope = false; bool nullScope = false;
for (NameMap::const_iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) { for (NameMap::const_iterator it = m_namemapp->begin(); it != m_namemapp->end(); ++it) {
const std::string& hiername = it->first; const std::string& hiername = it->first;
if (!hiername.empty() && hiername[0] == '\t') nullScope=true; if (!hiername.empty() && hiername[0] == '\t') nullScope = true;
} }
if (nullScope) { if (nullScope) {
NameMap* newmapp = new NameMap; NameMap* newmapp = new NameMap;
for (NameMap::const_iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) { for (NameMap::const_iterator it = m_namemapp->begin(); it != m_namemapp->end(); ++it) {
const std::string& hiername = it->first; const std::string& hiername = it->first;
const std::string& decl = it->second; const std::string& decl = it->second;
std::string newname = std::string("top"); std::string newname = std::string("top");
if (hiername[0] != '\t') newname += ' '; if (hiername[0] != '\t') newname += ' ';
newname += hiername; newname += hiername;
newmapp->insert(std::make_pair(newname,decl)); newmapp->insert(std::make_pair(newname, decl));
} }
deleteNameMap(); deleteNameMap();
m_namemapp = newmapp; m_namemapp = newmapp;
@ -322,8 +321,8 @@ void VerilatedVcd::printStr(const char* str) {
} }
void VerilatedVcd::printQuad(vluint64_t n) { void VerilatedVcd::printQuad(vluint64_t n) {
char buf [100]; char buf[100];
sprintf(buf,"%" VL_PRI64 "u", n); sprintf(buf, "%" VL_PRI64 "u", n);
printStr(buf); printStr(buf);
} }
@ -366,17 +365,17 @@ void VerilatedVcd::bufferFlush() VL_MT_UNSAFE_ONE {
char* wp = m_wrBufp; char* wp = m_wrBufp;
while (true) { while (true) {
ssize_t remaining = (m_writep - wp); ssize_t remaining = (m_writep - wp);
if (remaining==0) break; if (remaining == 0) break;
errno = 0; errno = 0;
ssize_t got = m_filep->write(wp, remaining); ssize_t got = m_filep->write(wp, remaining);
if (got>0) { if (got > 0) {
wp += got; wp += got;
m_wroteBytes += got; m_wroteBytes += got;
} else if (got < 0) { } else if (got < 0) {
if (errno != EAGAIN && errno != EINTR) { if (errno != EAGAIN && errno != EINTR) {
// write failed, presume error (perhaps out of disk space) // write failed, presume error (perhaps out of disk space)
std::string msg = std::string("VerilatedVcd::bufferFlush: ")+strerror(errno); std::string msg = std::string("VerilatedVcd::bufferFlush: ") + strerror(errno);
VL_FATAL_MT("",0,"",msg.c_str()); VL_FATAL_MT("", 0, "", msg.c_str());
closeErr(); closeErr();
break; break;
} }
@ -391,13 +390,13 @@ void VerilatedVcd::bufferFlush() VL_MT_UNSAFE_ONE {
// Simple methods // Simple methods
void VerilatedVcd::set_time_unit(const char* unitp) { void VerilatedVcd::set_time_unit(const char* unitp) {
//cout<<" set_time_unit("<<unitp<<") == "<<timescaleToDouble(unitp) // cout<<" set_time_unit("<<unitp<<") == "<<timescaleToDouble(unitp)
// <<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl; // <<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
m_timeUnit = timescaleToDouble(unitp); m_timeUnit = timescaleToDouble(unitp);
} }
void VerilatedVcd::set_time_resolution(const char* unitp) { void VerilatedVcd::set_time_resolution(const char* unitp) {
//cout<<"set_time_resolution("<<unitp<<") == "<<timescaleToDouble(unitp) // cout<<"set_time_resolution("<<unitp<<") == "<<timescaleToDouble(unitp)
// <<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl; // <<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
m_timeRes = timescaleToDouble(unitp); m_timeRes = timescaleToDouble(unitp);
} }
@ -405,9 +404,9 @@ void VerilatedVcd::set_time_resolution(const char* unitp) {
double VerilatedVcd::timescaleToDouble(const char* unitp) { double VerilatedVcd::timescaleToDouble(const char* unitp) {
char* endp; char* endp;
double value = strtod(unitp, &endp); double value = strtod(unitp, &endp);
if (value==0.0 && endp==unitp) value=1; // On error so we allow just "ns" to return 1e-9. if (value == 0.0 && endp == unitp) value = 1; // On error so we allow just "ns" to return 1e-9.
unitp=endp; unitp = endp;
while (*unitp && isspace(*unitp)) unitp++; for (; *unitp && isspace(*unitp); unitp++) {}
switch (*unitp) { switch (*unitp) {
case 's': value *= 1e1; break; case 's': value *= 1e1; break;
case 'm': value *= 1e-3; break; case 'm': value *= 1e-3; break;
@ -429,7 +428,8 @@ std::string VerilatedVcd::doubleToTimescale(double value) {
else if (value>=1e-12) { suffixp="ps"; value *= 1e12; } else if (value>=1e-12) { suffixp="ps"; value *= 1e12; }
else if (value>=1e-15) { suffixp="fs"; value *= 1e15; } else if (value>=1e-15) { suffixp="fs"; value *= 1e15; }
else if (value>=1e-18) { suffixp="as"; value *= 1e18; } else if (value>=1e-18) { suffixp="as"; value *= 1e18; }
char valuestr[100]; sprintf(valuestr,"%3.0f%s", value, suffixp); char valuestr[100];
sprintf(valuestr, "%3.0f%s", value, suffixp);
return valuestr; // Gets converted to string, so no ref to stack return valuestr; // Gets converted to string, so no ref to stack
} }
@ -437,16 +437,20 @@ std::string VerilatedVcd::doubleToTimescale(double value) {
// Definitions // Definitions
void VerilatedVcd::printIndent(int level_change) { void VerilatedVcd::printIndent(int level_change) {
if (level_change<0) m_modDepth += level_change; if (level_change < 0) m_modDepth += level_change;
assert(m_modDepth>=0); assert(m_modDepth >= 0);
for (int i=0; i<m_modDepth; i++) printStr(" "); for (int i = 0; i < m_modDepth; i++) {
if (level_change>0) m_modDepth += level_change; printStr(" ");
}
if (level_change > 0) m_modDepth += level_change;
} }
void VerilatedVcd::dumpHeader() { void VerilatedVcd::dumpHeader() {
printStr("$version Generated by VerilatedVcd $end\n"); printStr("$version Generated by VerilatedVcd $end\n");
time_t time_str = time(NULL); time_t time_str = time(NULL);
printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n"); printStr("$date ");
printStr(ctime(&time_str));
printStr(" $end\n");
printStr("$timescale "); printStr("$timescale ");
const std::string& timeResStr = doubleToTimescale(m_timeRes); const std::string& timeResStr = doubleToTimescale(m_timeRes);
@ -456,7 +460,7 @@ void VerilatedVcd::dumpHeader() {
makeNameMap(); makeNameMap();
// Signal header // Signal header
assert(m_modDepth==0); assert(m_modDepth == 0);
printIndent(1); printIndent(1);
printStr("\n"); printStr("\n");
@ -467,7 +471,7 @@ void VerilatedVcd::dumpHeader() {
// Print the signal names // Print the signal names
const char* lastName = ""; const char* lastName = "";
for (NameMap::const_iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) { for (NameMap::const_iterator it = m_namemapp->begin(); it != m_namemapp->end(); ++it) {
const std::string& hiernamestr = it->first; const std::string& hiernamestr = it->first;
const std::string& decl = it->second; const std::string& decl = it->second;
@ -479,13 +483,16 @@ void VerilatedVcd::dumpHeader() {
// Skip common prefix, it must break at a space or tab // Skip common prefix, it must break at a space or tab
for (; *np && (*np == *lp); np++, lp++) {} for (; *np && (*np == *lp); np++, lp++) {}
while (np!=hiername && *np && *np!=' ' && *np!='\t') { np--; lp--; } while (np != hiername && *np && *np != ' ' && *np != '\t') {
//printf("hier %s\n lp=%s\n np=%s\n",hiername,lp,np); np--;
lp--;
}
// printf("hier %s\n lp=%s\n np=%s\n",hiername,lp,np);
// Any extra spaces in last name are scope ups we need to do // Any extra spaces in last name are scope ups we need to do
bool first = true; bool first = true;
for (; *lp; lp++) { for (; *lp; lp++) {
if (*lp==' ' || (first && *lp!='\t')) { if (*lp == ' ' || (first && *lp != '\t')) {
printIndent(-1); printIndent(-1);
printStr("$upscope $end\n"); printStr("$upscope $end\n");
} }
@ -494,14 +501,18 @@ void VerilatedVcd::dumpHeader() {
// Any new spaces are scope downs we need to do // Any new spaces are scope downs we need to do
while (*np) { while (*np) {
if (*np==' ') np++; if (*np == ' ') np++;
if (*np=='\t') break; // tab means signal name starts if (*np == '\t') break; // tab means signal name starts
printIndent(1); printIndent(1);
printStr("$scope module "); printStr("$scope module ");
for (; *np && *np!=' ' && *np!='\t'; np++) { for (; *np && *np != ' ' && *np != '\t'; np++) {
if (*np=='[') printStr("("); if (*np == '[') {
else if (*np==']') printStr(")"); printStr("(");
else *m_writep++=*np; } else if (*np == ']') {
printStr(")");
} else {
*m_writep++ = *np;
}
} }
printStr(" $end\n"); printStr(" $end\n");
} }
@ -510,7 +521,7 @@ void VerilatedVcd::dumpHeader() {
printStr(decl.c_str()); printStr(decl.c_str());
} }
while (m_modDepth>1) { while (m_modDepth > 1) {
printIndent(-1); printIndent(-1);
printStr("$upscope $end\n"); printStr("$upscope $end\n");
} }
@ -530,8 +541,9 @@ void VerilatedVcd::module(const std::string& name) {
void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep, void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
bool array, int arraynum, bool tri, bool bussed, int msb, int lsb) { bool array, int arraynum, bool tri, bool bussed, int msb, int lsb) {
if (!code) { VL_FATAL_MT(__FILE__, __LINE__, "", if (!code) {
"Internal: internal trace problem, code 0 is illegal"); } VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: internal trace problem, code 0 is illegal");
}
int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1; int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
int codesNeeded = 1 + int(bits / 32); int codesNeeded = 1 + int(bits / 32);
@ -540,11 +552,11 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
// Make sure array is large enough // Make sure array is large enough
m_nextCode = std::max(m_nextCode, code + codesNeeded); m_nextCode = std::max(m_nextCode, code + codesNeeded);
if (m_sigs.capacity() <= m_nextCode) { if (m_sigs.capacity() <= m_nextCode) {
m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up m_sigs.reserve(m_nextCode * 2); // Power-of-2 allocation speeds things up
} }
// Make sure write buffer is large enough (one character per bit), plus header // Make sure write buffer is large enough (one character per bit), plus header
bufferResize(bits+1024); bufferResize(bits + 1024);
// Save declaration info // Save declaration info
VerilatedVcdSig sig = VerilatedVcdSig(code, bits); VerilatedVcdSig sig = VerilatedVcdSig(code, bits);
@ -558,11 +570,11 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
// Note the hiername may be nothing, if so we'll add "\t{name}" // Note the hiername may be nothing, if so we'll add "\t{name}"
std::string nameasstr = name; std::string nameasstr = name;
if (!m_modName.empty()) { if (!m_modName.empty()) {
nameasstr = m_modName+m_scopeEscape+nameasstr; // Optional ->module prefix nameasstr = m_modName + m_scopeEscape + nameasstr; // Optional ->module prefix
} }
std::string hiername; std::string hiername;
std::string basename; std::string basename;
for (const char* cp=nameasstr.c_str(); *cp; cp++) { for (const char* cp = nameasstr.c_str(); *cp; cp++) {
if (isScopeEscape(*cp)) { if (isScopeEscape(*cp)) {
// Ahh, we've just read a scope, not a basename // Ahh, we've just read a scope, not a basename
if (!hiername.empty()) hiername += " "; if (!hiername.empty()) hiername += " ";
@ -572,12 +584,17 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
basename += *cp; basename += *cp;
} }
} }
hiername += "\t"+basename; hiername += "\t" + basename;
// Print reference // Print reference
std::string decl = "$var "; std::string decl = "$var ";
if (m_evcd) decl += "port"; else decl += wirep; // usually "wire" if (m_evcd) {
char buf [1000]; decl += "port";
} else {
decl += wirep; // usually "wire"
}
char buf[1000];
sprintf(buf, " %2d ", bits); sprintf(buf, " %2d ", bits);
decl += buf; decl += buf;
if (m_evcd) { if (m_evcd) {
@ -598,7 +615,7 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
decl += buf; decl += buf;
} }
decl += " $end\n"; decl += " $end\n";
m_namemapp->insert(std::make_pair(hiername,decl)); m_namemapp->insert(std::make_pair(hiername, decl));
} }
void VerilatedVcd::declBit(vluint32_t code, const char* name, bool array, int arraynum) { void VerilatedVcd::declBit(vluint32_t code, const char* name, bool array, int arraynum) {
@ -646,7 +663,9 @@ void VerilatedVcd::fullDouble(vluint32_t code, const double newval) {
// Buffer can't overflow before sprintf; we sized during declaration // Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", newval); sprintf(m_writep, "r%.16g", newval);
m_writep += strlen(m_writep); m_writep += strlen(m_writep);
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++ = ' ';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
void VerilatedVcd::fullFloat(vluint32_t code, const float newval) { void VerilatedVcd::fullFloat(vluint32_t code, const float newval) {
@ -655,7 +674,9 @@ void VerilatedVcd::fullFloat(vluint32_t code, const float newval) {
// Buffer can't overflow before sprintf; we sized during declaration // Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", static_cast<double>(newval)); sprintf(m_writep, "r%.16g", static_cast<double>(newval));
m_writep += strlen(m_writep); m_writep += strlen(m_writep);
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++ = ' ';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
@ -716,9 +737,7 @@ void VerilatedVcd::dumpPrep(vluint64_t timeui) {
//====================================================================== //======================================================================
// Static members // Static members
void VerilatedVcd::flush_all() VL_MT_UNSAFE_ONE { void VerilatedVcd::flush_all() VL_MT_UNSAFE_ONE { VerilatedVcdSingleton::flush_all(); }
VerilatedVcdSingleton::flush_all();
}
//====================================================================== //======================================================================
//====================================================================== //======================================================================
@ -748,39 +767,39 @@ void vcdInit(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
// Note need to add 3 for next code. // Note need to add 3 for next code.
vcdp->module("top2"); vcdp->module("top2");
vcdp->declBus(0x2, "t2v1",-1,4,1); vcdp->declBus(0x2, "t2v1",-1,4,1);
vcdp->declTriBit (0x10, "io1", -1); vcdp->declTriBit(0x10, "io1",-1);
vcdp->declTriBus (0x12, "io5", -1,4,0); vcdp->declTriBus(0x12, "io5",-1,4,0);
vcdp->declTriArray(0x16, "io96",-1,95,0); vcdp->declTriArray(0x16, "io96",-1,95,0);
// Note need to add 6 for next code. // Note need to add 6 for next code.
vcdp->declDouble (0x1c, "doub",-1); vcdp->declDouble(0x1c, "doub",-1);
// Note need to add 2 for next code. // Note need to add 2 for next code.
vcdp->declArray(0x1e, "q2",-1, 95, 0); vcdp->declArray(0x1e, "q2",-1,95,0);
// Note need to add 4 for next code. // Note need to add 4 for next code.
} }
void vcdFull(VerilatedVcd* vcdp, void* userthis, vluint32_t code) { void vcdFull(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
vcdp->fullBus (0x2, v1,5); vcdp->fullBus(0x2, v1, 5);
vcdp->fullBus (0x3, v2,7); vcdp->fullBus(0x3, v2, 7);
vcdp->fullBit (0x4, s1); vcdp->fullBit(0x4, s1);
vcdp->fullBus (0x5, ch,2); vcdp->fullBus(0x5, ch, 2);
vcdp->fullArray(0x6, &s2[0], 38); vcdp->fullArray(0x6, &s2[0], 38);
vcdp->fullTriBit (0x10, tri96[0]&1, tri96__tri[0]&1); vcdp->fullTriBit(0x10, tri96[0] & 1, tri96__tri[0] & 1);
vcdp->fullTriBus (0x12, tri96[0]&0x1f, tri96__tri[0]&0x1f, 5); vcdp->fullTriBus(0x12, tri96[0] & 0x1f, tri96__tri[0] & 0x1f, 5);
vcdp->fullTriArray(0x16, tri96, tri96__tri, 96); vcdp->fullTriArray(0x16, tri96, tri96__tri, 96);
vcdp->fullDouble(0x1c, doub); vcdp->fullDouble(0x1c, doub);
vcdp->fullArray(0x1e, &quad96[0], 96); vcdp->fullArray(0x1e, &quad96[0], 96);
} }
void vcdChange(VerilatedVcd* vcdp, void* userthis, vluint32_t code) { void vcdChange(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
vcdp->chgBus (0x2, v1,5); vcdp->chgBus(0x2, v1, 5);
vcdp->chgBus (0x3, v2,7); vcdp->chgBus(0x3, v2, 7);
vcdp->chgBit (0x4, s1); vcdp->chgBit(0x4, s1);
vcdp->chgBus (0x5, ch,2); vcdp->chgBus(0x5, ch, 2);
vcdp->chgArray(0x6, &s2[0], 38); vcdp->chgArray(0x6, &s2[0], 38);
vcdp->chgTriBit (0x10, tri96[0]&1, tri96__tri[0]&1); vcdp->chgTriBit(0x10, tri96[0] & 1, tri96__tri[0] & 1);
vcdp->chgTriBus (0x12, tri96[0]&0x1f, tri96__tri[0]&0x1f, 5); vcdp->chgTriBus(0x12, tri96[0] & 0x1f, tri96__tri[0] & 0x1f, 5);
vcdp->chgTriArray (0x16, tri96, tri96__tri, 96); vcdp->chgTriArray(0x16, tri96, tri96__tri, 96);
vcdp->chgDouble (0x1c, doub); vcdp->chgDouble(0x1c, doub);
vcdp->chgArray(0x1e, &quad96[0], 96); vcdp->chgArray(0x1e, &quad96[0], 96);
} }
@ -803,13 +822,13 @@ main() {
v1 = 0xfff; v1 = 0xfff;
tri96[2] = 4; tri96[1] = 2; tri96[0] = 1; tri96[2] = 4; tri96[1] = 2; tri96[0] = 1;
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = ~0; // Still tri tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = ~0; // Still tri
quad96[1] = 0xffffffff ; quad96[0] = 0; quad96[1] = 0xffffffff; quad96[0] = 0;
doub = 1.5; doub = 1.5;
vcdp->dump(timestamp++); vcdp->dump(timestamp++);
v2 = 0x1; v2 = 0x1;
s2[1] = 2; s2[1] = 2;
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = 0; // enable w/o data change tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = 0; // enable w/o data change
quad96[1] = 0 ; quad96[0] = ~0; quad96[1] = 0; quad96[0] = ~0;
doub = -1.66e13; doub = -1.66e13;
vcdp->dump(timestamp++); vcdp->dump(timestamp++);
ch = 2; ch = 2;

View File

@ -60,6 +60,7 @@ protected:
VerilatedVcdSig(vluint32_t code, int bits) VerilatedVcdSig(vluint32_t code, int bits)
: m_code(code) : m_code(code)
, m_bits(bits) {} , m_bits(bits) {}
public: public:
~VerilatedVcdSig() {} ~VerilatedVcdSig() {}
}; };
@ -75,33 +76,33 @@ typedef void (*VerilatedVcdCallback_t)(VerilatedVcd* vcdp, void* userthis, vluin
class VerilatedVcd { class VerilatedVcd {
private: private:
VerilatedVcdFile* m_filep; ///< File we're writing to VerilatedVcdFile* m_filep; ///< File we're writing to
bool m_fileNewed; ///< m_filep needs destruction bool m_fileNewed; ///< m_filep needs destruction
bool m_isOpen; ///< True indicates open file bool m_isOpen; ///< True indicates open file
bool m_evcd; ///< True for evcd format bool m_evcd; ///< True for evcd format
std::string m_filename; ///< Filename we're writing to (if open) std::string m_filename; ///< Filename we're writing to (if open)
vluint64_t m_rolloverMB; ///< MB of file size to rollover at vluint64_t m_rolloverMB; ///< MB of file size to rollover at
char m_scopeEscape; ///< Character to separate scope components char m_scopeEscape; ///< Character to separate scope components
int m_modDepth; ///< Depth of module hierarchy int m_modDepth; ///< Depth of module hierarchy
bool m_fullDump; ///< True indicates dump ignoring if changed bool m_fullDump; ///< True indicates dump ignoring if changed
vluint32_t m_nextCode; ///< Next code number to assign vluint32_t m_nextCode; ///< Next code number to assign
std::string m_modName; ///< Module name being traced now std::string m_modName; ///< Module name being traced now
double m_timeRes; ///< Time resolution (ns/ms etc) double m_timeRes; ///< Time resolution (ns/ms etc)
double m_timeUnit; ///< Time units (ns/ms etc) double m_timeUnit; ///< Time units (ns/ms etc)
vluint64_t m_timeLastDump; ///< Last time we did a dump vluint64_t m_timeLastDump; ///< Last time we did a dump
char* m_wrBufp; ///< Output buffer char* m_wrBufp; ///< Output buffer
char* m_wrFlushp; ///< Output buffer flush trigger location char* m_wrFlushp; ///< Output buffer flush trigger location
char* m_writep; ///< Write pointer into output buffer char* m_writep; ///< Write pointer into output buffer
vluint64_t m_wrChunkSize; ///< Output buffer size vluint64_t m_wrChunkSize; ///< Output buffer size
vluint64_t m_wroteBytes; ///< Number of bytes written to this file vluint64_t m_wroteBytes; ///< Number of bytes written to this file
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
typedef std::vector<VerilatedVcdSig> SigVec; typedef std::vector<VerilatedVcdSig> SigVec;
SigVec m_sigs; ///< Pointer to signal information SigVec m_sigs; ///< Pointer to signal information
typedef std::vector<VerilatedVcdCallInfo*> CallbackVec; typedef std::vector<VerilatedVcdCallInfo*> CallbackVec;
CallbackVec m_callbacks; ///< Routines to perform dumping CallbackVec m_callbacks; ///< Routines to perform dumping
typedef std::map<std::string,std::string> NameMap; typedef std::map<std::string, std::string> NameMap;
NameMap* m_namemapp; ///< List of names for the header NameMap* m_namemapp; ///< List of names for the header
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
@ -153,6 +154,7 @@ private:
// CONSTRUCTORS // CONSTRUCTORS
VL_UNCOPYABLE(VerilatedVcd); VL_UNCOPYABLE(VerilatedVcd);
public: public:
explicit VerilatedVcd(VerilatedVcdFile* filep = NULL); explicit VerilatedVcd(VerilatedVcdFile* filep = NULL);
~VerilatedVcd(); ~VerilatedVcd();
@ -170,7 +172,8 @@ public:
inline bool isScopeEscape(char c) { return isspace(c) || c == m_scopeEscape; } inline bool isScopeEscape(char c) { return isspace(c) || c == m_scopeEscape; }
// METHODS // METHODS
void open(const char* filename) VL_MT_UNSAFE_ONE; ///< Open the file; call isOpen() to see if errors /// Open the file; call isOpen() to see if errors
void open(const char* filename) VL_MT_UNSAFE_ONE;
void openNext(bool incFilename); ///< Open next data-only file void openNext(bool incFilename); ///< Open next data-only file
void close() VL_MT_UNSAFE_ONE; ///< Close the file void close() VL_MT_UNSAFE_ONE; ///< Close the file
/// Flush any remaining data to this file /// Flush any remaining data to this file
@ -194,47 +197,54 @@ public:
/// Inside dumping routines, declare callbacks for tracings /// Inside dumping routines, declare callbacks for tracings
void addCallback(VerilatedVcdCallback_t initcb, VerilatedVcdCallback_t fullcb, void addCallback(VerilatedVcdCallback_t initcb, VerilatedVcdCallback_t fullcb,
VerilatedVcdCallback_t changecb, VerilatedVcdCallback_t changecb, void* userthis) VL_MT_UNSAFE_ONE;
void* userthis) VL_MT_UNSAFE_ONE;
/// 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 signal /// Inside dumping routines, declare a signal
void declBit( vluint32_t code, const char* name, bool array, int arraynum); void declBit(vluint32_t code, const char* name, bool array, int arraynum);
void declBus( vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declBus(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
void declQuad( vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declQuad(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
void declArray( vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declArray(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
void declTriBit( vluint32_t code, const char* name, bool array, int arraynum); void declTriBit(vluint32_t code, const char* name, bool array, int arraynum);
void declTriBus( vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declTriBus(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
void declTriQuad( vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declTriQuad(vluint32_t code, const char* name, bool array, int arraynum, int msb,
void declTriArray(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); int lsb);
void declDouble( vluint32_t code, const char* name, bool array, int arraynum); void declTriArray(vluint32_t code, const char* name, bool array, int arraynum, int msb,
void declFloat( vluint32_t code, const char* name, bool array, int arraynum); int lsb);
void declDouble(vluint32_t code, const char* name, bool array, int arraynum);
void declFloat(vluint32_t code, const char* name, bool array, int arraynum);
// ... other module_start for submodules (based on cell name) // ... other module_start for submodules (based on cell name)
/// Inside dumping routines, dump one signal /// Inside dumping routines, dump one signal
void fullBit(vluint32_t code, const vluint32_t newval) { void fullBit(vluint32_t code, const vluint32_t newval) {
// Note the &1, so we don't require clean input -- makes more common no change case faster // Note the &1, so we don't require clean input -- makes more common no change case faster
m_sigs_oldvalp[code] = newval; m_sigs_oldvalp[code] = newval;
*m_writep++=('0'+static_cast<char>(newval&1)); printCode(code); *m_writep++='\n'; *m_writep++ = ('0' + static_cast<char>(newval & 1));
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
void fullBus(vluint32_t code, const vluint32_t newval, int bits) { void fullBus(vluint32_t code, const vluint32_t newval, int bits) {
m_sigs_oldvalp[code] = newval; m_sigs_oldvalp[code] = newval;
*m_writep++='b'; *m_writep++ = 'b';
for (int bit=bits-1; bit>=0; --bit) { for (int bit = bits - 1; bit >= 0; --bit) {
*m_writep++=((newval&(1L<<bit))?'1':'0'); *m_writep++ = ((newval & (1L << bit)) ? '1' : '0');
} }
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++ = ' ';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
void fullQuad(vluint32_t code, const vluint64_t newval, int bits) { void fullQuad(vluint32_t code, const vluint64_t newval, int bits) {
(*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) = newval; (*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) = newval;
*m_writep++='b'; *m_writep++ = 'b';
for (int bit=bits-1; bit>=0; --bit) { for (int bit = bits - 1; bit >= 0; --bit) {
*m_writep++ = ((newval & (VL_ULL(1) << bit)) ? '1' : '0'); *m_writep++ = ((newval & (VL_ULL(1) << bit)) ? '1' : '0');
} }
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++ = ' ';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
void fullArray(vluint32_t code, const vluint32_t* newval, int bits) { void fullArray(vluint32_t code, const vluint32_t* newval, int bits) {
@ -245,64 +255,72 @@ public:
for (int bit = bits - 1; bit >= 0; --bit) { for (int bit = bits - 1; bit >= 0; --bit) {
*m_writep++ = ((newval[(bit / 32)] & (1L << (bit & 0x1f))) ? '1' : '0'); *m_writep++ = ((newval[(bit / 32)] & (1L << (bit & 0x1f))) ? '1' : '0');
} }
*m_writep ++= ' '; printCode(code); *m_writep ++= '\n'; *m_writep++ = ' ';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
void fullArray(vluint32_t code, const vluint64_t* newval, int bits) { void fullArray(vluint32_t code, const vluint64_t* newval, int bits) {
for (int word = 0; word < (((bits - 1) / 64) + 1); ++word) { for (int word = 0; word < (((bits - 1) / 64) + 1); ++word) {
m_sigs_oldvalp[code + word] = newval[word]; m_sigs_oldvalp[code + word] = newval[word];
} }
*m_writep ++= 'b'; *m_writep++ = 'b';
for (int bit = bits - 1; bit >= 0; --bit) { for (int bit = bits - 1; bit >= 0; --bit) {
*m_writep++ = ((newval[(bit / 64)] & (VL_ULL(1) << (bit & 0x3f))) ? '1' : '0'); *m_writep++ = ((newval[(bit / 64)] & (VL_ULL(1) << (bit & 0x3f))) ? '1' : '0');
} }
*m_writep ++= ' '; printCode(code); *m_writep ++= '\n'; *m_writep++ = ' ';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
void fullTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri) { void fullTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri) {
m_sigs_oldvalp[code] = newval; m_sigs_oldvalp[code] = newval;
m_sigs_oldvalp[code+1] = newtri; m_sigs_oldvalp[code + 1] = newtri;
*m_writep++ = "01zz"[m_sigs_oldvalp[code] *m_writep++ = "01zz"[m_sigs_oldvalp[code] | (m_sigs_oldvalp[code + 1] << 1)];
| (m_sigs_oldvalp[code+1]<<1)]; printCode(code);
printCode(code); *m_writep++='\n'; *m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
void fullTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits) { void fullTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits) {
m_sigs_oldvalp[code] = newval; m_sigs_oldvalp[code] = newval;
m_sigs_oldvalp[code+1] = newtri; m_sigs_oldvalp[code + 1] = newtri;
*m_writep++='b'; *m_writep++ = 'b';
for (int bit=bits-1; bit>=0; --bit) { for (int bit = bits - 1; bit >= 0; --bit) {
*m_writep++ = "01zz"[((newval >> bit)&1) *m_writep++ = "01zz"[((newval >> bit) & 1) | (((newtri >> bit) & 1) << 1)];
| (((newtri >> bit)&1)<<1)];
} }
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++ = ' ';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
void fullTriQuad(vluint32_t code, const vluint64_t newval, void fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits) {
const vluint32_t newtri, int bits) {
(*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) = newval; (*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) = newval;
(*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code+1]))) = newtri; (*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code + 1]))) = newtri;
*m_writep++='b'; *m_writep++ = 'b';
for (int bit=bits-1; bit>=0; --bit) { for (int bit = bits - 1; bit >= 0; --bit) {
*m_writep++ = "01zz"[((newval >> bit) & VL_ULL(1)) *m_writep++ = "01zz"[((newval >> bit) & VL_ULL(1))
| (((newtri >> bit) & VL_ULL(1)) << VL_ULL(1))]; | (((newtri >> bit) & VL_ULL(1)) << VL_ULL(1))];
} }
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++ = ' ';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
void fullTriArray(vluint32_t code, const vluint32_t* newvalp, void fullTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip,
const vluint32_t* newtrip, int bits) { int bits) {
for (int word=0; word<(((bits-1)/32)+1); ++word) { for (int word = 0; word < (((bits - 1) / 32) + 1); ++word) {
m_sigs_oldvalp[code+word*2] = newvalp[word]; m_sigs_oldvalp[code + word * 2] = newvalp[word];
m_sigs_oldvalp[code+word*2+1] = newtrip[word]; m_sigs_oldvalp[code + word * 2 + 1] = newtrip[word];
} }
*m_writep++='b'; *m_writep++ = 'b';
for (int bit=bits-1; bit>=0; --bit) { for (int bit = bits - 1; bit >= 0; --bit) {
vluint32_t valbit = (newvalp[(bit/32)]>>(bit&0x1f)) & 1; vluint32_t valbit = (newvalp[(bit / 32)] >> (bit & 0x1f)) & 1;
vluint32_t tribit = (newtrip[(bit/32)]>>(bit&0x1f)) & 1; vluint32_t tribit = (newtrip[(bit / 32)] >> (bit & 0x1f)) & 1;
*m_writep++ = "01zz"[valbit | (tribit<<1)]; *m_writep++ = "01zz"[valbit | (tribit << 1)];
} }
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++ = ' ';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
void fullDouble(vluint32_t code, const double newval); void fullDouble(vluint32_t code, const double newval);
@ -313,15 +331,19 @@ public:
/// Thus this is for special standalone applications that after calling /// Thus this is for special standalone applications that after calling
/// fullBitX, must when then value goes non-X call fullBit. /// fullBitX, must when then value goes non-X call fullBit.
inline void fullBitX(vluint32_t code) { inline void fullBitX(vluint32_t code) {
*m_writep++='x'; printCode(code); *m_writep++='\n'; *m_writep++ = 'x';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
inline void fullBusX(vluint32_t code, int bits) { inline void fullBusX(vluint32_t code, int bits) {
*m_writep++='b'; *m_writep++ = 'b';
for (int bit=bits-1; bit>=0; --bit) { for (int bit = bits - 1; bit >= 0; --bit) {
*m_writep++='x'; *m_writep++ = 'x';
} }
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++ = ' ';
printCode(code);
*m_writep++ = '\n';
bufferCheck(); bufferCheck();
} }
inline void fullQuadX(vluint32_t code, int bits) { fullBusX(code, bits); } inline void fullQuadX(vluint32_t code, int bits) { fullBusX(code, bits); }
@ -370,10 +392,8 @@ public:
} }
} }
} }
inline void chgTriBit(vluint32_t code, const vluint32_t newval, inline void chgTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri) {
const vluint32_t newtri) { vluint32_t diff = ((m_sigs_oldvalp[code] ^ newval) | (m_sigs_oldvalp[code + 1] ^ newtri));
vluint32_t diff = ((m_sigs_oldvalp[code] ^ newval)
| (m_sigs_oldvalp[code+1] ^ newtri));
if (VL_UNLIKELY(diff)) { if (VL_UNLIKELY(diff)) {
// Verilator 3.510 and newer provide clean input, so the below // Verilator 3.510 and newer provide clean input, so the below
// is only for back compatibility // is only for back compatibility
@ -382,32 +402,32 @@ public:
} }
} }
} }
inline void chgTriBus(vluint32_t code, const vluint32_t newval, inline void chgTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri,
const vluint32_t newtri, int bits) { int bits) {
vluint32_t diff = ((m_sigs_oldvalp[code] ^ newval) vluint32_t diff = ((m_sigs_oldvalp[code] ^ newval) | (m_sigs_oldvalp[code + 1] ^ newtri));
| (m_sigs_oldvalp[code+1] ^ newtri));
if (VL_UNLIKELY(diff)) { if (VL_UNLIKELY(diff)) {
if (VL_UNLIKELY(bits==32 || (diff & ((1U<<bits)-1) ))) { if (VL_UNLIKELY(bits == 32 || (diff & ((1U << bits) - 1)))) {
fullTriBus(code, newval, newtri, bits); fullTriBus(code, newval, newtri, bits);
} }
} }
} }
inline void chgTriQuad(vluint32_t code, const vluint64_t newval, inline void chgTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri,
const vluint32_t newtri, int bits) { int bits) {
vluint64_t diff = ( ((*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) ^ newval) vluint64_t diff
| ((*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code+1]))) ^ newtri)); = (((*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) ^ newval)
| ((*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code + 1]))) ^ newtri));
if (VL_UNLIKELY(diff)) { if (VL_UNLIKELY(diff)) {
if (VL_UNLIKELY(bits == 64 || (diff & ((VL_ULL(1) << bits) - 1)))) { if (VL_UNLIKELY(bits == 64 || (diff & ((VL_ULL(1) << bits) - 1)))) {
fullTriQuad(code, newval, newtri, bits); fullTriQuad(code, newval, newtri, bits);
} }
} }
} }
inline void chgTriArray(vluint32_t code, const vluint32_t* newvalp, inline void chgTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip,
const vluint32_t* newtrip, int bits) { int bits) {
for (int word=0; word<(((bits-1)/32)+1); ++word) { for (int word = 0; word < (((bits - 1) / 32) + 1); ++word) {
if (VL_UNLIKELY((m_sigs_oldvalp[code+word*2] ^ newvalp[word]) if (VL_UNLIKELY((m_sigs_oldvalp[code + word * 2] ^ newvalp[word])
| (m_sigs_oldvalp[code+word*2+1] ^ newtrip[word]))) { | (m_sigs_oldvalp[code + word * 2 + 1] ^ newtrip[word]))) {
fullTriArray(code,newvalp,newtrip,bits); fullTriArray(code, newvalp, newtrip, bits);
return; return;
} }
} }
@ -441,12 +461,14 @@ class VerilatedVcdC {
// CONSTRUCTORS // CONSTRUCTORS
VL_UNCOPYABLE(VerilatedVcdC); VL_UNCOPYABLE(VerilatedVcdC);
public: public:
explicit VerilatedVcdC(VerilatedVcdFile* filep = NULL) explicit VerilatedVcdC(VerilatedVcdFile* filep = NULL)
: m_sptrace(filep) {} : m_sptrace(filep) {}
~VerilatedVcdC() { close(); } ~VerilatedVcdC() { close(); }
/// Routines can only be called from one thread; allow next call from different thread /// Routines can only be called from one thread; allow next call from different thread
void changeThread() { spTrace()->changeThread(); } void changeThread() { spTrace()->changeThread(); }
public: public:
// ACCESSORS // ACCESSORS
/// Is file open? /// Is file open?