Internals: Add more const. No functional change.

This commit is contained in:
Wilson Snyder 2021-06-18 22:19:35 -04:00
parent 6c9c16c31d
commit 52cde49a6f
17 changed files with 532 additions and 510 deletions

View File

@ -215,7 +215,7 @@ std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
char* bufp = new char[len + 1]; char* bufp = new char[len + 1];
VL_VSNPRINTF(bufp, len + 1, formatp, ap); VL_VSNPRINTF(bufp, len + 1, formatp, ap);
std::string out = std::string(bufp, len); const std::string out = std::string(bufp, len);
delete[] bufp; delete[] bufp;
return out; return out;
} }
@ -246,7 +246,7 @@ void VL_DBG_MSGF(const char* formatp, ...) VL_MT_SAFE {
// includes that otherwise would be required in every Verilated module // includes that otherwise would be required in every Verilated module
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
std::string out = _vl_string_vprintf(formatp, ap); const std::string out = _vl_string_vprintf(formatp, ap);
va_end(ap); va_end(ap);
// printf("-imm-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), // printf("-imm-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(),
// out.c_str()); // out.c_str());
@ -261,7 +261,7 @@ void VL_DBG_MSGF(const char* formatp, ...) VL_MT_SAFE {
void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE { void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
std::string out = _vl_string_vprintf(formatp, ap); const std::string out = _vl_string_vprintf(formatp, ap);
va_end(ap); va_end(ap);
VerilatedThreadMsgQueue::post(VerilatedMsg([=]() { // VerilatedThreadMsgQueue::post(VerilatedMsg([=]() { //
VL_PRINTF("%s", out.c_str()); VL_PRINTF("%s", out.c_str());
@ -301,7 +301,7 @@ vluint64_t vl_rand64() VL_MT_SAFE {
if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1]; if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1];
} }
// Xoroshiro128+ algorithm // Xoroshiro128+ algorithm
vluint64_t result = t_state[0] + t_state[1]; const vluint64_t result = t_state[0] + t_state[1];
t_state[1] ^= t_state[0]; t_state[1] ^= t_state[0];
t_state[0] = (((t_state[0] << 55) | (t_state[0] >> 9)) ^ t_state[1] ^ (t_state[1] << 14)); t_state[0] = (((t_state[0] << 55) | (t_state[0] >> 9)) ^ t_state[1] ^ (t_state[1] << 14));
t_state[1] = (t_state[1] << 36) | (t_state[1] >> 28); t_state[1] = (t_state[1] << 36) | (t_state[1] >> 28);
@ -356,7 +356,7 @@ WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
//=========================================================================== //===========================================================================
// Debug // Debug
void _vl_debug_print_w(int lbits, WDataInP iwp) VL_MT_SAFE { void _vl_debug_print_w(int lbits, const WDataInP iwp) VL_MT_SAFE {
VL_PRINTF_MT(" Data: w%d: ", lbits); VL_PRINTF_MT(" Data: w%d: ", lbits);
for (int i = VL_WORDS_I(lbits) - 1; i >= 0; --i) VL_PRINTF_MT("%08x ", iwp[i]); for (int i = VL_WORDS_I(lbits) - 1; i >= 0; --i) VL_PRINTF_MT("%08x ", iwp[i]);
VL_PRINTF_MT("\n"); VL_PRINTF_MT("\n");
@ -365,24 +365,24 @@ void _vl_debug_print_w(int lbits, WDataInP iwp) VL_MT_SAFE {
//=========================================================================== //===========================================================================
// Slow math // Slow math
WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WDataInP rwp,
bool is_modulus) VL_MT_SAFE { bool is_modulus) VL_MT_SAFE {
// See Knuth Algorithm D. Computes u/v = q.r // See Knuth Algorithm D. Computes u/v = q.r
// This isn't massively tuned, as wide division is rare // This isn't massively tuned, as wide division is rare
// for debug see V3Number version // for debug see V3Number version
// Requires clean input // Requires clean input
int words = VL_WORDS_I(lbits); const int words = VL_WORDS_I(lbits);
for (int i = 0; i < words; ++i) owp[i] = 0; for (int i = 0; i < words; ++i) owp[i] = 0;
// Find MSB and check for zero. // Find MSB and check for zero.
int umsbp1 = VL_MOSTSETBITP1_W(words, lwp); // dividend const int umsbp1 = VL_MOSTSETBITP1_W(words, lwp); // dividend
int vmsbp1 = VL_MOSTSETBITP1_W(words, rwp); // divisor const int vmsbp1 = VL_MOSTSETBITP1_W(words, rwp); // divisor
if (VL_UNLIKELY(vmsbp1 == 0) // rwp==0 so division by zero. Return 0. if (VL_UNLIKELY(vmsbp1 == 0) // rwp==0 so division by zero. Return 0.
|| VL_UNLIKELY(umsbp1 == 0)) { // 0/x so short circuit and return 0 || VL_UNLIKELY(umsbp1 == 0)) { // 0/x so short circuit and return 0
return owp; return owp;
} }
int uw = VL_WORDS_I(umsbp1); // aka "m" in the algorithm const int uw = VL_WORDS_I(umsbp1); // aka "m" in the algorithm
int vw = VL_WORDS_I(vmsbp1); // aka "n" in the algorithm const int vw = VL_WORDS_I(vmsbp1); // aka "n" in the algorithm
if (vw == 1) { // Single divisor word breaks rest of algorithm if (vw == 1) { // Single divisor word breaks rest of algorithm
vluint64_t k = 0; vluint64_t k = 0;
@ -408,8 +408,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
// Algorithm requires divisor MSB to be set // Algorithm requires divisor MSB to be set
// Copy and shift to normalize divisor so MSB of vn[vw-1] is set // Copy and shift to normalize divisor so MSB of vn[vw-1] is set
int s = 31 - VL_BITBIT_I(vmsbp1 - 1); // shift amount (0...31) const int s = 31 - VL_BITBIT_I(vmsbp1 - 1); // shift amount (0...31)
vluint32_t shift_mask = s ? 0xffffffff : 0; // otherwise >> 32 won't mask the value const vluint32_t shift_mask = s ? 0xffffffff : 0; // otherwise >> 32 won't mask the value
for (int i = vw - 1; i > 0; --i) { for (int i = vw - 1; i > 0; --i) {
vn[i] = (rwp[i] << s) | (shift_mask & (rwp[i - 1] >> (32 - s))); vn[i] = (rwp[i] << s) | (shift_mask & (rwp[i - 1] >> (32 - s)));
} }
@ -429,8 +429,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
// Main loop // Main loop
for (int j = uw - vw; j >= 0; --j) { for (int j = uw - vw; j >= 0; --j) {
// Estimate // Estimate
vluint64_t unw64 = (static_cast<vluint64_t>(un[j + vw]) << 32ULL const vluint64_t unw64 = (static_cast<vluint64_t>(un[j + vw]) << 32ULL
| static_cast<vluint64_t>(un[j + vw - 1])); | static_cast<vluint64_t>(un[j + vw - 1]));
vluint64_t qhat = unw64 / static_cast<vluint64_t>(vn[vw - 1]); vluint64_t qhat = unw64 / static_cast<vluint64_t>(vn[vw - 1]);
vluint64_t rhat = unw64 - qhat * static_cast<vluint64_t>(vn[vw - 1]); vluint64_t rhat = unw64 - qhat * static_cast<vluint64_t>(vn[vw - 1]);
@ -478,8 +478,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
} }
} }
WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lwp,
WDataInP rwp) VL_MT_SAFE { const WDataInP rwp) VL_MT_SAFE {
// obits==lbits, rbits can be different // obits==lbits, rbits can be different
owp[0] = 1; owp[0] = 1;
for (int i = 1; i < VL_WORDS_I(obits); i++) owp[i] = 0; for (int i = 1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
@ -501,13 +501,13 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp,
} }
return owp; return owp;
} }
WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, const WDataInP lwp,
QData rhs) VL_MT_SAFE { QData rhs) VL_MT_SAFE {
VlWide<VL_WQ_WORDS_E> rhsw; VlWide<VL_WQ_WORDS_E> rhsw;
VL_SET_WQ(rhsw, rhs); VL_SET_WQ(rhsw, rhs);
return VL_POW_WWW(obits, lbits, rbits, owp, lwp, rhsw); return VL_POW_WWW(obits, lbits, rbits, owp, lwp, rhsw);
} }
QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE { QData VL_POW_QQW(int, int, int rbits, QData lhs, const WDataInP rwp) VL_MT_SAFE {
// Skip check for rhs == 0, as short-circuit doesn't save time // Skip check for rhs == 0, as short-circuit doesn't save time
if (VL_UNLIKELY(lhs == 0)) return 0; if (VL_UNLIKELY(lhs == 0)) return 0;
QData power = lhs; QData power = lhs;
@ -519,11 +519,11 @@ QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE {
return out; return out;
} }
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lwp,
bool lsign, bool rsign) VL_MT_SAFE { const WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE {
// obits==lbits, rbits can be different // obits==lbits, rbits can be different
if (rsign && VL_SIGN_W(rbits, rwp)) { if (rsign && VL_SIGN_W(rbits, rwp)) {
int words = VL_WORDS_I(obits); const int words = VL_WORDS_I(obits);
VL_ZERO_W(obits, owp); VL_ZERO_W(obits, owp);
EData lor = 0; // 0=all zeros, ~0=all ones, else mix EData lor = 0; // 0=all zeros, ~0=all ones, else mix
for (int i = 1; i < (words - 1); ++i) { lor |= lwp[i]; } for (int i = 1; i < (words - 1); ++i) { lor |= lwp[i]; }
@ -545,13 +545,13 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W
} }
return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp); return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
} }
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, const WDataInP lwp,
bool lsign, bool rsign) VL_MT_SAFE { QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
VlWide<VL_WQ_WORDS_E> rhsw; VlWide<VL_WQ_WORDS_E> rhsw;
VL_SET_WQ(rhsw, rhs); VL_SET_WQ(rhsw, rhs);
return VL_POWSS_WWW(obits, lbits, rbits, owp, lwp, rhsw, lsign, rsign); return VL_POWSS_WWW(obits, lbits, rbits, owp, lwp, rhsw, lsign, rsign);
} }
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign, QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, const WDataInP rwp, bool lsign,
bool rsign) VL_MT_SAFE { bool rsign) VL_MT_SAFE {
// Skip check for rhs == 0, as short-circuit doesn't save time // Skip check for rhs == 0, as short-circuit doesn't save time
if (rsign && VL_SIGN_W(rbits, rwp)) { if (rsign && VL_SIGN_W(rbits, rwp)) {
@ -571,23 +571,23 @@ QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsig
return VL_POW_QQW(obits, rbits, rbits, lhs, rwp); return VL_POW_QQW(obits, rbits, rbits, lhs, rwp);
} }
double VL_ITOR_D_W(int lbits, WDataInP lwp) VL_PURE { double VL_ITOR_D_W(int lbits, const WDataInP lwp) VL_PURE {
int ms_word = VL_WORDS_I(lbits) - 1; int ms_word = VL_WORDS_I(lbits) - 1;
for (; !lwp[ms_word] && ms_word > 0;) --ms_word; for (; !lwp[ms_word] && ms_word > 0;) --ms_word;
if (ms_word == 0) return static_cast<double>(lwp[0]); if (ms_word == 0) return static_cast<double>(lwp[0]);
if (ms_word == 1) return static_cast<double>(VL_SET_QW(lwp)); if (ms_word == 1) return static_cast<double>(VL_SET_QW(lwp));
// We need 53 bits of mantissa, which might mean looking at 3 words // We need 53 bits of mantissa, which might mean looking at 3 words
// namely ms_word, ms_word-1 and ms_word-2 // namely ms_word, ms_word-1 and ms_word-2
EData ihi = lwp[ms_word]; const EData ihi = lwp[ms_word];
EData imid = lwp[ms_word - 1]; const EData imid = lwp[ms_word - 1];
EData ilo = lwp[ms_word - 2]; const EData ilo = lwp[ms_word - 2];
double hi = static_cast<double>(ihi) * std::exp2(2 * VL_EDATASIZE); const double hi = static_cast<double>(ihi) * std::exp2(2 * VL_EDATASIZE);
double mid = static_cast<double>(imid) * std::exp2(VL_EDATASIZE); const double mid = static_cast<double>(imid) * std::exp2(VL_EDATASIZE);
double lo = static_cast<double>(ilo); const double lo = static_cast<double>(ilo);
double d = (hi + mid + lo) * std::exp2(VL_EDATASIZE * (ms_word - 2)); const double d = (hi + mid + lo) * std::exp2(VL_EDATASIZE * (ms_word - 2));
return d; return d;
} }
double VL_ISTOR_D_W(int lbits, WDataInP lwp) VL_PURE { double VL_ISTOR_D_W(int lbits, const WDataInP lwp) VL_PURE {
if (!VL_SIGN_W(lbits, lwp)) return VL_ITOR_D_W(lbits, lwp); if (!VL_SIGN_W(lbits, lwp)) return VL_ITOR_D_W(lbits, lwp);
vluint32_t pos[VL_MULS_MAX_WORDS + 1]; // Fixed size, as MSVC++ doesn't allow [words] here vluint32_t pos[VL_MULS_MAX_WORDS + 1]; // Fixed size, as MSVC++ doesn't allow [words] here
VL_NEGATE_W(VL_WORDS_I(lbits), pos, lwp); VL_NEGATE_W(VL_WORDS_I(lbits), pos, lwp);
@ -599,8 +599,8 @@ double VL_ISTOR_D_W(int lbits, WDataInP lwp) VL_PURE {
// Formatting // Formatting
// Output a string representation of a wide number // Output a string representation of a wide number
std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE { std::string VL_DECIMAL_NW(int width, const WDataInP lwp) VL_MT_SAFE {
int maxdecwidth = (width + 3) * 4 / 3; const int maxdecwidth = (width + 3) * 4 / 3;
// Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word // Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word
VlWide<VL_VALUE_STRING_MAX_WIDTH / 4 + 2> bcd; VlWide<VL_VALUE_STRING_MAX_WIDTH / 4 + 2> bcd;
VL_ZERO_RESET_W(maxdecwidth, bcd); VL_ZERO_RESET_W(maxdecwidth, bcd);
@ -652,17 +652,17 @@ std::string _vl_vsformat_time(char* tmp, T ld, int timeunit, bool left, size_t w
WDataInP shifted = VL_EXTEND_WQ(b, 0, tmp0, static_cast<QData>(ld)); WDataInP shifted = VL_EXTEND_WQ(b, 0, tmp0, static_cast<QData>(ld));
if (shift < 0) { if (shift < 0) {
WDataInP pow10 = VL_EXTEND_WQ(b, 0, tmp1, vl_time_pow10(-shift)); const WDataInP pow10 = VL_EXTEND_WQ(b, 0, tmp1, vl_time_pow10(-shift));
shifted = VL_DIV_WWW(b, tmp2, shifted, pow10); shifted = VL_DIV_WWW(b, tmp2, shifted, pow10);
} else { } else {
WDataInP pow10 = VL_EXTEND_WQ(b, 0, tmp1, vl_time_pow10(shift)); const WDataInP pow10 = VL_EXTEND_WQ(b, 0, tmp1, vl_time_pow10(shift));
shifted = VL_MUL_W(w, tmp2, shifted, pow10); shifted = VL_MUL_W(w, tmp2, shifted, pow10);
} }
WDataInP fracDigitsPow10 = VL_EXTEND_WQ(b, 0, tmp3, vl_time_pow10(fracDigits)); const WDataInP fracDigitsPow10 = VL_EXTEND_WQ(b, 0, tmp3, vl_time_pow10(fracDigits));
WDataInP integer = VL_DIV_WWW(b, tmp0, shifted, fracDigitsPow10); const WDataInP integer = VL_DIV_WWW(b, tmp0, shifted, fracDigitsPow10);
WDataInP frac = VL_MODDIV_WWW(b, tmp1, shifted, fracDigitsPow10); const WDataInP frac = VL_MODDIV_WWW(b, tmp1, shifted, fracDigitsPow10);
WDataInP max64Bit const WDataInP max64Bit
= VL_EXTEND_WQ(b, 0, tmp2, std::numeric_limits<vluint64_t>::max()); // breaks shifted = VL_EXTEND_WQ(b, 0, tmp2, std::numeric_limits<vluint64_t>::max()); // breaks shifted
if (VL_GT_W(w, integer, max64Bit)) { if (VL_GT_W(w, integer, max64Bit)) {
WDataOutP v = VL_ASSIGN_W(b, tmp3, integer); // breaks fracDigitsPow10 WDataOutP v = VL_ASSIGN_W(b, tmp3, integer); // breaks fracDigitsPow10
@ -674,7 +674,7 @@ std::string _vl_vsformat_time(char* tmp, T ld, int timeunit, bool left, size_t w
*ptr = '\0'; *ptr = '\0';
while (VL_GT_W(w, v, zero)) { while (VL_GT_W(w, v, zero)) {
--ptr; --ptr;
WDataInP mod = VL_MODDIV_WWW(b, tmp2, v, ten); // breaks max64Bit const WDataInP mod = VL_MODDIV_WWW(b, tmp2, v, ten); // breaks max64Bit
*ptr = "0123456789"[VL_SET_QW(mod)]; *ptr = "0123456789"[VL_SET_QW(mod)];
VlWide<w> divided; VlWide<w> divided;
VL_DIV_WWW(b, divided, v, ten); VL_DIV_WWW(b, divided, v, ten);
@ -801,7 +801,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
case 'g': case 'g':
case '^': { // Realtime case '^': { // Realtime
const int lbits = va_arg(ap, int); const int lbits = va_arg(ap, int);
double d = va_arg(ap, double); const double d = va_arg(ap, double);
if (lbits) {} // UNUSED - always 64 if (lbits) {} // UNUSED - always 64
if (fmt == '^') { // Realtime if (fmt == '^') { // Realtime
if (!widthSet) width = Verilated::threadContextp()->impp()->timeFormatWidth(); if (!widthSet) width = Verilated::threadContextp()->impp()->timeFormatWidth();
@ -834,7 +834,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
} }
switch (fmt) { switch (fmt) {
case 'c': { case 'c': {
IData charval = ld & 0xff; const IData charval = ld & 0xff;
output += static_cast<char>(charval); output += static_cast<char>(charval);
break; break;
} }
@ -842,7 +842,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
std::string field; std::string field;
for (; lsb >= 0; --lsb) { for (; lsb >= 0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit lsb = (lsb / 8) * 8; // Next digit
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff; const IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
field += (charval == 0) ? ' ' : charval; field += (charval == 0) ? ' ' : charval;
} }
std::string padding; std::string padding;
@ -957,7 +957,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
} }
break; break;
default: { // LCOV_EXCL_START default: { // LCOV_EXCL_START
std::string msg = std::string("Unknown _vl_vsformat code: ") + pos[0]; const std::string msg = std::string("Unknown _vl_vsformat code: ") + pos[0];
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str()); VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
break; break;
} // LCOV_EXCL_STOP } // LCOV_EXCL_STOP
@ -982,11 +982,11 @@ static inline void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE {
floc -= 8; floc -= 8;
} }
} }
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, static inline int _vl_vsss_peek(FILE* fp, int& floc, const WDataInP fromp,
const std::string& fstr) VL_MT_SAFE { const std::string& fstr) VL_MT_SAFE {
// Get a character without advancing // Get a character without advancing
if (fp) { if (fp) {
int data = std::fgetc(fp); const int data = std::fgetc(fp);
if (data == EOF) return EOF; if (data == EOF) return EOF;
ungetc(data, fp); ungetc(data, fp);
return data; return data;
@ -1000,16 +1000,17 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp,
} }
} }
} }
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp, static inline void _vl_vsss_skipspace(FILE* fp, int& floc, const WDataInP fromp,
const std::string& fstr) VL_MT_SAFE { const std::string& fstr) VL_MT_SAFE {
while (true) { while (true) {
int c = _vl_vsss_peek(fp, floc, fromp, fstr); const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
if (c == EOF || !std::isspace(c)) return; if (c == EOF || !std::isspace(c)) return;
_vl_vsss_advance(fp, floc); _vl_vsss_advance(fp, floc);
} }
} }
static inline void _vl_vsss_read_str(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr, static inline void _vl_vsss_read_str(FILE* fp, int& floc, const WDataInP fromp,
char* tmpp, const char* acceptp) VL_MT_SAFE { const std::string& fstr, char* tmpp,
const char* acceptp) VL_MT_SAFE {
// Read into tmp, consisting of characters from acceptp list // Read into tmp, consisting of characters from acceptp list
char* cp = tmpp; char* cp = tmpp;
while (true) { while (true) {
@ -1023,8 +1024,9 @@ static inline void _vl_vsss_read_str(FILE* fp, int& floc, WDataInP fromp, const
*cp++ = '\0'; *cp++ = '\0';
// VL_DBG_MSGF(" _read got='"<<tmpp<<"'\n"); // VL_DBG_MSGF(" _read got='"<<tmpp<<"'\n");
} }
static inline char* _vl_vsss_read_bin(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr, static inline char* _vl_vsss_read_bin(FILE* fp, int& floc, const WDataInP fromp,
char* beginp, std::size_t n, bool inhibit = false) { const std::string& fstr, char* beginp, std::size_t n,
bool inhibit = false) {
// Variant of _vl_vsss_read_str using the same underlying I/O functions but optimized // Variant of _vl_vsss_read_str using the same underlying I/O functions but optimized
// specifically for block reads of N bytes (read operations are not demarcated by // specifically for block reads of N bytes (read operations are not demarcated by
// whitespace). In the fp case, except descriptor to have been opened in binary mode. // whitespace). In the fp case, except descriptor to have been opened in binary mode.
@ -1074,7 +1076,7 @@ static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const
} }
IData _vl_vsscanf(FILE* fp, // If a fscanf IData _vl_vsscanf(FILE* fp, // If a fscanf
int fbits, WDataInP fromp, // Else if a sscanf int fbits, const WDataInP fromp, // Else if a sscanf
const std::string& fstr, // if a sscanf to string const std::string& fstr, // if a sscanf to string
const char* formatp, va_list ap) VL_MT_SAFE { const char* formatp, va_list ap) VL_MT_SAFE {
// Read a Verilog $sscanf/$fscanf style format into the output list // Read a Verilog $sscanf/$fscanf style format into the output list
@ -1240,7 +1242,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
break; break;
} }
default: { // LCOV_EXCL_START default: { // LCOV_EXCL_START
std::string msg = std::string("Unknown _vl_vsscanf code: ") + pos[0]; const std::string msg = std::string("Unknown _vl_vsscanf code: ") + pos[0];
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str()); VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
break; break;
} // LCOV_EXCL_STOP } // LCOV_EXCL_STOP
@ -1282,7 +1284,7 @@ FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE {
return Verilated::threadContextp()->impp()->fdToFp(lhs); return Verilated::threadContextp()->impp()->fdToFp(lhs);
} }
void _vl_vint_to_string(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE { void _vl_vint_to_string(int obits, char* destoutp, const WDataInP sourcep) VL_MT_SAFE {
// See also VL_DATA_TO_STRING_NW // See also VL_DATA_TO_STRING_NW
int lsb = obits - 1; int lsb = obits - 1;
bool start = true; bool start = true;
@ -1303,7 +1305,7 @@ void _vl_vint_to_string(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE
void _vl_string_to_vint(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE { void _vl_string_to_vint(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE {
// Convert C string to Verilog format // Convert C string to Verilog format
size_t bytes = VL_BYTES_I(obits); const size_t bytes = VL_BYTES_I(obits);
char* op = reinterpret_cast<char*>(destp); char* op = reinterpret_cast<char*>(destp);
if (srclen > bytes) srclen = bytes; // Don't overflow destination if (srclen > bytes) srclen = bytes; // Don't overflow destination
size_t i = 0; size_t i = 0;
@ -1315,7 +1317,7 @@ static IData getLine(std::string& str, IData fpi, size_t maxLen) VL_MT_SAFE {
str.clear(); str.clear();
// While threadsafe, each thread can only access different file handles // While threadsafe, each thread can only access different file handles
FILE* fp = VL_CVT_I_FP(fpi); FILE* const fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
// We don't use fgets, as we must read \0s. // We don't use fgets, as we must read \0s.
@ -1331,7 +1333,7 @@ static IData getLine(std::string& str, IData fpi, size_t maxLen) VL_MT_SAFE {
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE { IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE {
std::string str; std::string str;
const IData bytes = VL_BYTES_I(obits); const IData bytes = VL_BYTES_I(obits);
IData got = getLine(str, fpi, bytes); const IData got = getLine(str, fpi, bytes);
if (VL_UNLIKELY(str.empty())) return 0; if (VL_UNLIKELY(str.empty())) return 0;
@ -1351,7 +1353,7 @@ IData VL_FGETS_NI(std::string& dest, IData fpi) VL_MT_SAFE {
IData VL_FERROR_IN(IData, std::string& outputr) VL_MT_SAFE { IData VL_FERROR_IN(IData, std::string& outputr) VL_MT_SAFE {
// We ignore lhs/fpi - IEEE says "most recent error" so probably good enough // We ignore lhs/fpi - IEEE says "most recent error" so probably good enough
IData ret = errno; const IData ret = errno;
outputr = std::string(::std::strerror(ret)); outputr = std::string(::std::strerror(ret));
return ret; return ret;
} }
@ -1474,12 +1476,12 @@ void VL_FWRITEF(IData fpi, const char* formatp, ...) VL_MT_SAFE {
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE { IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE {
// While threadsafe, each thread can only access different file handles // While threadsafe, each thread can only access different file handles
FILE* fp = VL_CVT_I_FP(fpi); FILE* const fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
IData got = _vl_vsscanf(fp, 0, nullptr, "", formatp, ap); const IData got = _vl_vsscanf(fp, 0, nullptr, "", formatp, ap);
va_end(ap); va_end(ap);
return got; return got;
} }
@ -1490,7 +1492,7 @@ IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) VL_MT_SAFE {
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
IData got = _vl_vsscanf(nullptr, lbits, fnw, "", formatp, ap); const IData got = _vl_vsscanf(nullptr, lbits, fnw, "", formatp, ap);
va_end(ap); va_end(ap);
return got; return got;
} }
@ -1500,21 +1502,21 @@ IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) VL_MT_SAFE {
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
IData got = _vl_vsscanf(nullptr, lbits, fnw, "", formatp, ap); const IData got = _vl_vsscanf(nullptr, lbits, fnw, "", formatp, ap);
va_end(ap); va_end(ap);
return got; return got;
} }
IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) VL_MT_SAFE { IData VL_SSCANF_IWX(int lbits, const WDataInP lwp, const char* formatp, ...) VL_MT_SAFE {
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
IData got = _vl_vsscanf(nullptr, lbits, lwp, "", formatp, ap); const IData got = _vl_vsscanf(nullptr, lbits, lwp, "", formatp, ap);
va_end(ap); va_end(ap);
return got; return got;
} }
IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_SAFE { IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_SAFE {
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
IData got = _vl_vsscanf(nullptr, ld.length() * 8, nullptr, ld, formatp, ap); const IData got = _vl_vsscanf(nullptr, ld.length() * 8, nullptr, ld, formatp, ap);
va_end(ap); va_end(ap);
return got; return got;
} }
@ -1522,7 +1524,7 @@ IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_
IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi, IData start, IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi, IData start,
IData count) VL_MT_SAFE { IData count) VL_MT_SAFE {
// While threadsafe, each thread can only access different file handles // While threadsafe, each thread can only access different file handles
FILE* fp = VL_CVT_I_FP(fpi); FILE* const fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
if (count > (array_size - (start - array_lsb))) count = array_size - (start - array_lsb); if (count > (array_size - (start - array_lsb))) count = array_size - (start - array_lsb);
// Prep for reading // Prep for reading
@ -1576,10 +1578,10 @@ IData VL_SYSTEM_IQ(QData lhs) VL_MT_SAFE {
VL_SET_WQ(lhsw, lhs); VL_SET_WQ(lhsw, lhs);
return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw); return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw);
} }
IData VL_SYSTEM_IW(int lhswords, WDataInP lhsp) VL_MT_SAFE { IData VL_SYSTEM_IW(int lhswords, const WDataInP lhsp) VL_MT_SAFE {
char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1]; char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
_vl_vint_to_string(lhswords * VL_EDATASIZE, filenamez, lhsp); _vl_vint_to_string(lhswords * VL_EDATASIZE, filenamez, lhsp);
int code = std::system(filenamez); // Yes, std::system() is threadsafe const int code = std::system(filenamez); // Yes, std::system() is threadsafe
return code >> 8; // Want exit status return code >> 8; // Want exit status
} }
@ -1707,7 +1709,7 @@ std::string VL_TO_STRING(CData lhs) { return VL_SFORMATF_NX("'h%0x", 8, lhs); }
std::string VL_TO_STRING(SData lhs) { return VL_SFORMATF_NX("'h%0x", 16, lhs); } std::string VL_TO_STRING(SData lhs) { return VL_SFORMATF_NX("'h%0x", 16, lhs); }
std::string VL_TO_STRING(IData lhs) { return VL_SFORMATF_NX("'h%0x", 32, lhs); } std::string VL_TO_STRING(IData lhs) { return VL_SFORMATF_NX("'h%0x", 32, lhs); }
std::string VL_TO_STRING(QData lhs) { return VL_SFORMATF_NX("'h%0x", 64, lhs); } std::string VL_TO_STRING(QData lhs) { return VL_SFORMATF_NX("'h%0x", 64, lhs); }
std::string VL_TO_STRING_W(int words, WDataInP obj) { std::string VL_TO_STRING_W(int words, const WDataInP obj) {
return VL_SFORMATF_NX("'h%0x", words * VL_EDATASIZE, obj); return VL_SFORMATF_NX("'h%0x", words * VL_EDATASIZE, obj);
} }
@ -1722,7 +1724,7 @@ std::string VL_TOUPPER_NN(const std::string& ld) VL_MT_SAFE {
return out; return out;
} }
std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE { std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_MT_SAFE {
// See also _vl_vint_to_string // See also _vl_vint_to_string
char destout[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1]; char destout[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
int obits = lwords * VL_EDATASIZE; int obits = lwords * VL_EDATASIZE;
@ -1804,7 +1806,7 @@ static const char* formatBinary(int nBits, vluint32_t bits) {
static VL_THREAD_LOCAL char t_buf[64]; static VL_THREAD_LOCAL char t_buf[64];
for (int i = 0; i < nBits; i++) { for (int i = 0; i < nBits; i++) {
bool isOne = bits & (1 << (nBits - 1 - i)); const bool isOne = bits & (1 << (nBits - 1 - i));
t_buf[i] = (isOne ? '1' : '0'); t_buf[i] = (isOne ? '1' : '0');
} }
t_buf[nBits] = '\0'; t_buf[nBits] = '\0';
@ -1885,7 +1887,7 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
// Check for hex or binary digits as file format requests // Check for hex or binary digits as file format requests
else if (std::isxdigit(c) || (!reading_addr && (c == 'x' || c == 'X'))) { else if (std::isxdigit(c) || (!reading_addr && (c == 'x' || c == 'X'))) {
c = std::tolower(c); c = std::tolower(c);
int value const int value
= (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c - 'a' + 10)) : (c - '0')); = (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c - 'a' + 10)) : (c - '0'));
if (reading_addr) { if (reading_addr) {
// Decode @ addresses // Decode @ addresses
@ -1914,12 +1916,13 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
return false; // EOF return false; // EOF
} }
void VlReadMem::setData(void* valuep, const std::string& rhs) { void VlReadMem::setData(void* valuep, const std::string& rhs) {
QData shift = m_hex ? 4ULL : 1ULL; const QData shift = m_hex ? 4ULL : 1ULL;
bool innum = false; bool innum = false;
// Shift value in // Shift value in
for (const auto& i : rhs) { for (const auto& i : rhs) {
char c = std::tolower(i); const char c = std::tolower(i);
int value = (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c - 'a' + 10)) : (c - '0')); const int value
= (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c - 'a' + 10)) : (c - '0'));
if (m_bits <= 8) { if (m_bits <= 8) {
CData* datap = reinterpret_cast<CData*>(valuep); CData* datap = reinterpret_cast<CData*>(valuep);
if (!innum) *datap = 0; if (!innum) *datap = 0;
@ -2001,9 +2004,9 @@ void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
} }
} else if (m_bits <= 64) { } else if (m_bits <= 64) {
const QData* datap = reinterpret_cast<const QData*>(valuep); const QData* datap = reinterpret_cast<const QData*>(valuep);
vluint64_t value = VL_MASK_Q(m_bits) & *datap; const vluint64_t value = VL_MASK_Q(m_bits) & *datap;
vluint32_t lo = value & 0xffffffff; const vluint32_t lo = value & 0xffffffff;
vluint32_t hi = value >> 32; const vluint32_t hi = value >> 32;
if (m_hex) { if (m_hex) {
fprintf(m_fp, memhFormat(m_bits - 32), hi); fprintf(m_fp, memhFormat(m_bits - 32), hi);
fprintf(m_fp, "%08x\n", lo); fprintf(m_fp, "%08x\n", lo);
@ -2012,7 +2015,7 @@ void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
fprintf(m_fp, "%s\n", formatBinary(32, lo)); fprintf(m_fp, "%s\n", formatBinary(32, lo));
} }
} else { } else {
WDataInP datap = reinterpret_cast<WDataInP>(valuep); const WDataInP datap = reinterpret_cast<WDataInP>(valuep);
// output as a sequence of VL_EDATASIZE'd words // output as a sequence of VL_EDATASIZE'd words
// from MSB to LSB. Mask off the MSB word which could // from MSB to LSB. Mask off the MSB word which could
// contain junk above the top of valid data. // contain junk above the top of valid data.
@ -2022,7 +2025,7 @@ void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
EData data = datap[word_idx]; EData data = datap[word_idx];
if (first) { if (first) {
data &= VL_MASK_E(m_bits); data &= VL_MASK_E(m_bits);
int top_word_nbits = VL_BITBIT_E(m_bits - 1) + 1; const int top_word_nbits = VL_BITBIT_E(m_bits - 1) + 1;
if (m_hex) { if (m_hex) {
fprintf(m_fp, memhFormat(top_word_nbits), data); fprintf(m_fp, memhFormat(top_word_nbits), data);
} else { } else {
@ -2108,7 +2111,7 @@ void VL_WRITEMEM_N(bool hex, // Hex format, else binary
if (VL_UNLIKELY(!wmem.isOpen())) return; if (VL_UNLIKELY(!wmem.isOpen())) return;
for (QData addr = start; addr <= end; ++addr) { for (QData addr = start; addr <= end; ++addr) {
QData row_offset = addr - array_lsb; const QData row_offset = addr - array_lsb;
if (bits <= 8) { if (bits <= 8) {
const CData* datap = &(reinterpret_cast<const CData*>(memp))[row_offset]; const CData* datap = &(reinterpret_cast<const CData*>(memp))[row_offset];
wmem.print(addr, false, datap); wmem.print(addr, false, datap);
@ -2122,8 +2125,8 @@ void VL_WRITEMEM_N(bool hex, // Hex format, else binary
const QData* datap = &(reinterpret_cast<const QData*>(memp))[row_offset]; const QData* datap = &(reinterpret_cast<const QData*>(memp))[row_offset];
wmem.print(addr, false, datap); wmem.print(addr, false, datap);
} else { } else {
WDataInP memDatap = reinterpret_cast<WDataInP>(memp); const WDataInP memDatap = reinterpret_cast<WDataInP>(memp);
WDataInP datap = &memDatap[row_offset * VL_WORDS_I(bits)]; const WDataInP datap = &memDatap[row_offset * VL_WORDS_I(bits)];
wmem.print(addr, false, datap); wmem.print(addr, false, datap);
} }
} }
@ -2351,7 +2354,7 @@ void VerilatedContext::timeprecision(int value) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex); const VerilatedLockGuard lock(m_mutex);
m_s.m_timeprecision = value; m_s.m_timeprecision = value;
#ifdef SYSTEMC_VERSION #ifdef SYSTEMC_VERSION
sc_time sc_res = sc_get_time_resolution(); const sc_time sc_res = sc_get_time_resolution();
int sc_prec = 99; int sc_prec = 99;
if (sc_res == sc_time(1, SC_SEC)) { if (sc_res == sc_time(1, SC_SEC)) {
sc_prec = 0; sc_prec = 0;
@ -2373,7 +2376,7 @@ void VerilatedContext::timeprecision(int value) VL_MT_SAFE {
<< ". Suggest use 'sc_set_time_resolution(" << vl_time_str(value) << ". Suggest use 'sc_set_time_resolution(" << vl_time_str(value)
<< ")', or Verilator '--timescale-override " << vl_time_str(sc_prec) << "/" << ")', or Verilator '--timescale-override " << vl_time_str(sc_prec) << "/"
<< vl_time_str(sc_prec) << "'"; << vl_time_str(sc_prec) << "'";
std::string msgs = msg.str(); const std::string msgs = msg.str();
VL_FATAL_MT("", 0, "", msgs.c_str()); VL_FATAL_MT("", 0, "", msgs.c_str());
} }
#endif #endif
@ -2434,7 +2437,7 @@ std::string VerilatedContextImp::argPlusMatch(const char* prefixp)
VL_MT_SAFE_EXCLUDES(m_argMutex) { VL_MT_SAFE_EXCLUDES(m_argMutex) {
const VerilatedLockGuard lock(m_argMutex); const VerilatedLockGuard lock(m_argMutex);
// Note prefixp does not include the leading "+" // Note prefixp does not include the leading "+"
size_t len = std::strlen(prefixp); const size_t len = std::strlen(prefixp);
if (VL_UNLIKELY(!m_args.m_argVecLoaded)) { if (VL_UNLIKELY(!m_args.m_argVecLoaded)) {
m_args.m_argVecLoaded = true; // Complain only once m_args.m_argVecLoaded = true; // Complain only once
VL_FATAL_MT("unknown", 0, "", VL_FATAL_MT("unknown", 0, "",
@ -2511,7 +2514,7 @@ void VerilatedContextImp::commandArgVl(const std::string& arg) {
} }
bool VerilatedContextImp::commandArgVlValue(const std::string& arg, const std::string& prefix, bool VerilatedContextImp::commandArgVlValue(const std::string& arg, const std::string& prefix,
std::string& valuer) { std::string& valuer) {
size_t len = prefix.length(); const size_t len = prefix.length();
if (0 == std::strncmp(prefix.c_str(), arg.c_str(), len)) { if (0 == std::strncmp(prefix.c_str(), arg.c_str(), len)) {
valuer = arg.substr(len); valuer = arg.substr(len);
return true; return true;
@ -2528,7 +2531,7 @@ void VerilatedContext::randSeed(int val) VL_MT_SAFE {
// and so the rand seed's mutex must also be static // and so the rand seed's mutex must also be static
const VerilatedLockGuard lock(VerilatedContextImp::s().s_randMutex); const VerilatedLockGuard lock(VerilatedContextImp::s().s_randMutex);
m_s.m_randSeed = val; m_s.m_randSeed = val;
vluint64_t newEpoch = VerilatedContextImp::s().s_randSeedEpoch + 1; const vluint64_t newEpoch = VerilatedContextImp::s().s_randSeedEpoch + 1;
// Obververs must see new epoch AFTER seed updated // Obververs must see new epoch AFTER seed updated
#ifdef VL_THREADED #ifdef VL_THREADED
std::atomic_signal_fence(std::memory_order_release); std::atomic_signal_fence(std::memory_order_release);
@ -2623,7 +2626,7 @@ const char* Verilated::catName(const char* n1, const char* n2, int scopet,
// Used by symbol table creation to make module names // Used by symbol table creation to make module names
static VL_THREAD_LOCAL char* t_strp = nullptr; static VL_THREAD_LOCAL char* t_strp = nullptr;
static VL_THREAD_LOCAL size_t t_len = 0; static VL_THREAD_LOCAL size_t t_len = 0;
size_t newlen const size_t newlen
= std::strlen(n1) + std::strlen(n2) + std::strlen(delimiter) + (scopet > 0 ? 2 : 1); = std::strlen(n1) + std::strlen(n2) + std::strlen(delimiter) + (scopet > 0 ? 2 : 1);
if (VL_UNLIKELY(!t_strp || newlen > t_len)) { if (VL_UNLIKELY(!t_strp || newlen > t_len)) {
if (t_strp) delete[] t_strp; if (t_strp) delete[] t_strp;
@ -2726,8 +2729,8 @@ void Verilated::nullPointerError(const char* filename, int linenum) VL_MT_SAFE {
void Verilated::overWidthError(const char* signame) VL_MT_SAFE { void Verilated::overWidthError(const char* signame) VL_MT_SAFE {
// Slowpath - Called only when signal sets too high of a bit // Slowpath - Called only when signal sets too high of a bit
std::string msg = (std::string("Testbench C set input '") + signame const std::string msg = (std::string("Testbench C set input '") + signame
+ "' to value that overflows what the signal's width can fit"); + "' to value that overflows what the signal's width can fit");
VL_FATAL_MT("unknown", 0, "", msg.c_str()); VL_FATAL_MT("unknown", 0, "", msg.c_str());
VL_UNREACHABLE VL_UNREACHABLE
} }
@ -2889,8 +2892,8 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap, boo
va_list ap; va_list ap;
va_start(ap, dims); va_start(ap, dims);
for (int i = 0; i < dims; ++i) { for (int i = 0; i < dims; ++i) {
int msb = va_arg(ap, int); const int msb = va_arg(ap, int);
int lsb = va_arg(ap, int); const int lsb = va_arg(ap, int);
if (i == 0) { if (i == 0) {
var.m_packed.m_left = msb; var.m_packed.m_left = msb;
var.m_packed.m_right = lsb; var.m_packed.m_right = lsb;
@ -2921,18 +2924,20 @@ VerilatedVar* VerilatedScope::varFind(const char* namep) const VL_MT_SAFE_POSTIN
void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE { void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE {
// Slowpath - Called only when find has failed // Slowpath - Called only when find has failed
std::string msg = (std::string("Testbench C called '") + VerilatedImp::exportName(funcnum) const std::string msg
+ "' but scope wasn't set, perhaps due to dpi import call without " = (std::string("Testbench C called '") + VerilatedImp::exportName(funcnum)
+ "'context', or missing svSetScope. See IEEE 1800-2017 35.5.3."); + "' but scope wasn't set, perhaps due to dpi import call without "
+ "'context', or missing svSetScope. See IEEE 1800-2017 35.5.3.");
VL_FATAL_MT("unknown", 0, "", msg.c_str()); VL_FATAL_MT("unknown", 0, "", msg.c_str());
return nullptr; return nullptr;
} }
void* VerilatedScope::exportFindError(int funcnum) const { void* VerilatedScope::exportFindError(int funcnum) const {
// Slowpath - Called only when find has failed // Slowpath - Called only when find has failed
std::string msg = (std::string("Testbench C called '") + VerilatedImp::exportName(funcnum) const std::string msg
+ "' but this DPI export function exists only in other scopes, not scope '" = (std::string("Testbench C called '") + VerilatedImp::exportName(funcnum)
+ name() + "'"); + "' but this DPI export function exists only in other scopes, not scope '" + name()
+ "'");
VL_FATAL_MT("unknown", 0, "", msg.c_str()); VL_FATAL_MT("unknown", 0, "", msg.c_str());
return nullptr; return nullptr;
} }

File diff suppressed because it is too large Load Diff

View File

@ -193,7 +193,7 @@ private:
// We used to backup and split on only .'s but it seems better to be verbose // We used to backup and split on only .'s but it seems better to be verbose
// and not assume . is the separator // and not assume . is the separator
std::string prefix = std::string(a, apre - a); const std::string prefix = std::string(a, apre - a);
// Scan backward to last mismatch // Scan backward to last mismatch
const char* apost = a + std::strlen(a) - 1; const char* apost = a + std::strlen(a) - 1;
@ -251,7 +251,7 @@ private:
public: public:
// PUBLIC METHODS // PUBLIC METHODS
void forcePerInstance(bool flag) VL_MT_SAFE_EXCLUDES(m_mutex) { void forcePerInstance(const bool flag) VL_MT_SAFE_EXCLUDES(m_mutex) {
Verilated::quiesce(); Verilated::quiesce();
const VerilatedLockGuard lock(m_mutex); const VerilatedLockGuard lock(m_mutex);
m_forcePerInstance = flag; m_forcePerInstance = flag;
@ -261,7 +261,7 @@ public:
const VerilatedLockGuard lock(m_mutex); const VerilatedLockGuard lock(m_mutex);
clearGuts(); clearGuts();
} }
void clearNonMatch(const char* matchp) VL_MT_SAFE_EXCLUDES(m_mutex) { void clearNonMatch(const char* const matchp) VL_MT_SAFE_EXCLUDES(m_mutex) {
Verilated::quiesce(); Verilated::quiesce();
const VerilatedLockGuard lock(m_mutex); const VerilatedLockGuard lock(m_mutex);
if (matchp && matchp[0]) { if (matchp && matchp[0]) {
@ -288,7 +288,7 @@ public:
assert(!m_insertp); assert(!m_insertp);
m_insertp = itemp; m_insertp = itemp;
} }
void insertf(const char* filenamep, int lineno) VL_MT_SAFE_EXCLUDES(m_mutex) { void insertf(const char* const filenamep, const int lineno) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex); const VerilatedLockGuard lock(m_mutex);
m_insertFilenamep = filenamep; m_insertFilenamep = filenamep;
m_insertLineno = lineno; m_insertLineno = lineno;

View File

@ -79,19 +79,19 @@ void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) {
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width) { void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width) {
// See also VL_SEL_WWI // See also VL_SEL_WWI
int msb = lsb + width - 1; const int msb = lsb + width - 1;
int word_shift = VL_BITWORD_I(lsb); const int word_shift = VL_BITWORD_I(lsb);
if (VL_BITBIT_I(lsb) == 0) { if (VL_BITBIT_I(lsb) == 0) {
// Just a word extract // Just a word extract
for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift]; for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift];
} else { } else {
int loffset = lsb & VL_SIZEBITS_I; const int loffset = lsb & VL_SIZEBITS_I;
int nbitsfromlow = 32 - loffset; // bits that end up in lword (know loffset!=0) const int nbitsfromlow = 32 - loffset; // bits that end up in lword (know loffset!=0)
// Middle words // Middle words
int words = VL_WORDS_I(msb - lsb + 1); const int words = VL_WORDS_I(msb - lsb + 1);
for (int i = 0; i < words; ++i) { for (int i = 0; i < words; ++i) {
dp[i] = sp[i + word_shift] >> loffset; dp[i] = sp[i + word_shift] >> loffset;
int upperword = i + word_shift + 1; const int upperword = i + word_shift + 1;
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) { if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
dp[i] |= sp[upperword] << nbitsfromlow; dp[i] |= sp[upperword] << nbitsfromlow;
} }
@ -101,20 +101,20 @@ void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width)
dp[VL_WORDS_I(width) - 1] &= VL_MASK_I(width); dp[VL_WORDS_I(width) - 1] &= VL_MASK_I(width);
} }
void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int width) { void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int width) {
int msb = lsb + width - 1; const int msb = lsb + width - 1;
int word_shift = VL_BITWORD_I(lsb); const int word_shift = VL_BITWORD_I(lsb);
if (VL_BITBIT_I(lsb) == 0) { if (VL_BITBIT_I(lsb) == 0) {
// Just a word extract // Just a word extract
for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift]; for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift];
} else { } else {
int loffset = lsb & VL_SIZEBITS_I; const int loffset = lsb & VL_SIZEBITS_I;
int nbitsfromlow = 32 - loffset; // bits that end up in lword (know loffset!=0) const int nbitsfromlow = 32 - loffset; // bits that end up in lword (know loffset!=0)
// Middle words // Middle words
int words = VL_WORDS_I(msb - lsb + 1); const int words = VL_WORDS_I(msb - lsb + 1);
for (int i = 0; i < words; ++i) { for (int i = 0; i < words; ++i) {
dp[i].aval = sp[i + word_shift].aval >> loffset; dp[i].aval = sp[i + word_shift].aval >> loffset;
dp[i].bval = sp[i + word_shift].bval >> loffset; dp[i].bval = sp[i + word_shift].bval >> loffset;
int upperword = i + word_shift + 1; const int upperword = i + word_shift + 1;
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) { if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
dp[i].aval |= sp[upperword].aval << nbitsfromlow; dp[i].aval |= sp[upperword].aval << nbitsfromlow;
dp[i].bval |= sp[upperword].bval << nbitsfromlow; dp[i].bval |= sp[upperword].bval << nbitsfromlow;
@ -127,22 +127,22 @@ void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int
} }
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) { void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) {
// See also _vl_insert_WI // See also _vl_insert_WI
int hbit = lbit + width - 1; const int hbit = lbit + width - 1;
int hoffset = VL_BITBIT_I(hbit); const int hoffset = VL_BITBIT_I(hbit);
int loffset = VL_BITBIT_I(lbit); const int loffset = VL_BITBIT_I(lbit);
if (hoffset == VL_SIZEBITS_I && loffset == 0) { if (hoffset == VL_SIZEBITS_I && loffset == 0) {
// Fast and common case, word based insertion // Fast and common case, word based insertion
dp[VL_BITWORD_I(lbit)] = s; dp[VL_BITWORD_I(lbit)] = s;
} else { } else {
int hword = VL_BITWORD_I(hbit); const int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit); const int lword = VL_BITWORD_I(lbit);
if (hword == lword) { // know < 32 bits because above checks it if (hword == lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset; const IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset;
dp[lword] = (dp[lword] & ~insmask) | ((s << loffset) & insmask); dp[lword] = (dp[lword] & ~insmask) | ((s << loffset) & insmask);
} else { } else {
IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0; const IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0;
IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset; const IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset;
int nbitsonright = 32 - loffset; // bits that end up in lword const int nbitsonright = 32 - loffset; // bits that end up in lword
dp[lword] = (dp[lword] & ~linsmask) | ((s << loffset) & linsmask); dp[lword] = (dp[lword] & ~linsmask) | ((s << loffset) & linsmask);
dp[hword] = (dp[hword] & ~hinsmask) | ((s >> nbitsonright) & hinsmask); dp[hword] = (dp[hword] & ~hinsmask) | ((s >> nbitsonright) & hinsmask);
} }
@ -150,24 +150,24 @@ void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width)
} }
// cppcheck-suppress passedByValue // cppcheck-suppress passedByValue
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int width) { void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int width) {
int hbit = lbit + width - 1; const int hbit = lbit + width - 1;
int hoffset = VL_BITBIT_I(hbit); const int hoffset = VL_BITBIT_I(hbit);
int loffset = VL_BITBIT_I(lbit); const int loffset = VL_BITBIT_I(lbit);
if (hoffset == VL_SIZEBITS_I && loffset == 0) { if (hoffset == VL_SIZEBITS_I && loffset == 0) {
// Fast and common case, word based insertion // Fast and common case, word based insertion
dp[VL_BITWORD_I(lbit)].aval = s.aval; dp[VL_BITWORD_I(lbit)].aval = s.aval;
dp[VL_BITWORD_I(lbit)].bval = s.bval; dp[VL_BITWORD_I(lbit)].bval = s.bval;
} else { } else {
int hword = VL_BITWORD_I(hbit); const int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit); const int lword = VL_BITWORD_I(lbit);
if (hword == lword) { // know < 32 bits because above checks it if (hword == lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset; const IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset;
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval << loffset) & insmask); dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval << loffset) & insmask);
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval << loffset) & insmask); dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval << loffset) & insmask);
} else { } else {
IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0; const IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0;
IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset; const IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset;
int nbitsonright = 32 - loffset; // bits that end up in lword const int nbitsonright = 32 - loffset; // bits that end up in lword
dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval << loffset) & linsmask); dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval << loffset) & linsmask);
dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval << loffset) & linsmask); dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval << loffset) & linsmask);
dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval >> nbitsonright) & hinsmask); dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval >> nbitsonright) & hinsmask);
@ -460,13 +460,13 @@ void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0); break; case 1: _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { case 2: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0); _vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
break; break;
} }
case 3: { case 3: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int); const int indx3 = va_arg(ap, int);
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); _vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
break; break;
} }
@ -492,13 +492,13 @@ void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break; case 1: _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { case 2: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); _vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
break; break;
} }
case 3: { case 3: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int); const int indx3 = va_arg(ap, int);
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); _vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
break; break;
} }
@ -528,13 +528,13 @@ void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1,
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0); break; case 1: _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { case 2: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0); _vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
break; break;
} }
case 3: { case 3: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int); const int indx3 = va_arg(ap, int);
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); _vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
break; break;
} }
@ -559,13 +559,13 @@ void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int in
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break; case 1: _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { case 2: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); _vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
break; break;
} }
case 3: { case 3: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int); const int indx3 = va_arg(ap, int);
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); _vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
break; break;
} }
@ -592,13 +592,13 @@ svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) {
switch (varp->udims()) { switch (varp->udims()) {
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break; case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
case 2: { case 2: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
break; break;
} }
case 3: { case 3: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int); const int indx3 = va_arg(ap, int);
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
break; break;
} }
@ -625,13 +625,13 @@ svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) {
switch (varp->udims()) { switch (varp->udims()) {
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break; case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
case 2: { case 2: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
break; break;
} }
case 3: { case 3: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int); const int indx3 = va_arg(ap, int);
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
break; break;
} }
@ -660,13 +660,13 @@ void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) {
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break; case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
case 2: { case 2: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); _vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
break; break;
} }
case 3: { case 3: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int); const int indx3 = va_arg(ap, int);
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); _vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
break; break;
} }
@ -691,13 +691,13 @@ void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...)
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break; case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
case 2: { case 2: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); _vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
break; break;
} }
case 3: { case 3: {
int indx2 = va_arg(ap, int); const int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int); const int indx3 = va_arg(ap, int);
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); _vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
break; break;
} }

View File

@ -38,7 +38,7 @@
// Convert svBitVecVal to Verilator internal data // Convert svBitVecVal to Verilator internal data
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, const svBitVecVal* lwp) VL_MT_SAFE { static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, const svBitVecVal* lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); const int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i]; for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i];
owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits); owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits);
} }
@ -48,20 +48,20 @@ static inline QData VL_SET_Q_SVBV(const svBitVecVal* lwp) VL_MT_SAFE {
static inline IData VL_SET_I_SVBV(const svBitVecVal* lwp) VL_MT_SAFE { return lwp[0]; } static inline IData VL_SET_I_SVBV(const svBitVecVal* lwp) VL_MT_SAFE { return lwp[0]; }
// Convert Verilator internal data to svBitVecVal // Convert Verilator internal data to svBitVecVal
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) VL_MT_SAFE { static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, const WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); const int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i]; for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i];
owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits); owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits);
} }
static inline void VL_SET_SVBV_I(int, svBitVecVal* owp, IData ld) VL_MT_SAFE { owp[0] = ld; } static inline void VL_SET_SVBV_I(int, svBitVecVal* owp, const IData ld) VL_MT_SAFE { owp[0] = ld; }
static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, QData ld) VL_MT_SAFE { static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, const QData ld) VL_MT_SAFE {
VL_SET_WQ(owp, ld); VL_SET_WQ(owp, ld);
} }
// Convert svLogicVecVal to Verilator internal data // Convert svLogicVecVal to Verilator internal data
// Note these functions ignore X/Z in svLogicVecVal // Note these functions ignore X/Z in svLogicVecVal
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, const svLogicVecVal* lwp) VL_MT_SAFE { static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, const svLogicVecVal* lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); const int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i].aval; for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i].aval;
owp[words - 1] = lwp[words - 1].aval & VL_MASK_I(obits); owp[words - 1] = lwp[words - 1].aval & VL_MASK_I(obits);
} }
@ -72,17 +72,17 @@ static inline IData VL_SET_I_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE { return
// Convert Verilator internal data to svLogicVecVal // Convert Verilator internal data to svLogicVecVal
// Note these functions never create X/Z in svLogicVecVal // Note these functions never create X/Z in svLogicVecVal
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) VL_MT_SAFE { static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, const WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); const int words = VL_WORDS_I(obits);
for (int i = 0; i < words; ++i) owp[i].bval = 0; for (int i = 0; i < words; ++i) owp[i].bval = 0;
for (int i = 0; i < words - 1; ++i) owp[i].aval = lwp[i]; for (int i = 0; i < words - 1; ++i) owp[i].aval = lwp[i];
owp[words - 1].aval = lwp[words - 1] & VL_MASK_I(obits); owp[words - 1].aval = lwp[words - 1] & VL_MASK_I(obits);
} }
static inline void VL_SET_SVLV_I(int, svLogicVecVal* owp, IData ld) VL_MT_SAFE { static inline void VL_SET_SVLV_I(int, svLogicVecVal* owp, const IData ld) VL_MT_SAFE {
owp[0].aval = ld; owp[0].aval = ld;
owp[0].bval = 0; owp[0].bval = 0;
} }
static inline void VL_SET_SVLV_Q(int, svLogicVecVal* owp, QData ld) VL_MT_SAFE { static inline void VL_SET_SVLV_Q(int, svLogicVecVal* owp, const QData ld) VL_MT_SAFE {
VlWide<2> lwp; VlWide<2> lwp;
VL_SET_WQ(lwp, ld); VL_SET_WQ(lwp, ld);
owp[0].aval = lwp[0]; owp[0].aval = lwp[0];

View File

@ -150,7 +150,7 @@ void VerilatedFst::emitTimeChange(vluint64_t timeui) { fstWriterEmitTimeChange(m
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, const char** itemNamesp, unsigned int minValbits, const char** itemNamesp,
const char** itemValuesp) { const char** itemValuesp) {
fstEnumHandle enumNum const fstEnumHandle enumNum
= fstWriterCreateEnumTable(m_fst, name, elements, minValbits, itemNamesp, itemValuesp); = fstWriterCreateEnumTable(m_fst, name, elements, minValbits, itemNamesp, itemValuesp);
m_local2fstdtype[dtypenum] = enumNum; m_local2fstdtype[dtypenum] = enumNum;
} }
@ -206,7 +206,7 @@ void VerilatedFst::declare(vluint32_t code, const char* name, int dtypenum, fstV
std::string name_str = name_ss.str(); std::string name_str = name_ss.str();
if (dtypenum > 0) { if (dtypenum > 0) {
fstEnumHandle enumNum = m_local2fstdtype[dtypenum]; const fstEnumHandle enumNum = m_local2fstdtype[dtypenum];
fstWriterEmitEnumTableRef(m_fst, enumNum); fstWriterEmitEnumTableRef(m_fst, enumNum);
} }

View File

@ -42,9 +42,9 @@ public:
// We want to avoid a depreciated warning, but still be back compatible. // We want to avoid a depreciated warning, but still be back compatible.
// Turning off the message just for this still results in an // Turning off the message just for this still results in an
// annoying "to turn off" message. // annoying "to turn off" message.
sc_time t1sec(1, SC_SEC); const sc_time t1sec(1, SC_SEC);
if (t1sec.to_default_time_units() != 0) { if (t1sec.to_default_time_units() != 0) {
sc_time tunits(1.0 / t1sec.to_default_time_units(), SC_SEC); const sc_time tunits(1.0 / t1sec.to_default_time_units(), SC_SEC);
spTrace()->set_time_unit(tunits.to_string()); spTrace()->set_time_unit(tunits.to_string());
} }
spTrace()->set_time_resolution(sc_get_time_resolution().to_string()); spTrace()->set_time_resolution(sc_get_time_resolution().to_string());

View File

@ -43,7 +43,7 @@ extern std::string VL_TO_STRING(SData lhs);
extern std::string VL_TO_STRING(IData lhs); extern std::string VL_TO_STRING(IData lhs);
extern std::string VL_TO_STRING(QData lhs); extern std::string VL_TO_STRING(QData lhs);
inline std::string VL_TO_STRING(const std::string& obj) { return "\"" + obj + "\""; } inline std::string VL_TO_STRING(const std::string& obj) { return "\"" + obj + "\""; }
extern std::string VL_TO_STRING_W(int words, WDataInP obj); extern std::string VL_TO_STRING_W(int words, const WDataInP obj);
//=================================================================== //===================================================================
// Shuffle RNG // Shuffle RNG
@ -131,7 +131,8 @@ template <std::size_t T_Words> struct VlWide final {
// Convert a C array to std::array reference by pointer magic, without copy. // Convert a C array to std::array reference by pointer magic, without copy.
// Data type (second argument) is so the function template can automatically generate. // Data type (second argument) is so the function template can automatically generate.
template <std::size_t T_Words> VlWide<T_Words>& VL_CVT_W_A(WDataInP inp, const VlWide<T_Words>&) { template <std::size_t T_Words>
VlWide<T_Words>& VL_CVT_W_A(const WDataInP inp, const VlWide<T_Words>&) {
return *((VlWide<T_Words>*)inp); return *((VlWide<T_Words>*)inp);
} }
@ -795,7 +796,7 @@ void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename,
VlWriteMem wmem(hex, bits, filename, start, end); VlWriteMem wmem(hex, bits, filename, start, end);
if (VL_UNLIKELY(!wmem.isOpen())) return; if (VL_UNLIKELY(!wmem.isOpen())) return;
for (const auto& i : obj) { for (const auto& i : obj) {
QData addr = i.first; const QData addr = i.first;
if (addr >= start && addr <= end) wmem.print(addr, true, &(i.second)); if (addr >= start && addr <= end) wmem.print(addr, true, &(i.second));
} }
} }
@ -876,7 +877,7 @@ static inline bool VL_CAST_DYNAMIC(VlClassRef<T> in, VlClassRef<U>& outr) {
//====================================================================== //======================================================================
// Conversion functions // Conversion functions
extern std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE; extern std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_MT_SAFE;
inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE { inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE {
VlWide<VL_WQ_WORDS_E> lw; VlWide<VL_WQ_WORDS_E> lw;
VL_SET_WQ(lw, lhs); VL_SET_WQ(lw, lhs);

View File

@ -72,9 +72,10 @@ bool VerilatedDeserialize::readDiffers(const void* __restrict datap,
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(); const std::string fn = filename();
std::string msg = "Can't deserialize save-restore file as was made from different model: " const 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());
// Die before we close() as close would infinite loop // Die before we close() as close would infinite loop
} }
@ -90,8 +91,8 @@ void VerilatedSerialize::header() VL_MT_UNSAFE_ONE {
void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE { 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, std::strlen(VLTSAVE_HEADER_STR)))) { if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, std::strlen(VLTSAVE_HEADER_STR)))) {
std::string fn = filename(); const std::string fn = filename();
std::string msg const std::string msg
= std::string( = std::string(
"Can't deserialize; file has wrong header signature, or file not found: ") "Can't deserialize; file has wrong header signature, or file not found: ")
+ filename(); + filename();
@ -109,9 +110,10 @@ void VerilatedSerialize::trailer() VL_MT_UNSAFE_ONE {
void VerilatedDeserialize::trailer() VL_MT_UNSAFE_ONE { void VerilatedDeserialize::trailer() 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_TRAILER_STR, std::strlen(VLTSAVE_TRAILER_STR)))) { if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, std::strlen(VLTSAVE_TRAILER_STR)))) {
std::string fn = filename(); const std::string fn = filename();
std::string msg = std::string("Can't deserialize; file has wrong end-of-file signature: ") const std::string msg
+ filename(); = std::string("Can't deserialize; file has wrong end-of-file signature: ")
+ filename();
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str()); VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
// Die before we close() as close would infinite loop // Die before we close() as close would infinite loop
} }
@ -192,10 +194,10 @@ void VerilatedSave::flush() VL_MT_UNSAFE_ONE {
if (VL_UNLIKELY(!isOpen())) return; if (VL_UNLIKELY(!isOpen())) return;
vluint8_t* wp = m_bufp; vluint8_t* wp = m_bufp;
while (true) { while (true) {
ssize_t remaining = (m_cp - wp); const 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); const ssize_t got = ::write(m_fd, wp, remaining);
if (got > 0) { if (got > 0) {
wp += got; wp += got;
} else if (VL_UNCOVERABLE(got < 0)) { } else if (VL_UNCOVERABLE(got < 0)) {
@ -223,17 +225,17 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
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); const 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); const ssize_t got = ::read(m_fd, m_endp, remaining);
if (got > 0) { if (got > 0) {
m_endp += got; m_endp += got;
} else if (VL_UNCOVERABLE(got < 0)) { } else if (VL_UNCOVERABLE(got < 0)) {
if (VL_UNCOVERABLE(errno != EAGAIN && errno != EINTR)) { if (VL_UNCOVERABLE(errno != EAGAIN && errno != EINTR)) {
// LCOV_EXCL_START // LCOV_EXCL_START
// write failed, presume error (perhaps out of disk space) // write failed, presume error (perhaps out of disk space)
std::string msg = std::string(__FUNCTION__) + ": " + std::strerror(errno); const std::string msg = std::string(__FUNCTION__) + ": " + std::strerror(errno);
VL_FATAL_MT("", 0, "", msg.c_str()); VL_FATAL_MT("", 0, "", msg.c_str());
close(); close();
break; break;

View File

@ -236,43 +236,43 @@ public:
//============================================================================= //=============================================================================
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint64_t& rhs) { inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const vluint64_t& rhs) {
return os.write(&rhs, sizeof(rhs)); return os.write(&rhs, sizeof(rhs));
} }
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint64_t& rhs) { inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint64_t& rhs) {
return os.read(&rhs, sizeof(rhs)); return os.read(&rhs, sizeof(rhs));
} }
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint32_t& rhs) { inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const vluint32_t& rhs) {
return os.write(&rhs, sizeof(rhs)); return os.write(&rhs, sizeof(rhs));
} }
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint32_t& rhs) { inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint32_t& rhs) {
return os.read(&rhs, sizeof(rhs)); return os.read(&rhs, sizeof(rhs));
} }
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint16_t& rhs) { inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const vluint16_t& rhs) {
return os.write(&rhs, sizeof(rhs)); return os.write(&rhs, sizeof(rhs));
} }
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint16_t& rhs) { inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint16_t& rhs) {
return os.read(&rhs, sizeof(rhs)); return os.read(&rhs, sizeof(rhs));
} }
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint8_t& rhs) { inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const vluint8_t& rhs) {
return os.write(&rhs, sizeof(rhs)); return os.write(&rhs, sizeof(rhs));
} }
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint8_t& rhs) { inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint8_t& rhs) {
return os.read(&rhs, sizeof(rhs)); return os.read(&rhs, sizeof(rhs));
} }
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, bool& rhs) { inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const bool& rhs) {
return os.write(&rhs, sizeof(rhs)); return os.write(&rhs, sizeof(rhs));
} }
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, bool& rhs) { inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, bool& rhs) {
return os.read(&rhs, sizeof(rhs)); return os.read(&rhs, sizeof(rhs));
} }
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, double& rhs) { inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const double& rhs) {
return os.write(&rhs, sizeof(rhs)); return os.write(&rhs, sizeof(rhs));
} }
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, double& rhs) { inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, double& rhs) {
return os.read(&rhs, sizeof(rhs)); return os.read(&rhs, sizeof(rhs));
} }
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, float& rhs) { inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const float& rhs) {
return os.write(&rhs, sizeof(rhs)); return os.write(&rhs, sizeof(rhs));
} }
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) { inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
@ -295,11 +295,11 @@ VerilatedDeserialize& operator>>(VerilatedDeserialize& os, VerilatedContext* rhs
template <class T_Key, class T_Value> template <class T_Key, class T_Value>
VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray<T_Key, T_Value>& rhs) { VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray<T_Key, T_Value>& rhs) {
os << rhs.atDefault(); os << rhs.atDefault();
vluint32_t len = rhs.size(); const vluint32_t len = rhs.size();
os << len; os << len;
for (const auto& i : rhs) { for (const auto& i : rhs) {
T_Key index = i.first; // Copy to get around const_iterator const T_Key index = i.first; // Copy to get around const_iterator
T_Value value = i.second; const T_Value value = i.second;
os << index << value; os << index << value;
} }
return os; return os;

View File

@ -93,7 +93,7 @@ void VlWorkerThread::startWorker(VlWorkerThread* workerp) {
VlThreadPool::VlThreadPool(VerilatedContext* contextp, int nThreads, bool profiling) VlThreadPool::VlThreadPool(VerilatedContext* contextp, 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(); const 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++) {
@ -149,7 +149,7 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed)
const VerilatedLockGuard lk(m_mutex); const VerilatedLockGuard lk(m_mutex);
VL_DEBUG_IF(VL_DBG_MSGF("+prof+threads writing to '%s'\n", filenamep);); VL_DEBUG_IF(VL_DBG_MSGF("+prof+threads writing to '%s'\n", filenamep););
FILE* fp = std::fopen(filenamep, "w"); FILE* const fp = std::fopen(filenamep, "w");
if (VL_UNLIKELY(!fp)) { if (VL_UNLIKELY(!fp)) {
VL_FATAL_MT(filenamep, 0, "", "+prof+threads+file file not writable"); VL_FATAL_MT(filenamep, 0, "", "+prof+threads+file file not writable");
// cppcheck-suppress resourceLeak // bug, doesn't realize fp is nullptr // cppcheck-suppress resourceLeak // bug, doesn't realize fp is nullptr

View File

@ -99,19 +99,19 @@ public:
// false while it's still waiting on more dependencies. // false while it's still waiting on more dependencies.
inline bool signalUpstreamDone(bool evenCycle) { inline bool signalUpstreamDone(bool evenCycle) {
if (evenCycle) { if (evenCycle) {
vluint32_t upstreamDepsDone const vluint32_t upstreamDepsDone
= 1 + m_upstreamDepsDone.fetch_add(1, std::memory_order_release); = 1 + m_upstreamDepsDone.fetch_add(1, std::memory_order_release);
assert(upstreamDepsDone <= m_upstreamDepCount); assert(upstreamDepsDone <= m_upstreamDepCount);
return (upstreamDepsDone == m_upstreamDepCount); return (upstreamDepsDone == m_upstreamDepCount);
} else { } else {
vluint32_t upstreamDepsDone_prev const vluint32_t upstreamDepsDone_prev
= m_upstreamDepsDone.fetch_sub(1, std::memory_order_release); = m_upstreamDepsDone.fetch_sub(1, std::memory_order_release);
assert(upstreamDepsDone_prev > 0); assert(upstreamDepsDone_prev > 0);
return (upstreamDepsDone_prev == 1); return (upstreamDepsDone_prev == 1);
} }
} }
inline bool areUpstreamDepsDone(bool evenCycle) const { inline bool areUpstreamDepsDone(bool evenCycle) const {
vluint32_t target = evenCycle ? m_upstreamDepCount : 0; const vluint32_t target = evenCycle ? m_upstreamDepCount : 0;
return m_upstreamDepsDone.load(std::memory_order_acquire) == target; return m_upstreamDepsDone.load(std::memory_order_acquire) == target;
} }
inline void waitUntilUpstreamDone(bool evenCycle) const { inline void waitUntilUpstreamDone(bool evenCycle) const {

View File

@ -129,7 +129,7 @@ void VerilatedVcd::openNextImp(bool incFilename) {
if (incFilename) { if (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('.'); const size_t pos = name.rfind('.');
if (pos > 8 && 0 == std::strncmp("_cat", name.c_str() + pos - 8, 4) if (pos > 8 && 0 == std::strncmp("_cat", name.c_str() + pos - 8, 4)
&& std::isdigit(name.c_str()[pos - 4]) && std::isdigit(name.c_str()[pos - 3]) && std::isdigit(name.c_str()[pos - 4]) && std::isdigit(name.c_str()[pos - 3])
&& std::isdigit(name.c_str()[pos - 2]) && std::isdigit(name.c_str()[pos - 1])) { && std::isdigit(name.c_str()[pos - 2]) && std::isdigit(name.c_str()[pos - 1])) {
@ -299,10 +299,10 @@ void VerilatedVcd::bufferFlush() VL_MT_UNSAFE_ONE {
if (VL_UNLIKELY(!isOpen())) return; if (VL_UNLIKELY(!isOpen())) return;
char* wp = m_wrBufp; char* wp = m_wrBufp;
while (true) { while (true) {
ssize_t remaining = (m_writep - wp); const 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); const ssize_t got = m_filep->write(wp, remaining);
if (got > 0) { if (got > 0) {
wp += got; wp += got;
m_wroteBytes += got; m_wroteBytes += got;
@ -352,7 +352,7 @@ void VerilatedVcd::dumpHeader() {
printStr("$version Generated by VerilatedVcd $end\n"); printStr("$version Generated by VerilatedVcd $end\n");
printStr("$date "); printStr("$date ");
{ {
time_t tick = time(nullptr); const time_t tick = time(nullptr);
tm ticktm; tm ticktm;
VL_LOCALTIME_R(&tick, &ticktm); VL_LOCALTIME_R(&tick, &ticktm);
constexpr int bufsize = 50; constexpr int bufsize = 50;

View File

@ -233,11 +233,11 @@ public:
// Inside dumping routines, dump one signal if it has changed. // Inside dumping routines, dump one signal if it has changed.
// We do want to inline these to avoid calls when the value did not change. // We do want to inline these to avoid calls when the value did not change.
inline void chgBit(vluint32_t code, const vluint32_t newval) { inline void chgBit(vluint32_t code, const vluint32_t newval) {
vluint32_t diff = oldp(code)[0] ^ newval; const vluint32_t diff = oldp(code)[0] ^ newval;
if (VL_UNLIKELY(diff)) fullBit(code, newval); if (VL_UNLIKELY(diff)) fullBit(code, newval);
} }
inline void chgBus(vluint32_t code, const vluint32_t newval, int bits) { inline void chgBus(vluint32_t code, const vluint32_t newval, int bits) {
vluint32_t diff = oldp(code)[0] ^ newval; const vluint32_t diff = oldp(code)[0] ^ newval;
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)))) {
fullBus(code, newval, bits); fullBus(code, newval, bits);
@ -245,7 +245,7 @@ public:
} }
} }
inline void chgQuad(vluint32_t code, const vluint64_t newval, int bits) { inline void chgQuad(vluint32_t code, const vluint64_t newval, int bits) {
vluint64_t diff = (*(reinterpret_cast<vluint64_t*>(oldp(code)))) ^ newval; const vluint64_t diff = (*(reinterpret_cast<vluint64_t*>(oldp(code)))) ^ newval;
if (VL_UNLIKELY(diff)) { if (VL_UNLIKELY(diff)) {
if (VL_UNLIKELY(bits == 64 || (diff & ((1ULL << bits) - 1)))) { if (VL_UNLIKELY(bits == 64 || (diff & ((1ULL << bits) - 1)))) {
fullQuad(code, newval, bits); fullQuad(code, newval, bits);
@ -270,7 +270,7 @@ public:
} }
} }
inline void chgTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri) { inline void chgTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri) {
vluint32_t diff = ((oldp(code)[0] ^ newval) | (oldp(code)[1] ^ newtri)); const vluint32_t diff = ((oldp(code)[0] ^ newval) | (oldp(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
@ -281,7 +281,7 @@ public:
} }
inline void chgTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, inline void chgTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri,
int bits) { int bits) {
vluint32_t diff = ((oldp(code)[0] ^ newval) | (oldp(code)[1] ^ newtri)); const vluint32_t diff = ((oldp(code)[0] ^ newval) | (oldp(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);
@ -290,8 +290,8 @@ public:
} }
inline void chgTriQuad(vluint32_t code, const vluint64_t newval, const vluint64_t newtri, inline void chgTriQuad(vluint32_t code, const vluint64_t newval, const vluint64_t newtri,
int bits) { int bits) {
vluint64_t diff = (((*(reinterpret_cast<vluint64_t*>(oldp(code)))) ^ newval) const vluint64_t diff = (((*(reinterpret_cast<vluint64_t*>(oldp(code)))) ^ newval)
| ((*(reinterpret_cast<vluint64_t*>(oldp(code + 1)))) ^ newtri)); | ((*(reinterpret_cast<vluint64_t*>(oldp(code + 1)))) ^ newtri));
if (VL_UNLIKELY(diff)) { if (VL_UNLIKELY(diff)) {
if (VL_UNLIKELY(bits == 64 || (diff & ((1ULL << bits) - 1)))) { if (VL_UNLIKELY(bits == 64 || (diff & ((1ULL << bits) - 1)))) {
fullTriQuad(code, newval, newtri, bits); fullTriQuad(code, newval, newtri, bits);

View File

@ -44,9 +44,9 @@ public:
// We want to avoid a depreciated warning, but still be back compatible. // We want to avoid a depreciated warning, but still be back compatible.
// Turning off the message just for this still results in an // Turning off the message just for this still results in an
// annoying "to turn off" message. // annoying "to turn off" message.
sc_time t1sec(1, SC_SEC); const sc_time t1sec(1, SC_SEC);
if (t1sec.to_default_time_units() != 0) { if (t1sec.to_default_time_units() != 0) {
sc_time tunits(1.0 / t1sec.to_default_time_units(), SC_SEC); const sc_time tunits(1.0 / t1sec.to_default_time_units(), SC_SEC);
spTrace()->set_time_unit(tunits.to_string()); spTrace()->set_time_unit(tunits.to_string());
} }
spTrace()->set_time_resolution(sc_get_time_resolution().to_string()); spTrace()->set_time_resolution(sc_get_time_resolution().to_string());

View File

@ -310,7 +310,7 @@ public:
return dynamic_cast<VerilatedVpioVar*>(reinterpret_cast<VerilatedVpio*>(h)); return dynamic_cast<VerilatedVpioVar*>(reinterpret_cast<VerilatedVpio*>(h));
} }
vluint32_t mask() const { return m_mask.u32; } vluint32_t mask() const { return m_mask.u32; }
vluint8_t mask_byte(int idx) { return m_mask.u8[idx & 3]; } vluint8_t mask_byte(int idx) const { return m_mask.u8[idx & 3]; }
vluint32_t entSize() const { return m_entSize; } vluint32_t entSize() const { return m_entSize; }
vluint32_t index() const { return m_index; } vluint32_t index() const { return m_index; }
virtual vluint32_t type() const override { virtual vluint32_t type() const override {
@ -365,7 +365,7 @@ public:
virtual vluint32_t type() const override { return vpiIterator; } virtual vluint32_t type() const override { return vpiIterator; }
virtual vpiHandle dovpi_scan() override { virtual vpiHandle dovpi_scan() override {
if (VL_LIKELY(m_scopep->varsp())) { if (VL_LIKELY(m_scopep->varsp())) {
VerilatedVarNameMap* varsp = m_scopep->varsp(); const VerilatedVarNameMap* const varsp = m_scopep->varsp();
if (VL_UNLIKELY(!m_started)) { if (VL_UNLIKELY(!m_started)) {
m_it = varsp->begin(); m_it = varsp->begin();
m_started = true; m_started = true;
@ -564,7 +564,7 @@ public:
} }
static void callTimedCbs() VL_MT_UNSAFE_ONE { static void callTimedCbs() VL_MT_UNSAFE_ONE {
assertOneCheck(); assertOneCheck();
QData time = VL_TIME_Q(); const QData time = VL_TIME_Q();
for (auto it = s().m_timedCbs.begin(); it != s().m_timedCbs.end();) { for (auto it = s().m_timedCbs.begin(); it != s().m_timedCbs.end();) {
if (VL_UNLIKELY(it->first.first <= time)) { if (VL_UNLIKELY(it->first.first <= time)) {
VerilatedVpiCbHolder& ho = it->second; VerilatedVpiCbHolder& ho = it->second;
@ -587,7 +587,7 @@ public:
if (VL_LIKELY(it != s().m_timedCbs.cend())) return it->first.first; if (VL_LIKELY(it != s().m_timedCbs.cend())) return it->first.first;
return ~0ULL; // maxquad return ~0ULL; // maxquad
} }
static bool callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE { static bool callCbs(const vluint32_t reason) VL_MT_UNSAFE_ONE {
VpioCbList& cbObjList = s().m_cbObjLists[reason]; VpioCbList& cbObjList = s().m_cbObjLists[reason];
bool called = false; bool called = false;
if (cbObjList.empty()) return called; if (cbObjList.empty()) return called;
@ -619,7 +619,7 @@ public:
const auto last = std::prev(cbObjList.end()); // prevent looping over newly added elements const auto last = std::prev(cbObjList.end()); // prevent looping over newly added elements
for (auto it = cbObjList.begin(); true;) { for (auto it = cbObjList.begin(); true;) {
// cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist // cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist
bool was_last = it == last; const bool was_last = it == last;
if (VL_UNLIKELY(it->invalid())) { // Deleted earlier, cleanup if (VL_UNLIKELY(it->invalid())) { // Deleted earlier, cleanup
it = cbObjList.erase(it); it = cbObjList.erase(it);
if (was_last) break; if (was_last) break;
@ -715,7 +715,7 @@ public:
void resetError() { m_flag = false; } void resetError() { m_flag = false; }
static void vpi_unsupported() { static void vpi_unsupported() {
// Not supported yet // Not supported yet
p_vpi_error_info error_info_p = VerilatedVpiImp::error_info()->getError(); const p_vpi_error_info error_info_p = VerilatedVpiImp::error_info()->getError();
if (error_info_p) { if (error_info_p) {
VL_FATAL_MT(error_info_p->file, error_info_p->line, "", error_info_p->message); VL_FATAL_MT(error_info_p->file, error_info_p->line, "", error_info_p->message);
return; return;
@ -1300,9 +1300,9 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
case cbAfterDelay: { case cbAfterDelay: {
QData time = 0; QData time = 0;
if (cb_data_p->time) time = VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low); if (cb_data_p->time) time = VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
QData abstime = VL_TIME_Q() + time; const QData abstime = VL_TIME_Q() + time;
vluint64_t id = VerilatedVpiImp::nextCallbackId(); vluint64_t id = VerilatedVpiImp::nextCallbackId();
VerilatedVpioTimedCb* vop = new VerilatedVpioTimedCb{id, abstime}; VerilatedVpioTimedCb* const vop = new VerilatedVpioTimedCb{id, abstime};
VerilatedVpiImp::cbTimedAdd(id, cb_data_p, abstime); VerilatedVpiImp::cbTimedAdd(id, cb_data_p, abstime);
return vop->castVpiHandle(); return vop->castVpiHandle();
} }
@ -1316,8 +1316,8 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
case cbEnterInteractive: // FALLTHRU // NOP, but need to return handle, so make object case cbEnterInteractive: // FALLTHRU // NOP, but need to return handle, so make object
case cbExitInteractive: // FALLTHRU // NOP, but need to return handle, so make object case cbExitInteractive: // FALLTHRU // NOP, but need to return handle, so make object
case cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object case cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object
vluint64_t id = VerilatedVpiImp::nextCallbackId(); const vluint64_t id = VerilatedVpiImp::nextCallbackId();
VerilatedVpioReasonCb* vop = new VerilatedVpioReasonCb{id, cb_data_p->reason}; VerilatedVpioReasonCb* const vop = new VerilatedVpioReasonCb{id, cb_data_p->reason};
VerilatedVpiImp::cbReasonAdd(id, cb_data_p); VerilatedVpiImp::cbReasonAdd(id, cb_data_p);
return vop->castVpiHandle(); return vop->castVpiHandle();
} }
@ -1332,7 +1332,7 @@ PLI_INT32 vpi_remove_cb(vpiHandle cb_obj) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_remove_cb %p\n", cb_obj);); VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_remove_cb %p\n", cb_obj););
VerilatedVpiImp::assertOneCheck(); VerilatedVpiImp::assertOneCheck();
VL_VPI_ERROR_RESET_(); VL_VPI_ERROR_RESET_();
VerilatedVpio* vop = VerilatedVpio::castp(cb_obj); VerilatedVpio* const vop = VerilatedVpio::castp(cb_obj);
if (VL_UNLIKELY(!vop)) return 0; if (VL_UNLIKELY(!vop)) return 0;
return vop->dovpi_remove_cb(); return vop->dovpi_remove_cb();
} }
@ -1355,7 +1355,7 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle_by_name %s %p\n", namep, scope);); VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle_by_name %s %p\n", namep, scope););
const VerilatedVar* varp = nullptr; const VerilatedVar* varp = nullptr;
const VerilatedScope* scopep; const VerilatedScope* scopep;
VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope); const VerilatedVpioScope* const voScopep = VerilatedVpioScope::castp(scope);
std::string scopeAndName = namep; std::string scopeAndName = namep;
if (voScopep) { if (voScopep) {
scopeAndName = std::string(voScopep->fullname()) + "." + namep; scopeAndName = std::string(voScopep->fullname()) + "." + namep;
@ -1373,7 +1373,7 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
} }
const char* baseNamep = scopeAndName.c_str(); const char* baseNamep = scopeAndName.c_str();
std::string scopename; std::string scopename;
const char* dotp = std::strrchr(namep, '.'); const char* const dotp = std::strrchr(namep, '.');
if (VL_LIKELY(dotp)) { if (VL_LIKELY(dotp)) {
baseNamep = dotp + 1; baseNamep = dotp + 1;
scopename = std::string(namep, dotp - namep); scopename = std::string(namep, dotp - namep);
@ -1407,7 +1407,7 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
// Memory words are not indexable // Memory words are not indexable
VerilatedVpioMemoryWord* vop = VerilatedVpioMemoryWord::castp(object); VerilatedVpioMemoryWord* vop = VerilatedVpioMemoryWord::castp(object);
if (VL_UNLIKELY(vop)) return nullptr; if (VL_UNLIKELY(vop)) return nullptr;
VerilatedVpioVar* varop = VerilatedVpioVar::castp(object); const VerilatedVpioVar* const varop = VerilatedVpioVar::castp(object);
if (VL_LIKELY(varop)) { if (VL_LIKELY(varop)) {
if (varop->varp()->dims() < 2) return nullptr; if (varop->varp()->dims() < 2) return nullptr;
if (VL_LIKELY(varop->varp()->unpacked().left() >= varop->varp()->unpacked().right())) { if (VL_LIKELY(varop->varp()->unpacked().left() >= varop->varp()->unpacked().right())) {
@ -1496,7 +1496,7 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
VL_VPI_ERROR_RESET_(); VL_VPI_ERROR_RESET_();
switch (type) { switch (type) {
case vpiMemoryWord: { case vpiMemoryWord: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return nullptr; if (VL_UNLIKELY(!vop)) return nullptr;
if (vop->varp()->dims() < 2) return nullptr; if (vop->varp()->dims() < 2) return nullptr;
if (vop->varp()->dims() > 2) { if (vop->varp()->dims() > 2) {
@ -1508,7 +1508,7 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
return (new VerilatedVpioMemoryWordIter(object, vop->varp()))->castVpiHandle(); return (new VerilatedVpioMemoryWordIter(object, vop->varp()))->castVpiHandle();
} }
case vpiRange: { case vpiRange: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return nullptr; if (VL_UNLIKELY(!vop)) return nullptr;
if (vop->varp()->dims() < 2) return nullptr; if (vop->varp()->dims() < 2) return nullptr;
// Unsupported is multidim list // Unsupported is multidim list
@ -1521,15 +1521,15 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
return ((new VerilatedVpioRangeIter(vop->rangep()))->castVpiHandle()); return ((new VerilatedVpioRangeIter(vop->rangep()))->castVpiHandle());
} }
case vpiReg: { case vpiReg: {
VerilatedVpioScope* vop = VerilatedVpioScope::castp(object); const VerilatedVpioScope* const vop = VerilatedVpioScope::castp(object);
if (VL_UNLIKELY(!vop)) return nullptr; if (VL_UNLIKELY(!vop)) return nullptr;
return ((new VerilatedVpioVarIter(vop->scopep()))->castVpiHandle()); return ((new VerilatedVpioVarIter(vop->scopep()))->castVpiHandle());
} }
case vpiModule: { case vpiModule: {
VerilatedVpioModule* vop = VerilatedVpioModule::castp(object); const VerilatedVpioModule* const vop = VerilatedVpioModule::castp(object);
const VerilatedHierarchyMap* map = VerilatedImp::hierarchyMap(); const VerilatedHierarchyMap* const map = VerilatedImp::hierarchyMap();
const VerilatedScope* mod = vop ? vop->scopep() : nullptr; const VerilatedScope* const modp = vop ? vop->scopep() : nullptr;
const auto it = vlstd::as_const(map)->find(const_cast<VerilatedScope*>(mod)); const auto it = vlstd::as_const(map)->find(const_cast<VerilatedScope*>(modp));
if (it == map->end()) return nullptr; if (it == map->end()) return nullptr;
return ((new VerilatedVpioModuleIter(it->second))->castVpiHandle()); return ((new VerilatedVpioModuleIter(it->second))->castVpiHandle());
} }
@ -1560,30 +1560,30 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
return Verilated::threadContextp()->timeprecision(); return Verilated::threadContextp()->timeprecision();
} }
case vpiTimeUnit: { case vpiTimeUnit: {
VerilatedVpioScope* vop = VerilatedVpioScope::castp(object); const VerilatedVpioScope* const vop = VerilatedVpioScope::castp(object);
if (!vop) if (!vop)
return Verilated::threadContextp()->timeunit(); // Null asks for global, not unlikely return Verilated::threadContextp()->timeunit(); // Null asks for global, not unlikely
return vop->scopep()->timeunit(); return vop->scopep()->timeunit();
} }
case vpiType: { case vpiType: {
VerilatedVpio* vop = VerilatedVpio::castp(object); const VerilatedVpio* const vop = VerilatedVpio::castp(object);
if (VL_UNLIKELY(!vop)) return 0; if (VL_UNLIKELY(!vop)) return 0;
return vop->type(); return vop->type();
} }
case vpiDirection: { case vpiDirection: {
// By forthought, the directions already are vpi enumerated // By forthought, the directions already are vpi enumerated
VerilatedVpioVarBase* vop = VerilatedVpioVarBase::castp(object); const VerilatedVpioVarBase* const vop = VerilatedVpioVarBase::castp(object);
if (VL_UNLIKELY(!vop)) return 0; if (VL_UNLIKELY(!vop)) return 0;
return vop->varp()->vldir(); return vop->varp()->vldir();
} }
case vpiScalar: // FALLTHRU case vpiScalar: // FALLTHRU
case vpiVector: { case vpiVector: {
VerilatedVpioVarBase* vop = VerilatedVpioVarBase::castp(object); const VerilatedVpioVarBase* const vop = VerilatedVpioVarBase::castp(object);
if (VL_UNLIKELY(!vop)) return 0; if (VL_UNLIKELY(!vop)) return 0;
return (property == vpiVector) ^ (vop->varp()->dims() == 0); return (property == vpiVector) ^ (vop->varp()->dims() == 0);
} }
case vpiSize: { case vpiSize: {
VerilatedVpioVarBase* vop = VerilatedVpioVarBase::castp(object); const VerilatedVpioVarBase* const vop = VerilatedVpioVarBase::castp(object);
if (VL_UNLIKELY(!vop)) return 0; if (VL_UNLIKELY(!vop)) return 0;
return vop->size(); return vop->size();
} }
@ -1602,7 +1602,7 @@ PLI_INT64 vpi_get64(PLI_INT32 /*property*/, vpiHandle /*object*/) {
PLI_BYTE8* vpi_get_str(PLI_INT32 property, vpiHandle object) { PLI_BYTE8* vpi_get_str(PLI_INT32 property, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_str %d %p\n", property, object);); VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_str %d %p\n", property, object););
VerilatedVpiImp::assertOneCheck(); VerilatedVpiImp::assertOneCheck();
VerilatedVpio* vop = VerilatedVpio::castp(object); const VerilatedVpio* const vop = VerilatedVpio::castp(object);
VL_VPI_ERROR_RESET_(); VL_VPI_ERROR_RESET_();
if (VL_UNLIKELY(!vop)) return nullptr; if (VL_UNLIKELY(!vop)) return nullptr;
switch (property) { switch (property) {
@ -1725,7 +1725,7 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
__FILE__, __LINE__, "", __FILE__, __LINE__, "",
"vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile"); "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
} }
WDataInP datap = (reinterpret_cast<EData*>(varDatap)); const WDataInP datap = (reinterpret_cast<EData*>(varDatap));
for (int i = 0; i < words; ++i) { for (int i = 0; i < words; ++i) {
t_out[i].aval = datap[i]; t_out[i].aval = datap[i];
t_out[i].bval = 0; t_out[i].bval = 0;
@ -1756,7 +1756,7 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
} else if (valuep->format == vpiOctStrVal) { } else if (valuep->format == vpiOctStrVal) {
valuep->value.str = t_outStr; valuep->value.str = t_outStr;
int chars = (varp->packed().elements() + 2) / 3; int chars = (varp->packed().elements() + 2) / 3;
int bytes = VL_BYTES_I(varp->packed().elements()); const int bytes = VL_BYTES_I(varp->packed().elements());
CData* datap = (reinterpret_cast<CData*>(varDatap)); CData* datap = (reinterpret_cast<CData*>(varDatap));
int i; int i;
if (chars > t_outStrSz) { if (chars > t_outStrSz) {
@ -1770,7 +1770,7 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
chars = t_outStrSz; chars = t_outStrSz;
} }
for (i = 0; i < chars; ++i) { for (i = 0; i < chars; ++i) {
div_t idx = div(i * 3, 8); const div_t idx = div(i * 3, 8);
int val = datap[idx.quot]; int val = datap[idx.quot];
if ((idx.quot + 1) < bytes) { if ((idx.quot + 1) < bytes) {
// if the next byte is valid or that in // if the next byte is valid or that in
@ -1832,7 +1832,7 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
if (i == (chars - 1)) { if (i == (chars - 1)) {
// most signifcant char, mask off non existant bits when vector // most signifcant char, mask off non existant bits when vector
// size is not a multiple of 4 // size is not a multiple of 4
unsigned int rem = varp->packed().elements() & 3; const unsigned int rem = varp->packed().elements() & 3;
if (rem) { if (rem) {
// generate bit mask & zero non existant bits // generate bit mask & zero non existant bits
val &= (1 << rem) - 1; val &= (1 << rem) - 1;
@ -1862,7 +1862,7 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
bytes = t_outStrSz; bytes = t_outStrSz;
} }
for (i = 0; i < bytes; ++i) { for (i = 0; i < bytes; ++i) {
char val = datap[bytes - i - 1]; const char val = datap[bytes - i - 1];
// other simulators replace [leading?] zero chars with spaces, replicate here. // other simulators replace [leading?] zero chars with spaces, replicate here.
t_outStr[i] = val ? val : ' '; t_outStr[i] = val ? val : ' ';
} }
@ -1896,7 +1896,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value valuep) {
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) { if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
vl_get_value(vop->varp(), vop->varDatap(), valuep, vop->fullname()); vl_get_value(vop->varp(), vop->varDatap(), valuep, vop->fullname());
return; return;
} else if (VerilatedVpioParam* vop = VerilatedVpioParam::castp(object)) { } else if (const VerilatedVpioParam* const vop = VerilatedVpioParam::castp(object)) {
vl_get_value(vop->varp(), vop->varDatap(), valuep, vop->fullname()); vl_get_value(vop->varp(), vop->varDatap(), valuep, vop->fullname());
return; return;
} else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) { } else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) {
@ -1920,7 +1920,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
VL_VPI_WARNING_(__FILE__, __LINE__, "Ignoring vpi_put_value with nullptr value pointer"); VL_VPI_WARNING_(__FILE__, __LINE__, "Ignoring vpi_put_value with nullptr value pointer");
return nullptr; return nullptr;
} }
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) { if (const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object)) {
VL_DEBUG_IF_PLI( VL_DEBUG_IF_PLI(
VL_DBG_MSGF("- vpi: vpi_put_value name=%s fmt=%d vali=%d\n", vop->fullname(), VL_DBG_MSGF("- vpi: vpi_put_value name=%s fmt=%d vali=%d\n", vop->fullname(),
valuep->format, valuep->value.integer); valuep->format, valuep->value.integer);
@ -1953,7 +1953,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
valuep->value.vector[1].aval & vop->mask(), valuep->value.vector[0].aval); valuep->value.vector[1].aval & vop->mask(), valuep->value.vector[0].aval);
return object; return object;
} else if (vop->varp()->vltype() == VLVT_WDATA) { } else if (vop->varp()->vltype() == VLVT_WDATA) {
int words = VL_WORDS_I(vop->varp()->packed().elements()); const int words = VL_WORDS_I(vop->varp()->packed().elements());
WDataOutP datap = (reinterpret_cast<EData*>(vop->varDatap())); WDataOutP datap = (reinterpret_cast<EData*>(vop->varDatap()));
for (int i = 0; i < words; ++i) { for (int i = 0; i < words; ++i) {
datap[i] = valuep->value.vector[i].aval; datap[i] = valuep->value.vector[i].aval;
@ -1962,8 +1962,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
return object; return object;
} }
} else if (valuep->format == vpiBinStrVal) { } else if (valuep->format == vpiBinStrVal) {
int bits = vop->varp()->packed().elements(); const int bits = vop->varp()->packed().elements();
int len = std::strlen(valuep->value.str); const int len = std::strlen(valuep->value.str);
CData* datap = (reinterpret_cast<CData*>(vop->varDatap())); CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
for (int i = 0; i < bits; ++i) { for (int i = 0; i < bits; ++i) {
char set = (i < len) ? (valuep->value.str[len - i - 1] == '1') : 0; char set = (i < len) ? (valuep->value.str[len - i - 1] == '1') : 0;
@ -1977,9 +1977,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
} }
return object; return object;
} else if (valuep->format == vpiOctStrVal) { } else if (valuep->format == vpiOctStrVal) {
int chars = (vop->varp()->packed().elements() + 2) / 3; const int chars = (vop->varp()->packed().elements() + 2) / 3;
int bytes = VL_BYTES_I(vop->varp()->packed().elements()); const int bytes = VL_BYTES_I(vop->varp()->packed().elements());
int len = std::strlen(valuep->value.str); const int len = std::strlen(valuep->value.str);
CData* datap = (reinterpret_cast<CData*>(vop->varDatap())); CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
div_t idx; div_t idx;
datap[0] = 0; // reset zero'th byte datap[0] = 0; // reset zero'th byte
@ -2029,7 +2029,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
} else if (valuep->format == vpiDecStrVal) { } else if (valuep->format == vpiDecStrVal) {
char remainder[16]; char remainder[16];
unsigned long long val; unsigned long long val;
int success = std::sscanf(valuep->value.str, "%30llu%15s", &val, remainder); const int success = std::sscanf(valuep->value.str, "%30llu%15s", &val, remainder);
if (success < 1) { if (success < 1) {
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Parsing failed for '%s' as value %s for %s", VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Parsing failed for '%s' as value %s for %s",
__func__, valuep->value.str, __func__, valuep->value.str,
@ -2057,12 +2057,12 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
return object; return object;
} }
} else if (valuep->format == vpiHexStrVal) { } else if (valuep->format == vpiHexStrVal) {
int chars = (vop->varp()->packed().elements() + 3) >> 2; const int chars = (vop->varp()->packed().elements() + 3) >> 2;
CData* datap = (reinterpret_cast<CData*>(vop->varDatap())); CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
char* val = valuep->value.str; char* val = valuep->value.str;
// skip hex ident if one is detected at the start of the string // skip hex ident if one is detected at the start of the string
if (val[0] == '0' && (val[1] == 'x' || val[1] == 'X')) val += 2; if (val[0] == '0' && (val[1] == 'x' || val[1] == 'X')) val += 2;
int len = std::strlen(val); const int len = std::strlen(val);
for (int i = 0; i < chars; ++i) { for (int i = 0; i < chars; ++i) {
char hex; char hex;
// compute hex digit value // compute hex digit value
@ -2097,8 +2097,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
datap[(chars - 1) >> 1] &= vop->mask_byte((chars - 1) >> 1); datap[(chars - 1) >> 1] &= vop->mask_byte((chars - 1) >> 1);
return object; return object;
} else if (valuep->format == vpiStringVal) { } else if (valuep->format == vpiStringVal) {
int bytes = VL_BYTES_I(vop->varp()->packed().elements()); const int bytes = VL_BYTES_I(vop->varp()->packed().elements());
int len = std::strlen(valuep->value.str); const int len = std::strlen(valuep->value.str);
CData* datap = (reinterpret_cast<CData*>(vop->varDatap())); CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
for (int i = 0; i < bytes; ++i) { for (int i = 0; i < bytes; ++i) {
// prepend with 0 values before placing string the least significant bytes // prepend with 0 values before placing string the least significant bytes
@ -2120,11 +2120,11 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s",
__func__, VerilatedVpiError::strFromVpiVal(valuep->format), vop->fullname()); __func__, VerilatedVpiError::strFromVpiVal(valuep->format), vop->fullname());
return nullptr; return nullptr;
} else if (VerilatedVpioParam* vop = VerilatedVpioParam::castp(object)) { } else if (const VerilatedVpioParam* const vop = VerilatedVpioParam::castp(object)) {
VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Ignoring vpi_put_value to vpiParameter: %s", VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Ignoring vpi_put_value to vpiParameter: %s",
__func__, vop->fullname()); __func__, vop->fullname());
return nullptr; return nullptr;
} else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) { } else if (const VerilatedVpioConst* const vop = VerilatedVpioConst::castp(object)) {
VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Ignoring vpi_put_value to vpiConstant: %s", VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Ignoring vpi_put_value to vpiConstant: %s",
__func__, vop->fullname()); __func__, vop->fullname());
return nullptr; return nullptr;
@ -2153,7 +2153,7 @@ void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
return; return;
} }
if (time_p->type == vpiSimTime) { if (time_p->type == vpiSimTime) {
QData qtime = VL_TIME_Q(); const QData qtime = VL_TIME_Q();
VlWide<2> itime; VlWide<2> itime;
VL_SET_WQ(itime, qtime); VL_SET_WQ(itime, qtime);
time_p->low = itime[0]; time_p->low = itime[0];
@ -2162,9 +2162,9 @@ void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
} else if (time_p->type == vpiScaledRealTime) { } else if (time_p->type == vpiScaledRealTime) {
double dtime = VL_TIME_D(); double dtime = VL_TIME_D();
if (VerilatedVpioScope* vop = VerilatedVpioScope::castp(object)) { if (VerilatedVpioScope* vop = VerilatedVpioScope::castp(object)) {
int scalePow10 const int scalePow10
= Verilated::threadContextp()->timeprecision() - vop->scopep()->timeunit(); = Verilated::threadContextp()->timeprecision() - vop->scopep()->timeunit();
double scale = vl_time_multiplier(scalePow10); // e.g. 0.0001 const double scale = vl_time_multiplier(scalePow10); // e.g. 0.0001
dtime *= scale; dtime *= scale;
} }
time_p->real = dtime; time_p->real = dtime;
@ -2198,7 +2198,7 @@ PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8* formatp, ...) {
VL_VPI_ERROR_RESET_(); VL_VPI_ERROR_RESET_();
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
int chars = vpi_mcd_vprintf(mcd, formatp, ap); const int chars = vpi_mcd_vprintf(mcd, formatp, ap);
va_end(ap); va_end(ap);
return chars; return chars;
} }
@ -2208,7 +2208,7 @@ PLI_INT32 vpi_printf(PLI_BYTE8* formatp, ...) {
VL_VPI_ERROR_RESET_(); VL_VPI_ERROR_RESET_();
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
int chars = vpi_vprintf(formatp, ap); const int chars = vpi_vprintf(formatp, ap);
va_end(ap); va_end(ap);
return chars; return chars;
} }
@ -2221,11 +2221,11 @@ PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8* format, va_list ap) { PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8* format, va_list ap) {
VerilatedVpiImp::assertOneCheck(); VerilatedVpiImp::assertOneCheck();
FILE* fp = VL_CVT_I_FP(mcd); FILE* const fp = VL_CVT_I_FP(mcd);
VL_VPI_ERROR_RESET_(); VL_VPI_ERROR_RESET_();
// cppcheck-suppress nullPointer // cppcheck-suppress nullPointer
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
int chars = vfprintf(fp, format, ap); const int chars = vfprintf(fp, format, ap);
return chars; return chars;
} }
@ -2238,7 +2238,7 @@ PLI_INT32 vpi_flush(void) {
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) { PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
VerilatedVpiImp::assertOneCheck(); VerilatedVpiImp::assertOneCheck();
FILE* fp = VL_CVT_I_FP(mcd); FILE* const fp = VL_CVT_I_FP(mcd);
VL_VPI_ERROR_RESET_(); VL_VPI_ERROR_RESET_();
if (VL_UNLIKELY(!fp)) return 1; if (VL_UNLIKELY(!fp)) return 1;
std::fflush(fp); std::fflush(fp);
@ -2255,7 +2255,7 @@ PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
// executing vpi_chk_error does not reset error // executing vpi_chk_error does not reset error
// error_info_p can be nullptr, so only return level in that case // error_info_p can be nullptr, so only return level in that case
VerilatedVpiImp::assertOneCheck(); VerilatedVpiImp::assertOneCheck();
p_vpi_error_info _error_info_p = VerilatedVpiImp::error_info()->getError(); p_vpi_error_info const _error_info_p = VerilatedVpiImp::error_info()->getError();
if (error_info_p && _error_info_p) *error_info_p = *_error_info_p; if (error_info_p && _error_info_p) *error_info_p = *_error_info_p;
if (!_error_info_p) return 0; // no error occured if (!_error_info_p) return 0; // no error occured
return _error_info_p->level; // return error severity level return _error_info_p->level; // return error severity level

View File

@ -47,7 +47,7 @@ public:
static bool callValueCbs() VL_MT_UNSAFE_ONE; static bool callValueCbs() VL_MT_UNSAFE_ONE;
/// Call callbacks of arbitrary types. /// Call callbacks of arbitrary types.
/// User wrapper code should call this from their main loops. /// User wrapper code should call this from their main loops.
static bool callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE; static bool callCbs(const vluint32_t reason) VL_MT_UNSAFE_ONE;
/// Returns time of the next registered VPI callback, or /// Returns time of the next registered VPI callback, or
/// ~(0ULL) if none are registered /// ~(0ULL) if none are registered
static QData cbNextDeadline() VL_MT_UNSAFE_ONE; static QData cbNextDeadline() VL_MT_UNSAFE_ONE;