diff --git a/include/verilated.cpp b/include/verilated.cpp index 0e2cd9ebc..6307702bd 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -16,8 +16,8 @@ /// \file /// \brief Verilator: Linked against all applications using Verilated source. /// -/// This file must be compiled and linked against all objects -/// created from Verilator. +/// This file must be compiled and linked against all objects +/// created from Verilator. /// /// Code available from: http://www.veripool.org/verilator /// @@ -73,9 +73,9 @@ void vl_finish(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE if (0 && hier) {} VL_PRINTF("- %s:%d: Verilog $finish\n", filename, linenum); // Not VL_PRINTF_MT, already on main thread if (Verilated::gotFinish()) { - VL_PRINTF("- %s:%d: Second verilog $finish, exiting\n", filename, linenum); // Not VL_PRINTF_MT, already on main thread - Verilated::flushCall(); - exit(0); + VL_PRINTF("- %s:%d: Second verilog $finish, exiting\n", filename, linenum); // Not VL_PRINTF_MT, already on main thread + Verilated::flushCall(); + exit(0); } Verilated::gotFinish(true); } @@ -85,7 +85,7 @@ void vl_finish(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE void vl_stop(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE { Verilated::gotFinish(true); Verilated::flushCall(); - vl_fatal(filename,linenum,hier,"Verilog $stop"); + vl_fatal(filename, linenum, hier, "Verilog $stop"); } #endif @@ -108,8 +108,8 @@ void vl_fatal(const char* filename, int linenum, const char* hier, const char* m void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE { #ifdef VL_THREADED VerilatedThreadMsgQueue::post(VerilatedMsg([=](){ - vl_finish(filename, linenum, hier); - })); + vl_finish(filename, linenum, hier); + })); #else vl_finish(filename, linenum, hier); #endif @@ -118,8 +118,8 @@ void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAF void VL_STOP_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE { #ifdef VL_THREADED VerilatedThreadMsgQueue::post(VerilatedMsg([=](){ - vl_stop(filename, linenum, hier); - })); + vl_stop(filename, linenum, hier); + })); #else vl_stop(filename, linenum, hier); #endif @@ -128,8 +128,8 @@ void VL_STOP_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_SAFE { #ifdef VL_THREADED VerilatedThreadMsgQueue::post(VerilatedMsg([=](){ - vl_fatal(filename, linenum, hier, msg); - })); + vl_fatal(filename, linenum, hier, msg); + })); #else vl_fatal(filename, linenum, hier, msg); #endif @@ -198,8 +198,8 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE { std::string out = _vl_string_vprintf(formatp, ap); va_end(ap); VerilatedThreadMsgQueue::post(VerilatedMsg([=](){ - VL_PRINTF("%s", out.c_str()); - })); + VL_PRINTF("%s", out.c_str()); + })); } #endif @@ -283,11 +283,11 @@ QData VL_RANDOM_Q(int obits) VL_MT_SAFE { } WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE { for (int i=0; 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"); } @@ -346,28 +346,28 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo int words = VL_WORDS_I(lbits); for (int i=0; i= 0; --j) { - vluint64_t unw64 = ((k<(lwp[j])); - owp[j] = unw64 / static_cast(rwp[0]); - k = unw64 - static_cast(owp[j])*static_cast(rwp[0]); - } - if (is_modulus) { - owp[0] = k; - for (int i=1; i= 0; --j) { + vluint64_t unw64 = ((k<(lwp[j])); + owp[j] = unw64 / static_cast(rwp[0]); + k = unw64 - static_cast(owp[j])*static_cast(rwp[0]); + } + if (is_modulus) { + owp[0] = k; + for (int i=1; i> 32 won't mask the value 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))); } vn[0] = rwp[0] << s; @@ -391,48 +391,48 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo if (s) un[uw] = lwp[uw-1] >> (32-s); else un[uw] = 0; for (int i=uw-1; i>0; --i) { - un[i] = (lwp[i] << s) | (shift_mask & (lwp[i-1] >> (32-s))); + un[i] = (lwp[i] << s) | (shift_mask & (lwp[i-1] >> (32-s))); } un[0] = lwp[0] << s; // Main loop for (int j = uw - vw; j >= 0; --j) { - // Estimate - vluint64_t unw64 = (static_cast(un[j+vw])<(un[j+vw-1])); - vluint64_t qhat = unw64 / static_cast(vn[vw-1]); - vluint64_t rhat = unw64 - qhat*static_cast(vn[vw-1]); + // Estimate + vluint64_t unw64 = (static_cast(un[j+vw])<(un[j+vw-1])); + vluint64_t qhat = unw64 / static_cast(vn[vw-1]); + vluint64_t rhat = unw64 - qhat*static_cast(vn[vw-1]); again: - if (qhat >= VL_ULL(0x100000000) - || ((qhat*vn[vw-2]) > ((rhat<= VL_ULL(0x100000000) + || ((qhat*vn[vw-2]) > ((rhat<> VL_ULL(32)) - (t >> VL_ULL(32)); - } - t = un[j+vw] - k; + vlsint64_t t = 0; // Must be signed + vluint64_t k = 0; + for (int i=0; i> VL_ULL(32)) - (t >> VL_ULL(32)); + } + t = un[j+vw] - k; un[j+vw] = t; owp[j] = qhat; // Save quotient digit - if (t < 0) { - // Over subtracted; correct by adding back - owp[j]--; - k = 0; - for (int i=0; i(un[i+j]) + static_cast(vn[i]) + k; - un[i+j] = t; - k = t >> VL_ULL(32); - } - un[j+vw] = un[j+vw] + k; - } + if (t < 0) { + // Over subtracted; correct by adding back + owp[j]--; + k = 0; + for (int i=0; i(un[i+j]) + static_cast(vn[i]) + k; + un[i+j] = t; + k = t >> VL_ULL(32); + } + un[j+vw] = un[j+vw] + k; + } } if (is_modulus) { // modulus @@ -443,7 +443,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo for (int i=vw; i0) { // power = power*power - VL_ASSIGN_W(obits, lastpowstore, powstore); - VL_MUL_W(VL_WORDS_I(obits), powstore, lastpowstore, lastpowstore); - } - if (VL_BITISSET_W(rwp,bit)) { // out *= power - VL_ASSIGN_W(obits, lastoutstore, owp); - VL_MUL_W(VL_WORDS_I(obits), owp, lastoutstore, powstore); - } + if (bit>0) { // power = power*power + VL_ASSIGN_W(obits, lastpowstore, powstore); + VL_MUL_W(VL_WORDS_I(obits), powstore, lastpowstore, lastpowstore); + } + if (VL_BITISSET_W(rwp, bit)) { // out *= power + VL_ASSIGN_W(obits, lastoutstore, owp); + VL_MUL_W(VL_WORDS_I(obits), owp, lastoutstore, powstore); + } } return owp; } WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs) VL_MT_SAFE { WData rhsw[2]; 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 { // Skip check for rhs == 0, as short-circuit doesn't save time @@ -479,8 +479,8 @@ QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE { QData power = lhs; QData out = VL_ULL(1); for (int bit=0; bit0) power = power*power; - if (VL_BITISSET_W(rwp,bit)) out *= power; + if (bit>0) power = power*power; + if (VL_BITISSET_W(rwp, bit)) out *= power; } return out; } @@ -489,8 +489,8 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W bool lsign, bool rsign) VL_MT_SAFE { // obits==lbits, rbits can be different if (rsign && VL_SIGN_W(rbits, rwp)) { - int words = VL_WORDS_I(obits); - VL_ZERO_W(obits, owp); + int words = VL_WORDS_I(obits); + VL_ZERO_W(obits, owp); IData lor = 0; // 0=all zeros, ~0=all ones, else mix for (int i=1; i < (words-1); ++i) { lor |= lwp[i]; @@ -502,7 +502,7 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W if (rwp[0] & 1) { return VL_ALLONES_W(obits, owp); } // -1^odd=-1 else { owp[0] = 1; return owp; } // -1^even=1 } - return 0; + return 0; } return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp); } @@ -510,7 +510,7 @@ WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign) VL_MT_SAFE { WData rhsw[2]; 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, bool rsign) VL_MT_SAFE { // Skip check for rhs == 0, as short-circuit doesn't save time @@ -521,7 +521,7 @@ QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsig if (rwp[0] & 1) return VL_MASK_I(obits); // -1^odd=-1 else return 1; // -1^even=1 } - return 0; + return 0; } return VL_POW_QQW(obits, rbits, rbits, lhs, rwp); } @@ -569,7 +569,7 @@ std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE { } // Do a va_arg returning a quad, assuming input argument is anything less than wide -#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_WORDSIZE) ? va_arg(ap,IData) : va_arg(ap,QData)) +#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_WORDSIZE) ? va_arg(ap, IData) : va_arg(ap, QData)) void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SAFE { // Format a Verilog $write style format into the output list @@ -586,10 +586,10 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA bool widthSet = false; int width = 0; for (const char* pos = formatp; *pos; ++pos) { - if (!inPct && pos[0]=='%') { - pctp = pos; - inPct = true; - widthSet = false; + if (!inPct && pos[0]=='%') { + pctp = pos; + inPct = true; + widthSet = false; width = 0; } else if (!inPct) { // Normal text // Fast-forward to next escape and add to output @@ -601,20 +601,20 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA } } else { // Format character inPct = false; - char fmt = pos[0]; - switch (fmt) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - inPct = true; // Get more digits - widthSet = true; - width = width*10 + (fmt - '0'); - break; - case '.': - inPct = true; // Get more digits - break; - case '%': - output += '%'; - break; + char fmt = pos[0]; + switch (fmt) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + inPct = true; // Get more digits + widthSet = true; + width = width*10 + (fmt - '0'); + break; + case '.': + inPct = true; // Get more digits + break; + case '%': + output += '%'; + break; case 'N': { // "C" string with name of module, add . if needed const char* cstrp = va_arg(ap, const char*); if (VL_LIKELY(*cstrp)) { output += cstrp; output += '.'; } @@ -626,47 +626,47 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA break; } case '@': { // Verilog/C++ string - va_arg(ap, int); // # bits is ignored - const std::string* cstrp = va_arg(ap, const std::string*); - output += *cstrp; - break; - } - case 'e': - case 'f': - case 'g': { - const int lbits = va_arg(ap, int); - double d = va_arg(ap, double); - if (lbits) {} // UNUSED - always 64 - strncpy(tmpf, pctp, pos-pctp+1); - tmpf[pos-pctp+1] = '\0'; - sprintf(tmp, tmpf, d); - output += tmp; - break; - } - default: { - // Deal with all read-and-print somethings - const int lbits = va_arg(ap, int); - QData ld = 0; - WData qlwp[2]; - WDataInP lwp; - if (lbits <= VL_QUADSIZE) { - ld = _VL_VA_ARG_Q(ap, lbits); - VL_SET_WQ(qlwp,ld); - lwp = qlwp; - } else { - lwp = va_arg(ap,WDataInP); - ld = lwp[0]; - } - int lsb=lbits-1; - if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) --lsb; - switch (fmt) { - case 'c': { - IData charval = ld & 0xff; - output += charval; - break; - } - case 's': - for (; lsb>=0; --lsb) { + va_arg(ap, int); // # bits is ignored + const std::string* cstrp = va_arg(ap, const std::string*); + output += *cstrp; + break; + } + case 'e': + case 'f': + case 'g': { + const int lbits = va_arg(ap, int); + double d = va_arg(ap, double); + if (lbits) {} // UNUSED - always 64 + strncpy(tmpf, pctp, pos-pctp+1); + tmpf[pos-pctp+1] = '\0'; + sprintf(tmp, tmpf, d); + output += tmp; + break; + } + default: { + // Deal with all read-and-print somethings + const int lbits = va_arg(ap, int); + QData ld = 0; + WData qlwp[2]; + WDataInP lwp; + if (lbits <= VL_QUADSIZE) { + ld = _VL_VA_ARG_Q(ap, lbits); + VL_SET_WQ(qlwp, ld); + lwp = qlwp; + } else { + lwp = va_arg(ap, WDataInP); + ld = lwp[0]; + } + int lsb=lbits-1; + if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp, lsb)) --lsb; + switch (fmt) { + case 'c': { + IData charval = ld & 0xff; + output += charval; + break; + } + case 's': + for (; lsb>=0; --lsb) { lsb = (lsb / 8) * 8; // Next digit IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff; output += (charval==0)?' ':charval; @@ -676,8 +676,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA int digits; std::string append; if (lbits <= VL_QUADSIZE) { - digits = sprintf(tmp,"%" VL_PRI64 "d", - static_cast(VL_EXTENDS_QQ(lbits,lbits,ld))); + digits = sprintf(tmp, "%" VL_PRI64 "d", + static_cast(VL_EXTENDS_QQ(lbits, lbits, ld))); append = tmp; } else { if (VL_SIGN_I(lbits, lwp[VL_WORDS_I(lbits)-1])) { @@ -689,8 +689,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA } digits = append.length(); } - int needmore = width-digits; - if (needmore>0) { + int needmore = width-digits; + if (needmore>0) { if (pctp && pctp[0] && pctp[1]=='0') { // %0 output.append(needmore, '0'); // Pre-pad zero } else { @@ -704,14 +704,14 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA int digits; std::string append; if (lbits <= VL_QUADSIZE) { - digits = sprintf(tmp,"%" VL_PRI64 "u",ld); + digits = sprintf(tmp, "%" VL_PRI64 "u", ld); append = tmp; } else { append = VL_DECIMAL_NW(lbits, lwp); digits = append.length(); } - int needmore = width-digits; - if (needmore>0) { + int needmore = width-digits; + if (needmore>0) { if (pctp && pctp[0] && pctp[1]=='0') { // %0 output.append(needmore, '0'); // Pre-pad zero } else { @@ -722,50 +722,50 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA break; } case 't': { // Time - int digits; - if (VL_TIME_MULTIPLIER==1) { - digits=sprintf(tmp,"%" VL_PRI64 "u",ld); - } else if (VL_TIME_MULTIPLIER==1000) { - digits=sprintf(tmp,"%" VL_PRI64 "u.%03" VL_PRI64 "u", + int digits; + if (VL_TIME_MULTIPLIER==1) { + digits=sprintf(tmp, "%" VL_PRI64 "u", ld); + } else if (VL_TIME_MULTIPLIER==1000) { + digits=sprintf(tmp, "%" VL_PRI64 "u.%03" VL_PRI64 "u", static_cast(ld/VL_TIME_MULTIPLIER), static_cast(ld%VL_TIME_MULTIPLIER)); - } else { - VL_FATAL_MT(__FILE__,__LINE__,"","Unsupported VL_TIME_MULTIPLIER"); - } + } else { + VL_FATAL_MT(__FILE__, __LINE__, "", "Unsupported VL_TIME_MULTIPLIER"); + } int needmore = width-digits; if (needmore>0) output.append(needmore, ' '); // Pre-pad spaces output += tmp; - break; - } - case 'b': - for (; lsb>=0; --lsb) { + break; + } + case 'b': + for (; lsb>=0; --lsb) { output += (VL_BITRSHIFT_W(lwp, lsb) & 1) + '0'; - } - break; - case 'o': + } + break; + case 'o': for (; lsb>=0; --lsb) { lsb = (lsb / 3) * 3; // Next digit // Octal numbers may span more than one wide word, - // so we need to grab each bit separately and check for overrun - // Octal is rare, so we'll do it a slow simple way - output += ('0' - + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+0)) ? 1 : 0) - + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+1)) ? 2 : 0) - + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+2)) ? 4 : 0)); - } - break; - case 'u': // Packed 2-state - output.reserve(output.size() + 4*VL_WORDS_I(lbits)); - for (int i=0; i((lwp[i] ) & 0xff); output += static_cast((lwp[i] >> 8) & 0xff); output += static_cast((lwp[i] >> 16) & 0xff); output += static_cast((lwp[i] >> 24) & 0xff); - } - break; - case 'z': // Packed 4-state - output.reserve(output.size() + 8*VL_WORDS_I(lbits)); - for (int i=0; i((lwp[i] ) & 0xff); output += static_cast((lwp[i] >> 8) & 0xff); output += static_cast((lwp[i] >> 16) & 0xff); @@ -783,13 +783,13 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA for (; lsb>=0; --lsb) { lsb = (lsb / 4) * 4; // Next digit IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xf; - output += "0123456789abcdef"[charval]; - } - break; - default: - std::string msg = std::string("Unknown _vl_vsformat code: ")+pos[0]; - VL_FATAL_MT(__FILE__,__LINE__,"",msg.c_str()); - break; + output += "0123456789abcdef"[charval]; + } + break; + default: + std::string msg = std::string("Unknown _vl_vsformat code: ")+pos[0]; + VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str()); + break; } // switch } } // switch @@ -808,80 +808,80 @@ static inline void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE { static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr) VL_MT_SAFE { // Get a character without advancing if (fp) { - int data = fgetc(fp); - if (data == EOF) return EOF; - ungetc(data,fp); - return data; + int data = fgetc(fp); + if (data == EOF) return EOF; + ungetc(data, fp); + return data; } else { if (floc < 0) return EOF; floc = floc & ~7; // Align to closest character if (fromp == NULL) { - return fstr[fstr.length()-1 - (floc>>3)]; - } else { + return fstr[fstr.length()-1 - (floc>>3)]; + } else { return VL_BITRSHIFT_W(fromp, floc) & 0xff; - } + } } } static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr) VL_MT_SAFE { while (1) { - int c = _vl_vsss_peek(fp, floc, fromp, fstr); - if (c==EOF || !isspace(c)) return; - _vl_vsss_advance(fp, floc); + int c = _vl_vsss_peek(fp, floc, fromp, fstr); + if (c==EOF || !isspace(c)) return; + _vl_vsss_advance(fp, floc); } } static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr, - char* tmpp, const char* acceptp) VL_MT_SAFE { + char* tmpp, const char* acceptp) VL_MT_SAFE { // Read into tmp, consisting of characters from acceptp list char* cp = tmpp; while (1) { - int c = _vl_vsss_peek(fp, floc, fromp, fstr); - if (c==EOF || isspace(c)) break; + int c = _vl_vsss_peek(fp, floc, fromp, fstr); + if (c==EOF || isspace(c)) break; if (acceptp // String - allow anything && NULL==strchr(acceptp, c)) break; if (acceptp) c = tolower(c); // Non-strings we'll simplify - *cp++ = c; - _vl_vsss_advance(fp, floc); + *cp++ = c; + _vl_vsss_advance(fp, floc); } *cp++ = '\0'; //VL_DBG_MSGF(" _read got='"<>=1) { - VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1); + VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1); } } static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, - const char* strp, size_t posstart, size_t posend) VL_MT_SAFE { + const char* strp, size_t posstart, size_t posend) VL_MT_SAFE { // Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits. int lsb = 0; for (int i=0, pos=static_cast(posend)-1; i=static_cast(posstart); --pos) { switch (tolower (strp[pos])) { case 'x': case 'z': case '?': // FALLTHRU case '0': lsb += baseLog2; break; - case '1': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 1); lsb+=baseLog2; break; - case '2': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 2); lsb+=baseLog2; break; - case '3': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 3); lsb+=baseLog2; break; - case '4': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 4); lsb+=baseLog2; break; - case '5': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 5); lsb+=baseLog2; break; - case '6': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 6); lsb+=baseLog2; break; - case '7': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 7); lsb+=baseLog2; break; - case '8': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 8); lsb+=baseLog2; break; - case '9': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 9); lsb+=baseLog2; break; - case 'a': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 10); lsb+=baseLog2; break; - case 'b': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 11); lsb+=baseLog2; break; - case 'c': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 12); lsb+=baseLog2; break; - case 'd': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 13); lsb+=baseLog2; break; - case 'e': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 14); lsb+=baseLog2; break; - case 'f': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 15); lsb+=baseLog2; break; - case '_': break; - } + case '1': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 1); lsb+=baseLog2; break; + case '2': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 2); lsb+=baseLog2; break; + case '3': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 3); lsb+=baseLog2; break; + case '4': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 4); lsb+=baseLog2; break; + case '5': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 5); lsb+=baseLog2; break; + case '6': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 6); lsb+=baseLog2; break; + case '7': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 7); lsb+=baseLog2; break; + case '8': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 8); lsb+=baseLog2; break; + case '9': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 9); lsb+=baseLog2; break; + case 'a': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 10); lsb+=baseLog2; break; + case 'b': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 11); lsb+=baseLog2; break; + case 'c': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 12); lsb+=baseLog2; break; + case 'd': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 13); lsb+=baseLog2; break; + case 'e': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 14); lsb+=baseLog2; break; + case 'f': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 15); lsb+=baseLog2; break; + case '_': break; + } } } IData _vl_vsscanf(FILE* fp, // If a fscanf - int fbits, WDataInP fromp, // Else if a sscanf - const std::string& fstr, // if a sscanf to string - const char* formatp, va_list ap) VL_MT_SAFE { + int fbits, WDataInP fromp, // Else if a sscanf + const std::string& fstr, // if a sscanf to string + const char* formatp, va_list ap) VL_MT_SAFE { // Read a Verilog $sscanf/$fscanf style format into the output list // The format must be pre-processed (and lower cased) by Verilator // Arguments are in "width, arg-value (or WDataIn* if wide)" form @@ -890,128 +890,128 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf IData got = 0; bool inPct = false; const char* pos = formatp; - for (; *pos && !_vl_vsss_eof(fp,floc); ++pos) { - //VL_DBG_MSGF("_vlscan fmt='"< VL_QUADSIZE) { - owp = va_arg(ap,WDataOutP); - } - for (int i=0; i(strlen(tmp)))-1; - int lsb = 0; - for (int i=0; i=0; --lpos) { - _vl_vsss_setbit(owp,obits,lsb, 8, tmp[lpos]); lsb+=8; - } - break; + // Skip loading spaces + inPct = false; + char fmt = pos[0]; + switch (fmt) { + case '%': { + int c = _vl_vsss_peek(fp, floc, fromp, fstr); + if (c != '%') goto done; + else _vl_vsss_advance(fp, floc); + break; + } + default: { + // Deal with all read-and-scan somethings + // Note LSBs are preserved if there's an overflow + const int obits = va_arg(ap, int); + WData qowp[2] = {0, 0}; + WDataOutP owp = qowp; + if (obits > VL_QUADSIZE) { + owp = va_arg(ap, WDataOutP); + } + for (int i=0; i(strlen(tmp)))-1; + int lsb = 0; + for (int i=0; i=0; --lpos) { + _vl_vsss_setbit(owp, obits, lsb, 8, tmp[lpos]); lsb+=8; + } + break; } case 'd': { // Signed decimal - _vl_vsss_skipspace(fp,floc,fromp,fstr); - _vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_"); - if (!tmp[0]) goto done; - vlsint64_t ld; - sscanf(tmp,"%30" VL_PRI64 "d",&ld); - VL_SET_WQ(owp,ld); - break; - } - case 'f': + _vl_vsss_skipspace(fp, floc, fromp, fstr); + _vl_vsss_read(fp, floc, fromp, fstr, tmp, "0123456789+-xXzZ?_"); + if (!tmp[0]) goto done; + vlsint64_t ld; + sscanf(tmp, "%30" VL_PRI64 "d",&ld); + VL_SET_WQ(owp, ld); + break; + } + case 'f': case 'e': case 'g': { // Real number - _vl_vsss_skipspace(fp,floc,fromp,fstr); - _vl_vsss_read(fp,floc,fromp,fstr, tmp, "+-.0123456789eE"); - if (!tmp[0]) goto done; - // cppcheck-suppress unusedStructMember // It's used - union { double r; vlsint64_t ld; } u; - u.r = strtod(tmp, NULL); - VL_SET_WQ(owp,u.ld); - break; - } + _vl_vsss_skipspace(fp, floc, fromp, fstr); + _vl_vsss_read(fp, floc, fromp, fstr, tmp, "+-.0123456789eE"); + if (!tmp[0]) goto done; + // cppcheck-suppress unusedStructMember // It's used + union { double r; vlsint64_t ld; } u; + u.r = strtod(tmp, NULL); + VL_SET_WQ(owp, u.ld); + break; + } case 't': // FALLTHRU // Time case '#': { // Unsigned decimal - _vl_vsss_skipspace(fp,floc,fromp,fstr); - _vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_"); - if (!tmp[0]) goto done; - QData ld; - sscanf(tmp,"%30" VL_PRI64 "u",&ld); - VL_SET_WQ(owp,ld); - break; - } - case 'b': { - _vl_vsss_skipspace(fp,floc,fromp,fstr); - _vl_vsss_read(fp,floc,fromp,fstr, tmp, "01xXzZ?_"); - if (!tmp[0]) goto done; - _vl_vsss_based(owp,obits, 1, tmp, 0, strlen(tmp)); - break; - } - case 'o': { - _vl_vsss_skipspace(fp,floc,fromp,fstr); - _vl_vsss_read(fp,floc,fromp,fstr, tmp, "01234567xXzZ?_"); - if (!tmp[0]) goto done; - _vl_vsss_based(owp,obits, 3, tmp, 0, strlen(tmp)); - break; - } - case 'x': { - _vl_vsss_skipspace(fp,floc,fromp,fstr); - _vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789abcdefABCDEFxXzZ?_"); - if (!tmp[0]) goto done; - _vl_vsss_based(owp,obits, 4, tmp, 0, strlen(tmp)); - break; - } - default: - std::string msg = std::string("Unknown _vl_vsscanf code: ")+pos[0]; - VL_FATAL_MT(__FILE__,__LINE__,"",msg.c_str()); + _vl_vsss_skipspace(fp, floc, fromp, fstr); + _vl_vsss_read(fp, floc, fromp, fstr, tmp, "0123456789+-xXzZ?_"); + if (!tmp[0]) goto done; + QData ld; + sscanf(tmp, "%30" VL_PRI64 "u",&ld); + VL_SET_WQ(owp, ld); + break; + } + case 'b': { + _vl_vsss_skipspace(fp, floc, fromp, fstr); + _vl_vsss_read(fp, floc, fromp, fstr, tmp, "01xXzZ?_"); + if (!tmp[0]) goto done; + _vl_vsss_based(owp, obits, 1, tmp, 0, strlen(tmp)); + break; + } + case 'o': { + _vl_vsss_skipspace(fp, floc, fromp, fstr); + _vl_vsss_read(fp, floc, fromp, fstr, tmp, "01234567xXzZ?_"); + if (!tmp[0]) goto done; + _vl_vsss_based(owp, obits, 3, tmp, 0, strlen(tmp)); + break; + } + case 'x': { + _vl_vsss_skipspace(fp, floc, fromp, fstr); + _vl_vsss_read(fp, floc, fromp, fstr, tmp, "0123456789abcdefABCDEFxXzZ?_"); + if (!tmp[0]) goto done; + _vl_vsss_based(owp, obits, 4, tmp, 0, strlen(tmp)); + break; + } + default: + std::string msg = std::string("Unknown _vl_vsscanf code: ")+pos[0]; + VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str()); break; } // switch - got++; - // Reload data if non-wide (if wide, we put it in the right place directly) - if (obits <= VL_BYTESIZE) { - CData* p = va_arg(ap,CData*); *p = owp[0]; - } else if (obits <= VL_SHORTSIZE) { - SData* p = va_arg(ap,SData*); *p = owp[0]; - } else if (obits <= VL_WORDSIZE) { - IData* p = va_arg(ap,IData*); *p = owp[0]; - } else if (obits <= VL_QUADSIZE) { - QData* p = va_arg(ap,QData*); *p = VL_SET_QW(owp); - } - } + got++; + // Reload data if non-wide (if wide, we put it in the right place directly) + if (obits <= VL_BYTESIZE) { + CData* p = va_arg(ap, CData*); *p = owp[0]; + } else if (obits <= VL_SHORTSIZE) { + SData* p = va_arg(ap, SData*); *p = owp[0]; + } else if (obits <= VL_WORDSIZE) { + IData* p = va_arg(ap, IData*); *p = owp[0]; + } else if (obits <= VL_QUADSIZE) { + QData* p = va_arg(ap, QData*); *p = VL_SET_QW(owp); + } + } } // switch } } @@ -1066,17 +1066,17 @@ IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE { char buffer[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; // V3Emit has static check that bytes < VL_TO_STRING_MAX_WORDS, but be safe if (VL_UNLIKELY(bytes > VL_TO_STRING_MAX_WORDS*VL_WORDSIZE)) { - VL_FATAL_MT(__FILE__,__LINE__,"","Internal: fgets buffer overrun"); + VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: fgets buffer overrun"); } // We don't use fgets, as we must read \0s. IData got = 0; char* cp = buffer; while (got < bytes) { - int c = getc(fp); // getc() is threadsafe - if (c==EOF) break; - *cp++ = c; got++; - if (c=='\n') break; + int c = getc(fp); // getc() is threadsafe + if (c==EOF) break; + *cp++ = c; got++; + if (c=='\n') break; } _VL_STRING_TO_VINT(obits, destp, got, buffer); @@ -1100,10 +1100,10 @@ IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) VL_MT_SAFE { _VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep); char modez[5]; _VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode); - return VL_FOPEN_S(filenamez,modez); + return VL_FOPEN_S(filenamez, modez); } IData VL_FOPEN_S(const char* filenamep, const char* modep) VL_MT_SAFE { - return VerilatedImp::fdNew(fopen(filenamep,modep)); + return VerilatedImp::fdNew(fopen(filenamep, modep)); } void VL_FCLOSE_I(IData fdi) VL_MT_SAFE { @@ -1118,7 +1118,7 @@ void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) VL_MT_SAFE static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); _vl_vsformat(output, formatp, ap); va_end(ap); @@ -1129,7 +1129,7 @@ void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...) VL_MT_SAFE static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); _vl_vsformat(output, formatp, ap); va_end(ap); @@ -1140,7 +1140,7 @@ void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...) VL_MT_SAFE static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); _vl_vsformat(output, formatp, ap); va_end(ap); @@ -1151,7 +1151,7 @@ void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...) VL_MT_SAFE static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); _vl_vsformat(output, formatp, ap); va_end(ap); @@ -1162,7 +1162,7 @@ void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) VL_MT_SAFE { static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); _vl_vsformat(output, formatp, ap); va_end(ap); @@ -1173,7 +1173,7 @@ void VL_SFORMAT_X(int obits_ignored, std::string &output, const char* formatp, . if (obits_ignored) {} output = ""; va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); _vl_vsformat(output, formatp, ap); va_end(ap); } @@ -1182,7 +1182,7 @@ std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE { static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); _vl_vsformat(output, formatp, ap); va_end(ap); @@ -1193,7 +1193,7 @@ void VL_WRITEF(const char* formatp, ...) VL_MT_SAFE { static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); _vl_vsformat(output, formatp, ap); va_end(ap); @@ -1208,7 +1208,7 @@ void VL_FWRITEF(IData fpi, const char* formatp, ...) VL_MT_SAFE { if (VL_UNLIKELY(!fp)) return; va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); _vl_vsformat(output, formatp, ap); va_end(ap); @@ -1221,7 +1221,7 @@ IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE { if (VL_UNLIKELY(!fp)) return 0; va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); IData got = _vl_vsscanf(fp, 0, NULL, "", formatp, ap); va_end(ap); return got; @@ -1231,7 +1231,7 @@ IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) VL_MT_SAFE { WData fnw[2]; VL_SET_WI(fnw, ld); va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); IData got = _vl_vsscanf(NULL, lbits, fnw, "", formatp, ap); va_end(ap); return got; @@ -1240,21 +1240,21 @@ IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) VL_MT_SAFE { WData fnw[2]; VL_SET_WQ(fnw, ld); va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); IData got = _vl_vsscanf(NULL, lbits, fnw, "", formatp, ap); va_end(ap); return got; } IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) VL_MT_SAFE { va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); IData got = _vl_vsscanf(NULL, lbits, lwp, "", formatp, ap); va_end(ap); return got; } IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_SAFE { va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); IData got = _vl_vsscanf(NULL, ld.length()*8, NULL, ld, formatp, ap); va_end(ap); return got; @@ -1589,22 +1589,22 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M bool done = false; char fmt = ' '; for (const char* posp = ld.c_str(); !done && *posp; ++posp) { - if (!inPct && posp[0]=='%') { - inPct = true; + if (!inPct && posp[0]=='%') { + inPct = true; } else if (!inPct) { // Normal text prefix += *posp; } else { // Format character - switch (tolower(*posp)) { - case '%': - prefix += *posp; - inPct = false; - break; - default: - fmt = *posp; - done = true; - break; - } - } + switch (tolower(*posp)) { + case '%': + prefix += *posp; + inPct = false; + break; + default: + fmt = *posp; + done = true; + break; + } + } } const std::string& match = VerilatedImp::argPlusMatch(prefix.c_str()); @@ -1614,32 +1614,32 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M VL_ZERO_RESET_W(rbits, rwp); switch (tolower(fmt)) { case 'd': - vlsint64_t lld; - sscanf(dp,"%30" VL_PRI64 "d",&lld); - VL_SET_WQ(rwp,lld); - break; + vlsint64_t lld; + sscanf(dp, "%30" VL_PRI64 "d",&lld); + VL_SET_WQ(rwp, lld); + break; case 'b': - _vl_vsss_based(rwp,rbits, 1, dp, 0, strlen(dp)); - break; + _vl_vsss_based(rwp, rbits, 1, dp, 0, strlen(dp)); + break; case 'o': - _vl_vsss_based(rwp,rbits, 3, dp, 0, strlen(dp)); - break; + _vl_vsss_based(rwp, rbits, 3, dp, 0, strlen(dp)); + break; case 'h': // FALLTHRU case 'x': - _vl_vsss_based(rwp,rbits, 4, dp, 0, strlen(dp)); + _vl_vsss_based(rwp, rbits, 4, dp, 0, strlen(dp)); break; case 's': // string/no conversion for (int i=0, lsb=0, posp=static_cast(strlen(dp))-1; i=0; --posp) { - _vl_vsss_setbit(rwp,rbits,lsb, 8, dp[posp]); lsb+=8; + _vl_vsss_setbit(rwp, rbits, lsb, 8, dp[posp]); lsb+=8; } break; case 'e': // FALLTHRU - Unsupported case 'f': // FALLTHRU - Unsupported case 'g': // FALLTHRU - Unsupported default: // Other simulators simply return 0 in these cases and don't error out - return 0; + return 0; } - _VL_CLEAN_INPLACE_W(rbits,rwp); + _VL_CLEAN_INPLACE_W(rbits, rwp); return 1; } IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_SAFE { @@ -1647,21 +1647,21 @@ IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_S bool inPct = false; bool done = false; for (const char* posp = ld.c_str(); !done && *posp; ++posp) { - if (!inPct && posp[0]=='%') { - inPct = true; + if (!inPct && posp[0]=='%') { + inPct = true; } else if (!inPct) { // Normal text prefix += *posp; } else { // Format character - switch (tolower(*posp)) { - case '%': - prefix += *posp; - inPct = false; - break; - default: - done = true; - break; - } - } + switch (tolower(*posp)) { + case '%': + prefix += *posp; + inPct = false; + break; + default: + done = true; + break; + } + } } const std::string& match = VerilatedImp::argPlusMatch(prefix.c_str()); const char* dp = match.c_str() + 1 /*leading + */ + prefix.length(); @@ -1722,9 +1722,9 @@ void Verilated::debug(int level) VL_MT_SAFE { s_s.s_debug = level; if (level) { #ifdef VL_DEBUG - VL_DEBUG_IF(VL_DBG_MSGF("- Verilated::debug is on. Message prefix indicates {,}.\n");); + VL_DEBUG_IF(VL_DBG_MSGF("- Verilated::debug is on. Message prefix indicates {,}.\n");); #else - VL_PRINTF_MT("- Verilated::debug attempted, but compiled without VL_DEBUG, so messages suppressed.\n"); + VL_PRINTF_MT("- Verilated::debug attempted, but compiled without VL_DEBUG, so messages suppressed.\n"); #endif } } @@ -1774,13 +1774,13 @@ const char* Verilated::catName(const char* n1, const char* n2) VL_MT_SAFE { static VL_THREAD_LOCAL size_t len = 0; size_t newlen = strlen(n1)+strlen(n2)+2; if (!strp || newlen > len) { - if (strp) delete [] strp; - strp = new char[newlen]; - len = newlen; + if (strp) delete [] strp; + strp = new char[newlen]; + len = newlen; } - strcpy(strp,n1); - if (*n1) strcat(strp,"."); - strcat(strp,n2); + strcpy(strp, n1); + if (*n1) strcat(strp, "."); + strcat(strp, n2); return strp; } @@ -1789,8 +1789,9 @@ void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE { if (s_flushCb == cb) {} // Ok - don't duplicate else if (!s_flushCb) { s_flushCb=cb; } else { - // Someday we may allow multiple callbacks ala atexit(), but until then - VL_FATAL_MT("unknown",0,"", "Verilated::flushCb called twice with different callbacks"); + // Someday we may allow multiple callbacks ala atexit(), but until then + VL_FATAL_MT("unknown", 0, "", + "Verilated::flushCb called twice with different callbacks"); } } @@ -1812,7 +1813,7 @@ void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE { VerilatedLockGuard lock(s_args.m_argMutex); s_args.argc = argc; s_args.argv = argv; - VerilatedImp::commandArgs(argc,argv); + VerilatedImp::commandArgs(argc, argv); } const char* Verilated::commandArgsPlusMatch(const char* prefixp) VL_MT_SAFE { @@ -1829,7 +1830,7 @@ void Verilated::overWidthError(const char* signame) VL_MT_SAFE { std::string msg = (std::string("Testbench C set input '") + signame + "' 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()); } void Verilated::mkdir(const char* dirname) VL_MT_UNSAFE { @@ -1888,7 +1889,7 @@ void VerilatedImp::internalsDump() VL_MT_SAFE { versionDump(); VL_PRINTF_MT(" Argv:"); for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) { - VL_PRINTF_MT(" %s",it->c_str()); + VL_PRINTF_MT(" %s", it->c_str()); } VL_PRINTF_MT("\n"); scopesDump(); @@ -2006,13 +2007,13 @@ VerilatedModule::~VerilatedModule() { vluint32_t VerilatedVarProps::entSize() const { vluint32_t size = 1; switch (vltype()) { - case VLVT_PTR: size=sizeof(void*); break; - case VLVT_UINT8: size=sizeof(CData); break; - case VLVT_UINT16: size=sizeof(SData); break; - case VLVT_UINT32: size=sizeof(IData); break; - case VLVT_UINT64: size=sizeof(QData); break; + case VLVT_PTR: size=sizeof(void*); break; + case VLVT_UINT8: size=sizeof(CData); break; + case VLVT_UINT16: size=sizeof(SData); break; + case VLVT_UINT32: size=sizeof(IData); break; + case VLVT_UINT64: size=sizeof(QData); break; case VLVT_WDATA: size=VL_WORDS_I(packed().elements())*sizeof(IData); break; - default: size=0; break; + default: size=0; break; } return size; } @@ -2063,7 +2064,7 @@ void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp, const m_symsp = symsp; char* namep = new char[strlen(prefixp)+strlen(suffixp)+2]; strcpy(namep, prefixp); - if (*prefixp && *suffixp) strcat(namep,"."); + if (*prefixp && *suffixp) strcat(namep, "."); strcat(namep, suffixp); m_namep = namep; VerilatedImp::scopeInsert(this); @@ -2074,23 +2075,24 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) VL_ // Insert a exported function into scope table int funcnum = VerilatedImp::exportInsert(namep); if (!finalize) { - // Need two passes so we know array size to create - // Alternative is to dynamically stretch the array, which is more code, and slower. - if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum+1; } + // Need two passes so we know array size to create + // Alternative is to dynamically stretch the array, which is more code, and slower. + if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum+1; } } else { - if (VL_UNLIKELY(funcnum >= m_funcnumMax)) { - VL_FATAL_MT(__FILE__,__LINE__,"","Internal: Bad funcnum vs. pre-finalize maximum"); + if (VL_UNLIKELY(funcnum >= m_funcnumMax)) { + VL_FATAL_MT(__FILE__, __LINE__, "", + "Internal: Bad funcnum vs. pre-finalize maximum"); } if (VL_UNLIKELY(!m_callbacksp)) { // First allocation m_callbacksp = new void* [m_funcnumMax]; - memset(m_callbacksp, 0, m_funcnumMax*sizeof(void*)); - } - m_callbacksp[funcnum] = cb; + memset(m_callbacksp, 0, m_funcnumMax*sizeof(void*)); + } + m_callbacksp[funcnum] = cb; } } void VerilatedScope::varInsert(int finalize, const char* namep, void* datap, - VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE { + VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE { // Grab dimensions // In the future we may just create a large table at emit time and statically construct from that. if (!finalize) return; @@ -2099,36 +2101,36 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap, VerilatedVar var(namep, datap, vltype, static_cast(vlflags), dims); va_list ap; - va_start(ap,dims); + va_start(ap, dims); for (int i=0; i=1 && i<=3) { var.m_unpacked[i-1].m_left = msb; var.m_unpacked[i-1].m_right = lsb; - } else { - // We could have a linked list of ranges, but really this whole thing needs - // to be generalized to support structs and unions, etc. - VL_FATAL_MT(__FILE__,__LINE__,"", + } else { + // We could have a linked list of ranges, but really this whole thing needs + // to be generalized to support structs and unions, etc. + VL_FATAL_MT(__FILE__, __LINE__, "", (std::string("Unsupported multi-dimensional public varInsert: ") + namep).c_str()); - } + } } va_end(ap); - m_varsp->insert(std::make_pair(namep,var)); + m_varsp->insert(std::make_pair(namep, var)); } // cppcheck-suppress unusedFunction // Used by applications VerilatedVar* VerilatedScope::varFind(const char* namep) const VL_MT_SAFE_POSTINIT { if (VL_LIKELY(m_varsp)) { - VerilatedVarNameMap::iterator it = m_varsp->find(namep); - if (VL_LIKELY(it != m_varsp->end())) { - return &(it->second); - } + VerilatedVarNameMap::iterator it = m_varsp->find(namep); + if (VL_LIKELY(it != m_varsp->end())) { + return &(it->second); + } } return NULL; } @@ -2136,35 +2138,35 @@ VerilatedVar* VerilatedScope::varFind(const char* namep) const VL_MT_SAFE_POSTIN void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE { // Slowpath - Called only when find has failed std::string msg = (std::string("Testbench C called '") - +VerilatedImp::exportName(funcnum) - +"' but scope wasn't set, perhaps due to dpi import call without 'context'"); - VL_FATAL_MT("unknown",0,"", msg.c_str()); + +VerilatedImp::exportName(funcnum) + +"' but scope wasn't set, perhaps due to dpi import call without 'context'"); + VL_FATAL_MT("unknown", 0, "", msg.c_str()); return NULL; } void* VerilatedScope::exportFindError(int funcnum) const { // Slowpath - Called only when find has failed std::string msg = (std::string("Testbench C called '") - +VerilatedImp::exportName(funcnum) - +"' but this DPI export function exists only in other scopes, not scope '" - +name()+"'"); - VL_FATAL_MT("unknown",0,"", msg.c_str()); + +VerilatedImp::exportName(funcnum) + +"' but this DPI export function exists only in other scopes, not scope '" + +name()+"'"); + VL_FATAL_MT("unknown", 0, "", msg.c_str()); return NULL; } void VerilatedScope::scopeDump() const { VL_PRINTF_MT(" SCOPE %p: %s\n", this, name()); for (int i=0; ivarsp()) { - for (VerilatedVarNameMap::const_iterator it = varsp->begin(); - it != varsp->end(); ++it) { - VL_PRINTF_MT(" VAR %p: %s\n", &(it->second), it->first); - } + for (VerilatedVarNameMap::const_iterator it = varsp->begin(); + it != varsp->end(); ++it) { + VL_PRINTF_MT(" VAR %p: %s\n", &(it->second), it->first); + } } } @@ -2174,7 +2176,7 @@ void VerilatedScope::scopeDump() const { #if defined(VL_THREADED) && defined(VL_DEBUG) void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE { VL_FATAL_MT(__FILE__, __LINE__, "", "Routine called that is single threaded, but called from" - " a different thread then the expected constructing thread"); + " a different thread then the expected constructing thread"); } #endif diff --git a/include/verilated.h b/include/verilated.h index 1008cceab..41e4483b3 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -16,9 +16,9 @@ /// \file /// \brief Verilator: Common include for all Verilated C files /// -/// This file is included automatically by Verilator at the top of -/// all C++ files it generates. It contains standard macros and -/// classes required by the Verilated code. +/// This file is included automatically by Verilator at the top of +/// all C++ files it generates. It contains standard macros and +/// classes required by the Verilated code. /// /// Code available from: http://www.veripool.org/verilator /// @@ -55,18 +55,18 @@ //========================================================================= // Basic types -// P // Packed data of bit type (C/S/I/Q/W) -typedef vluint8_t CData; ///< Verilated pack data, 1-8 bits -typedef vluint16_t SData; ///< Verilated pack data, 9-16 bits -typedef vluint32_t IData; ///< Verilated pack data, 17-32 bits -typedef vluint64_t QData; ///< Verilated pack data, 33-64 bits -typedef vluint32_t WData; ///< Verilated pack data, >64 bits, as an array -// float F // No typedef needed; Verilator uses float -// double D // No typedef needed; Verilator uses double -// string N // No typedef needed; Verilator uses string +// P // Packed data of bit type (C/S/I/Q/W) +typedef vluint8_t CData; ///< Verilated pack data, 1-8 bits +typedef vluint16_t SData; ///< Verilated pack data, 9-16 bits +typedef vluint32_t IData; ///< Verilated pack data, 17-32 bits +typedef vluint64_t QData; ///< Verilated pack data, 33-64 bits +typedef vluint32_t WData; ///< Verilated pack data, >64 bits, as an array +// float F // No typedef needed; Verilator uses float +// double D // No typedef needed; Verilator uses double +// string N // No typedef needed; Verilator uses string -typedef const WData* WDataInP; ///< Array input to a function -typedef WData* WDataOutP; ///< Array output from a function +typedef const WData* WDataInP; ///< Array input to a function +typedef WData* WDataOutP; ///< Array output from a function typedef void (*VerilatedVoidCb)(void); @@ -83,22 +83,22 @@ class VerilatedFstC; enum VerilatedVarType { VLVT_UNKNOWN=0, - VLVT_PTR, // Pointer to something - VLVT_UINT8, // AKA CData - VLVT_UINT16, // AKA SData - VLVT_UINT32, // AKA IData - VLVT_UINT64, // AKA QData - VLVT_WDATA, // AKA WData - VLVT_STRING // C++ string + VLVT_PTR, // Pointer to something + VLVT_UINT8, // AKA CData + VLVT_UINT16, // AKA SData + VLVT_UINT32, // AKA IData + VLVT_UINT64, // AKA QData + VLVT_WDATA, // AKA WData + VLVT_STRING // C++ string }; enum VerilatedVarFlags { VLVD_0 = 0, // None - VLVD_IN = 1, // == vpiInput - VLVD_OUT = 2, // == vpiOutput - VLVD_INOUT = 3, // == vpiInOut - VLVD_NODIR = 5, // == vpiNoDirection - VLVF_MASK_DIR = 7, // Bit mask for above directions + VLVD_IN = 1, // == vpiInput + VLVD_OUT = 2, // == vpiOutput + VLVD_INOUT = 3, // == vpiInOut + VLVD_NODIR = 5, // == vpiNoDirection + VLVF_MASK_DIR = 7, // Bit mask for above directions // Flags VLVF_PUB_RD = (1<<8), // Public readable VLVF_PUB_RW = (1<<9), // Public writable @@ -217,48 +217,48 @@ public: // Declare nets #ifndef VL_ST_SIG -# define VL_ST_SIG8(name, msb,lsb) CData name ///< Declare signal, 1-8 bits -# define VL_ST_SIG16(name, msb,lsb) SData name ///< Declare signal, 9-16 bits -# define VL_ST_SIG64(name, msb,lsb) QData name ///< Declare signal, 33-64 bits -# define VL_ST_SIG(name, msb,lsb) IData name ///< Declare signal, 17-32 bits -# define VL_ST_SIGW(name,msb,lsb,words) WData name[words] ///< Declare signal, 65+ bits +# define VL_ST_SIG8(name, msb,lsb) CData name ///< Declare signal, 1-8 bits +# define VL_ST_SIG16(name, msb,lsb) SData name ///< Declare signal, 9-16 bits +# define VL_ST_SIG64(name, msb,lsb) QData name ///< Declare signal, 33-64 bits +# define VL_ST_SIG(name, msb,lsb) IData name ///< Declare signal, 17-32 bits +# define VL_ST_SIGW(name,msb,lsb,words) WData name[words] ///< Declare signal, 65+ bits #endif #ifndef VL_SIG -# define VL_SIG8(name, msb,lsb) CData name ///< Declare signal, 1-8 bits -# define VL_SIG16(name, msb,lsb) SData name ///< Declare signal, 9-16 bits -# define VL_SIG64(name, msb,lsb) QData name ///< Declare signal, 33-64 bits -# define VL_SIG(name, msb,lsb) IData name ///< Declare signal, 17-32 bits -# define VL_SIGW(name, msb,lsb, words) WData name[words] ///< Declare signal, 65+ bits -# define VL_IN8(name, msb,lsb) CData name ///< Declare input signal, 1-8 bits -# define VL_IN16(name, msb,lsb) SData name ///< Declare input signal, 9-16 bits -# define VL_IN64(name, msb,lsb) QData name ///< Declare input signal, 33-64 bits -# define VL_IN(name, msb,lsb) IData name ///< Declare input signal, 17-32 bits -# define VL_INW(name, msb,lsb, words) WData name[words] ///< Declare input signal, 65+ bits -# define VL_INOUT8(name, msb,lsb) CData name ///< Declare bidir signal, 1-8 bits -# define VL_INOUT16(name, msb,lsb) SData name ///< Declare bidir signal, 9-16 bits -# define VL_INOUT64(name, msb,lsb) QData name ///< Declare bidir signal, 33-64 bits -# define VL_INOUT(name, msb,lsb) IData name ///< Declare bidir signal, 17-32 bits -# define VL_INOUTW(name, msb,lsb, words) WData name[words] ///< Declare bidir signal, 65+ bits -# define VL_OUT8(name, msb,lsb) CData name ///< Declare output signal, 1-8 bits -# define VL_OUT16(name, msb,lsb) SData name ///< Declare output signal, 9-16 bits -# define VL_OUT64(name, msb,lsb) QData name ///< Declare output signal, 33-64bits -# define VL_OUT(name, msb,lsb) IData name ///< Declare output signal, 17-32 bits -# define VL_OUTW(name, msb,lsb, words) WData name[words] ///< Declare output signal, 65+ bits +# define VL_SIG8(name, msb,lsb) CData name ///< Declare signal, 1-8 bits +# define VL_SIG16(name, msb,lsb) SData name ///< Declare signal, 9-16 bits +# define VL_SIG64(name, msb,lsb) QData name ///< Declare signal, 33-64 bits +# define VL_SIG(name, msb,lsb) IData name ///< Declare signal, 17-32 bits +# define VL_SIGW(name, msb,lsb, words) WData name[words] ///< Declare signal, 65+ bits +# define VL_IN8(name, msb,lsb) CData name ///< Declare input signal, 1-8 bits +# define VL_IN16(name, msb,lsb) SData name ///< Declare input signal, 9-16 bits +# define VL_IN64(name, msb,lsb) QData name ///< Declare input signal, 33-64 bits +# define VL_IN(name, msb,lsb) IData name ///< Declare input signal, 17-32 bits +# define VL_INW(name, msb,lsb, words) WData name[words] ///< Declare input signal, 65+ bits +# define VL_INOUT8(name, msb,lsb) CData name ///< Declare bidir signal, 1-8 bits +# define VL_INOUT16(name, msb,lsb) SData name ///< Declare bidir signal, 9-16 bits +# define VL_INOUT64(name, msb,lsb) QData name ///< Declare bidir signal, 33-64 bits +# define VL_INOUT(name, msb,lsb) IData name ///< Declare bidir signal, 17-32 bits +# define VL_INOUTW(name, msb,lsb, words) WData name[words] ///< Declare bidir signal, 65+ bits +# define VL_OUT8(name, msb,lsb) CData name ///< Declare output signal, 1-8 bits +# define VL_OUT16(name, msb,lsb) SData name ///< Declare output signal, 9-16 bits +# define VL_OUT64(name, msb,lsb) QData name ///< Declare output signal, 33-64bits +# define VL_OUT(name, msb,lsb) IData name ///< Declare output signal, 17-32 bits +# define VL_OUTW(name, msb,lsb, words) WData name[words] ///< Declare output signal, 65+ bits -# define VL_PIN_NOP(instname,pin,port) ///< Connect a pin, ala SP_PIN -# define VL_CELL(instname,type) ///< Declare a cell, ala SP_CELL +# define VL_PIN_NOP(instname,pin,port) ///< Connect a pin, ala SP_PIN +# define VL_CELL(instname,type) ///< Declare a cell, ala SP_CELL /// Declare a module, ala SC_MODULE -# define VL_MODULE(modname) class modname : public VerilatedModule +# define VL_MODULE(modname) class modname : public VerilatedModule /// Constructor, ala SC_CTOR -# define VL_CTOR(modname) modname(const char* __VCname="") +# define VL_CTOR(modname) modname(const char* __VCname="") /// Constructor declaration for C++, ala SP_CTOR_IMPL -# define VL_CTOR_IMP(modname) modname::modname(const char* __VCname) : VerilatedModule(__VCname) +# define VL_CTOR_IMP(modname) modname::modname(const char* __VCname) : VerilatedModule(__VCname) /// Constructor declaration for SystemC, ala SP_CTOR_IMPL -# define VL_SC_CTOR_IMP(modname) modname::modname(sc_module_name) +# define VL_SC_CTOR_IMP(modname) modname::modname(sc_module_name) #endif @@ -291,12 +291,12 @@ public: // But for internal use only class VerilatedScope { // Fastpath: - VerilatedSyms* m_symsp; ///< Symbol table - void** m_callbacksp; ///< Callback table pointer (Fastpath) - int m_funcnumMax; ///< Maxium function number stored (Fastpath) + VerilatedSyms* m_symsp; ///< Symbol table + void** m_callbacksp; ///< Callback table pointer (Fastpath) + int m_funcnumMax; ///< Maxium function number stored (Fastpath) // 4 bytes padding (on -m64), for rent. - VerilatedVarNameMap* m_varsp; ///< Variable map - const char* m_namep; ///< Scope name (Slowpath) + VerilatedVarNameMap* m_varsp; ///< Variable map + const char* m_namep; ///< Scope name (Slowpath) public: // But internals only - called from VerilatedModule's VerilatedScope(); @@ -304,7 +304,7 @@ public: // But internals only - called from VerilatedModule's void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp) VL_MT_UNSAFE; void exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE; void varInsert(int finalize, const char* namep, void* datap, - VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE; + VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE; // ACCESSORS const char* name() const { return m_namep; } inline VerilatedSyms* symsp() const { return m_symsp; } @@ -314,13 +314,13 @@ public: // But internals only - called from VerilatedModule's void* exportFindError(int funcnum) const; static void* exportFindNullError(int funcnum) VL_MT_SAFE; static inline void* exportFind(const VerilatedScope* scopep, int funcnum) VL_MT_SAFE { - if (VL_UNLIKELY(!scopep)) return exportFindNullError(funcnum); - if (VL_LIKELY(funcnum < scopep->m_funcnumMax)) { - // m_callbacksp must be declared, as Max'es are > 0 - return scopep->m_callbacksp[funcnum]; - } else { - return scopep->exportFindError(funcnum); - } + if (VL_UNLIKELY(!scopep)) return exportFindNullError(funcnum); + if (VL_LIKELY(funcnum < scopep->m_funcnumMax)) { + // m_callbacksp must be declared, as Max'es are > 0 + return scopep->m_callbacksp[funcnum]; + } else { + return scopep->exportFindError(funcnum); + } } }; @@ -332,15 +332,15 @@ class Verilated { // Slow path variables static VerilatedMutex m_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED - static VerilatedVoidCb s_flushCb; ///< Flush callback function + static VerilatedVoidCb s_flushCb; ///< Flush callback function static struct Serialized { // All these members serialized/deserialized // Fast path int s_debug; ///< See accessors... only when VL_DEBUG set - bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated - bool s_gotFinish; ///< A $finish statement executed - bool s_assertOn; ///< Assertions are enabled - bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported + bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated + bool s_gotFinish; ///< A $finish statement executed + bool s_assertOn; ///< Assertions are enabled + bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported // Slow path int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random int s_randSeed; ///< Random seed: 0=random @@ -363,8 +363,8 @@ class Verilated { // assumption is that the restore is allowed to pass different arguments static struct CommandArgValues { VerilatedMutex m_argMutex; ///< Mutex for s_args members, when VL_THREADED - int argc; - const char** argv; + int argc; + const char** argv; CommandArgValues() : argc(0), argv(NULL) {} ~CommandArgValues() {} } s_args; @@ -373,14 +373,14 @@ class Verilated { static VL_THREAD_LOCAL struct ThreadLocal { #ifdef VL_THREADED vluint32_t t_mtaskId; ///< Current mtask# executing on this thread - vluint32_t t_endOfEvalReqd; ///< Messages may be pending, thread needs endOf-eval calls + vluint32_t t_endOfEvalReqd; ///< Messages may be pending, thread needs endOf-eval calls #endif - const VerilatedScope* t_dpiScopep; ///< DPI context scope - const char* t_dpiFilename; ///< DPI context filename - int t_dpiLineno; ///< DPI context line number + const VerilatedScope* t_dpiScopep; ///< DPI context scope + const char* t_dpiFilename; ///< DPI context filename + int t_dpiLineno; ///< DPI context line number - ThreadLocal(); - ~ThreadLocal(); + ThreadLocal(); + ~ThreadLocal(); } t_s; private: @@ -405,9 +405,9 @@ public: #ifdef VL_DEBUG /// Return debug level /// When multithreaded this may not immediately react to another thread changing the level (no mutex) - static inline int debug() VL_MT_SAFE { return s_s.s_debug; } + static inline int debug() VL_MT_SAFE { return s_s.s_debug; } #else - static inline int debug() VL_PURE { return 0; } ///< Return constant 0 debug level, so C++'s optimizer rips up + static inline int debug() VL_PURE { return 0; } ///< Return constant 0 debug level, so C++'s optimizer rips up #endif /// Enable calculation of unused signals static void calcUnusedSigs(bool flag) VL_MT_SAFE; @@ -418,7 +418,7 @@ public: static bool gotFinish() VL_MT_SAFE { return s_s.s_gotFinish; } ///< Return if got a $finish /// Allow traces to at some point be enabled (disables some optimizations) static void traceEverOn(bool flag) VL_MT_SAFE { - if (flag) { calcUnusedSigs(flag); } + if (flag) { calcUnusedSigs(flag); } } /// Enable/disable assertions static void assertOn(bool flag) VL_MT_SAFE; @@ -484,9 +484,9 @@ public: // Internal: Get and set DPI context static const VerilatedScope* dpiScope() VL_MT_SAFE { return t_s.t_dpiScopep; } - static void dpiScope(const VerilatedScope* scopep) VL_MT_SAFE { t_s.t_dpiScopep=scopep; } + static void dpiScope(const VerilatedScope* scopep) VL_MT_SAFE { t_s.t_dpiScopep = scopep; } static void dpiContext(const VerilatedScope* scopep, const char* filenamep, int lineno) VL_MT_SAFE { - t_s.t_dpiScopep = scopep; t_s.t_dpiFilename = filenamep; t_s.t_dpiLineno = lineno; } + t_s.t_dpiScopep = scopep; t_s.t_dpiFilename = filenamep; t_s.t_dpiLineno = lineno; } static void dpiClearContext() VL_MT_SAFE { t_s.t_dpiScopep = NULL; } static bool dpiInContext() VL_MT_SAFE { return t_s.t_dpiScopep != NULL; } static const char* dpiFilenamep() VL_MT_SAFE { return t_s.t_dpiFilename; } @@ -590,7 +590,7 @@ extern IData VL_FOPEN_S(const char* filenamep, const char* modep); extern IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode); extern IData VL_FOPEN_QI(QData filename, IData mode); inline IData VL_FOPEN_II(IData filename, IData mode) VL_MT_SAFE { - return VL_FOPEN_QI(filename,mode); } + return VL_FOPEN_QI(filename, mode); } extern void VL_FCLOSE_I(IData fdi); @@ -603,7 +603,7 @@ extern void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwo QData filename, void* memp, IData start, IData end); inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwords, IData filename, void* memp, IData start, IData end) VL_MT_SAFE { - VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, filename,memp,start,end); } + VL_READMEM_Q(hex, width, depth, array_lsb, fnwords, filename, memp, start, end); } extern void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords, WDataInP filenamep, const void* memp, IData start, IData end); @@ -611,7 +611,7 @@ extern void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int fnw QData filename, const void* memp, IData start, IData end); inline void VL_WRITEMEM_I(bool hex, int width, int depth, int array_lsb, int fnwords, IData filename, const void* memp, IData start, IData end) VL_MT_SAFE { - VL_WRITEMEM_Q(hex, width,depth,array_lsb,fnwords, filename,memp,start,end); } + VL_WRITEMEM_Q(hex, width, depth, array_lsb, fnwords, filename, memp, start, end); } extern void VL_WRITEF(const char* formatp, ...); extern void VL_FWRITEF(IData fpi, const char* formatp, ...); @@ -688,7 +688,7 @@ static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { #define VL_SIGN_I(nbits,lhs) ((lhs) >> VL_BITBIT_I((nbits) - VL_UL(1))) #define VL_SIGN_Q(nbits,lhs) ((lhs) >> VL_BITBIT_Q((nbits) - VL_ULL(1))) #define VL_SIGN_W(nbits,rwp) ((rwp)[VL_BITWORD_I((nbits)-VL_UL(1))] >> VL_BITBIT_I((nbits)-VL_UL(1))) -#define VL_SIGNONES_I(nbits,lhs) (-(VL_SIGN_I(nbits,lhs))) +#define VL_SIGNONES_I(nbits,lhs) (-(VL_SIGN_I(nbits, lhs))) // Sign bit extended up to MSB, doesn't include unsigned portion // Optimization bug in GCC 3.3 returns different bitmasks to later states for @@ -738,8 +738,8 @@ extern double sc_time_stamp(); //========================================================================= // Functional macros/routines // These all take the form -// VL_func_IW(bits,bits,op,op) -// VL_func_WW(bits,bits,out,op,op) +// VL_func_IW(bits, bits, op, op) +// VL_func_WW(bits, bits, out, op, op) // The I/W indicates if it's a integer or wide for the output and each operand. // The bits indicate the bit width of the output and each operand. // If wide output, a temporary storage location is specified. @@ -753,17 +753,17 @@ extern double sc_time_stamp(); #define VL_CLEAN_QQ(obits,lbits,lhs) ((lhs) & VL_MASK_Q(obits)) // EMIT_RULE: VL_ASSIGNCLEAN: oclean=clean; obits==lbits; -#define VL_ASSIGNCLEAN_W(obits,owp,lwp) VL_CLEAN_WW(obits,obits,owp,lwp) +#define VL_ASSIGNCLEAN_W(obits,owp,lwp) VL_CLEAN_WW((obits), (obits), (owp), (lwp)) static inline WDataOutP _VL_CLEAN_INPLACE_W(int obits, WDataOutP owp) VL_MT_SAFE { int words = VL_WORDS_I(obits); owp[words-1] &= VL_MASK_I(obits); - return(owp); + return owp; } static inline WDataOutP VL_CLEAN_WW(int obits, int, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { int words = VL_WORDS_I(obits); for (int i=0; (i < (words-1)); ++i) owp[i] = lwp[i]; owp[words-1] = lwp[words-1] & VL_MASK_I(obits); - return(owp); + return owp; } static inline WDataOutP VL_ZERO_W(int obits, WDataOutP owp) VL_MT_SAFE { int words = VL_WORDS_I(obits); @@ -783,30 +783,30 @@ static inline WDataOutP VL_ALLONES_W(int obits, WDataOutP owp) VL_MT_SAFE { static inline WDataOutP VL_ASSIGN_W(int obits, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { int words = VL_WORDS_I(obits); for (int i=0; i < words; ++i) owp[i] = lwp[i]; - return(owp); + return owp; } // EMIT_RULE: VL_ASSIGNBIT: rclean=clean; static inline void VL_ASSIGNBIT_II(int, int bit, CData& lhsr, IData rhs) VL_PURE { lhsr = ((lhsr & ~(VL_UL(1)< _butemp = (svar).read(); \ for (int i=0; i < words; ++i) { \ int msb = ((i+1)*VL_WORDSIZE) - 1; \ msb = (msb >= (obits)) ? ((obits)-1) : msb; \ - (owp)[i] = _butemp.range(msb,i*VL_WORDSIZE).to_uint(); \ + (owp)[i] = _butemp.range(msb, i*VL_WORDSIZE).to_uint(); \ } \ (owp)[words-1] &= VL_MASK_I(obits); \ } @@ -913,51 +913,51 @@ static inline WDataOutP VL_EXTEND_WI(int obits, int, WDataOutP owp, IData ld) VL // Note for extracts that obits != lbits owp[0] = ld; for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0; - return(owp); + return owp; } static inline WDataOutP VL_EXTEND_WQ(int obits, int, WDataOutP owp, QData ld) VL_MT_SAFE { - VL_SET_WQ(owp,ld); + VL_SET_WQ(owp, ld); for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0; - return(owp); + return owp; } static inline WDataOutP VL_EXTEND_WW(int obits, int lbits, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { for (int i=0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i]; for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0; - return(owp); + return owp; } // EMIT_RULE: VL_EXTENDS: oclean=*dirty*; obits=lbits; // Sign extension; output dirty static inline IData VL_EXTENDS_II(int, int lbits, IData lhs) VL_PURE { - return VL_EXTENDSIGN_I(lbits,lhs) | lhs; + return VL_EXTENDSIGN_I(lbits, lhs) | lhs; } static inline QData VL_EXTENDS_QI(int, int lbits, QData lhs/*Q_as_need_extended*/) VL_PURE { - return VL_EXTENDSIGN_Q(lbits,lhs) | lhs; + return VL_EXTENDSIGN_Q(lbits, lhs) | lhs; } static inline QData VL_EXTENDS_QQ(int, int lbits, QData lhs) VL_PURE { - return VL_EXTENDSIGN_Q(lbits,lhs) | lhs; + return VL_EXTENDSIGN_Q(lbits, lhs) | lhs; } static inline WDataOutP VL_EXTENDS_WI(int obits, int lbits, WDataOutP owp, IData ld) VL_MT_SAFE { - IData sign = VL_SIGNONES_I(lbits,ld); + IData sign = VL_SIGNONES_I(lbits, ld); owp[0] = ld | (sign & ~VL_MASK_I(lbits)); for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = sign; - return(owp); + return owp; } static inline WDataOutP VL_EXTENDS_WQ(int obits, int lbits, WDataOutP owp, QData ld) VL_MT_SAFE { - VL_SET_WQ(owp,ld); - IData sign = VL_SIGNONES_I(lbits,owp[1]); + VL_SET_WQ(owp, ld); + IData sign = VL_SIGNONES_I(lbits, owp[1]); owp[1] |= sign & ~VL_MASK_I(lbits); for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = sign; - return(owp); + return owp; } static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { for (int i=0; i < VL_WORDS_I(lbits)-1; ++i) owp[i] = lwp[i]; - int lmsw=VL_WORDS_I(lbits)-1; - IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]); + int lmsw = VL_WORDS_I(lbits)-1; + IData sign = VL_SIGNONES_I(lbits, lwp[lmsw]); owp[lmsw] = lwp[lmsw] | (sign & ~VL_MASK_I(lbits)); for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); ++i) owp[i] = sign; - return(owp); + return owp; } //=================================================================== @@ -968,7 +968,7 @@ static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp, WData #define VL_REDAND_IQ(obits,lbits,lhs) ((lhs) == VL_MASK_Q(lbits)) static inline IData VL_REDAND_IW(int, int lbits, WDataInP lwp) VL_MT_SAFE { int words = VL_WORDS_I(lbits); - IData combine=lwp[0]; + IData combine = lwp[0]; for (int i=1; i < words-1; ++i) combine &= lwp[i]; combine &= ~VL_MASK_I(lbits) | lwp[words-1]; return ((~combine)==0); @@ -978,9 +978,9 @@ static inline IData VL_REDAND_IW(int, int lbits, WDataInP lwp) VL_MT_SAFE { #define VL_REDOR_I(lhs) ((lhs)!=0) #define VL_REDOR_Q(lhs) ((lhs)!=0) static inline IData VL_REDOR_W(int words, WDataInP lwp) VL_MT_SAFE { - IData equal=0; + IData equal = 0; for (int i=0; i < words; ++i) equal |= lwp[i]; - return(equal!=0); + return (equal != 0); } // EMIT_RULE: VL_REDXOR: oclean=dirty; obits=1; @@ -1060,13 +1060,13 @@ static inline IData VL_ONEHOT_Q(QData lhs) VL_PURE { return (((lhs & (lhs-1))==0) & (lhs!=0)); } static inline IData VL_ONEHOT_W(int words, WDataInP lwp) VL_MT_SAFE { - IData one=0; + IData one = 0; for (int i=0; (i < words); ++i) { - if (lwp[i]) { - if (one) return 0; - one = 1; - if (lwp[i] & (lwp[i]-1)) return 0; - } + if (lwp[i]) { + if (one) return 0; + one = 1; + if (lwp[i] & (lwp[i]-1)) return 0; + } } return one; } @@ -1078,13 +1078,13 @@ static inline IData VL_ONEHOT0_Q(QData lhs) VL_PURE { return ((lhs & (lhs-1))==0); } static inline IData VL_ONEHOT0_W(int words, WDataInP lwp) VL_MT_SAFE { - bool one=false; + bool one = false; for (int i=0; (i < words); ++i) { - if (lwp[i]) { - if (one) return 0; - one = true; - if (lwp[i] & (lwp[i]-1)) return 0; - } + if (lwp[i]) { + if (one) return 0; + one = true; + if (lwp[i] & (lwp[i]-1)) return 0; + } } return 1; } @@ -1093,28 +1093,28 @@ static inline IData VL_CLOG2_I(IData lhs) VL_PURE { // There are faster algorithms, or fls GCC4 builtins, but rarely used if (VL_UNLIKELY(!lhs)) return 0; lhs--; - int shifts=0; + int shifts = 0; for (; lhs!=0; ++shifts) lhs = lhs >> 1; return shifts; } static inline IData VL_CLOG2_Q(QData lhs) VL_PURE { if (VL_UNLIKELY(!lhs)) return 0; lhs--; - int shifts=0; + int shifts = 0; for (; lhs!=0; ++shifts) lhs = lhs >> VL_ULL(1); return shifts; } static inline IData VL_CLOG2_W(int words, WDataInP lwp) VL_MT_SAFE { - IData adjust = (VL_COUNTONES_W(words,lwp)==1) ? 0 : 1; + IData adjust = (VL_COUNTONES_W(words, lwp)==1) ? 0 : 1; for (int i=words-1; i>=0; --i) { - if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken - for (int bit=31; bit>=0; --bit) { - if (VL_UNLIKELY(VL_BITISSET_I(lwp[i],bit))) { - return i*VL_WORDSIZE + bit + adjust; - } - } - // Can't get here - one bit must be set - } + if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken + for (int bit=31; bit>=0; --bit) { + if (VL_UNLIKELY(VL_BITISSET_I(lwp[i], bit))) { + return i*VL_WORDSIZE + bit + adjust; + } + } + // Can't get here - one bit must be set + } } return 0; } @@ -1122,14 +1122,14 @@ static inline IData VL_CLOG2_W(int words, WDataInP lwp) VL_MT_SAFE { static inline IData VL_MOSTSETBITP1_W(int words, WDataInP lwp) VL_MT_SAFE { // MSB set bit plus one; similar to FLS. 0=value is zero for (int i=words-1; i>=0; --i) { - if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken - for (int bit=31; bit>=0; --bit) { - if (VL_UNLIKELY(VL_BITISSET_I(lwp[i],bit))) { - return i*VL_WORDSIZE + bit + 1; - } - } - // Can't get here - one bit must be set - } + if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken + for (int bit=31; bit>=0; --bit) { + if (VL_UNLIKELY(VL_BITISSET_I(lwp[i], bit))) { + return i*VL_WORDSIZE + bit + 1; + } + } + // Can't get here - one bit must be set + } } return 0; } @@ -1138,35 +1138,35 @@ static inline IData VL_MOSTSETBITP1_W(int words, WDataInP lwp) VL_MT_SAFE { // SIMPLE LOGICAL OPERATORS // EMIT_RULE: VL_AND: oclean=lclean||rclean; obits=lbits; lbits==rbits; -static inline WDataOutP VL_AND_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_AND_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=0; (i < words); ++i) owp[i] = (lwp[i] & rwp[i]); - return(owp); + return owp; } // EMIT_RULE: VL_OR: oclean=lclean&&rclean; obits=lbits; lbits==rbits; -static inline WDataOutP VL_OR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_OR_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=0; (i < words); ++i) owp[i] = (lwp[i] | rwp[i]); - return(owp); + return owp; } // EMIT_RULE: VL_CHANGEXOR: oclean=1; obits=32; lbits==rbits; -static inline IData VL_CHANGEXOR_W(int words, WDataInP lwp,WDataInP rwp) VL_MT_SAFE { +static inline IData VL_CHANGEXOR_W(int words, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { IData od = 0; for (int i=0; (i < words); ++i) od |= (lwp[i] ^ rwp[i]); return(od); } // EMIT_RULE: VL_XOR: oclean=lclean&&rclean; obits=lbits; lbits==rbits; -static inline WDataOutP VL_XOR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_XOR_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=0; (i < words); ++i) owp[i] = (lwp[i] ^ rwp[i]); - return(owp); + return owp; } // EMIT_RULE: VL_XNOR: oclean=dirty; obits=lbits; lbits==rbits; -static inline WDataOutP VL_XNOR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_XNOR_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=0; (i < words); ++i) owp[i] = (lwp[i] ^ ~rwp[i]); - return(owp); + return owp; } // EMIT_RULE: VL_NOT: oclean=dirty; obits=lbits; -static inline WDataOutP VL_NOT_W(int words, WDataOutP owp,WDataInP lwp) VL_MT_SAFE { +static inline WDataOutP VL_NOT_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { for (int i=0; i < words; ++i) owp[i] = ~(lwp[i]); - return(owp); + return owp; } //========================================================================= @@ -1178,32 +1178,32 @@ static inline WDataOutP VL_NOT_W(int words, WDataOutP owp,WDataInP lwp) VL_MT_SA // EMIT_RULE: VL_GT: oclean=clean; lclean==clean; rclean==clean; obits=1; lbits==rbits; // EMIT_RULE: VL_GTE: oclean=clean; lclean==clean; rclean==clean; obits=1; lbits==rbits; // EMIT_RULE: VL_LTE: oclean=clean; lclean==clean; rclean==clean; obits=1; lbits==rbits; -#define VL_NEQ_W(words,lwp,rwp) (!VL_EQ_W(words,lwp,rwp)) -#define VL_LT_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)<0) -#define VL_LTE_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)<=0) -#define VL_GT_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)>0) -#define VL_GTE_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)>=0) +#define VL_NEQ_W(words,lwp,rwp) (!VL_EQ_W(words,lwp,rwp)) +#define VL_LT_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)<0) +#define VL_LTE_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)<=0) +#define VL_GT_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)>0) +#define VL_GTE_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)>=0) // Output clean, AND MUST BE CLEAN static inline IData VL_EQ_W(int words, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { - int nequal=0; + int nequal = 0; for (int i=0; (i < words); ++i) nequal |= (lwp[i] ^ rwp[i]); - return(nequal==0); + return (nequal==0); } // Internal usage static inline int _VL_CMP_W(int words, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=words-1; i>=0; --i) { - if (lwp[i] > rwp[i]) return 1; - if (lwp[i] < rwp[i]) return -1; + if (lwp[i] > rwp[i]) return 1; + if (lwp[i] < rwp[i]) return -1; } return(0); // == } -#define VL_LTS_IWW(obits,lbits,rbbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)<0) -#define VL_LTES_IWW(obits,lbits,rbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)<=0) -#define VL_GTS_IWW(obits,lbits,rbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)>0) -#define VL_GTES_IWW(obits,lbits,rbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)>=0) +#define VL_LTS_IWW(obits,lbits,rbbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)<0) +#define VL_LTES_IWW(obits,lbits,rbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)<=0) +#define VL_GTS_IWW(obits,lbits,rbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)>0) +#define VL_GTES_IWW(obits,lbits,rbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)>=0) static inline IData VL_GTS_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE { // For lbits==32, this becomes just a single instruction, otherwise ~5. @@ -1253,10 +1253,10 @@ static inline IData VL_LTES_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PU static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { int words = VL_WORDS_I(lbits); - int i=words-1; + int i = words-1; // We need to flip sense if negative comparison - IData lsign = VL_SIGN_I(lbits,lwp[i]); - IData rsign = VL_SIGN_I(lbits,rwp[i]); + IData lsign = VL_SIGN_I(lbits, lwp[i]); + IData rsign = VL_SIGN_I(lbits, rwp[i]); if (!lsign && rsign) return 1; // + > - if (lsign && !rsign) return -1; // - < + for (; i>=0; --i) { @@ -1272,32 +1272,32 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { // EMIT_RULE: VL_MUL: oclean=dirty; lclean==clean; rclean==clean; // EMIT_RULE: VL_DIV: oclean=dirty; lclean==clean; rclean==clean; // EMIT_RULE: VL_MODDIV: oclean=dirty; lclean==clean; rclean==clean; -#define VL_DIV_III(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)/(rhs)) -#define VL_DIV_QQQ(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)/(rhs)) +#define VL_DIV_III(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)/(rhs)) +#define VL_DIV_QQQ(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)/(rhs)) #define VL_DIV_WWW(lbits,owp,lwp,rwp) (_vl_moddiv_w(lbits,owp,lwp,rwp,0)) -#define VL_MODDIV_III(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)%(rhs)) -#define VL_MODDIV_QQQ(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)%(rhs)) +#define VL_MODDIV_III(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)%(rhs)) +#define VL_MODDIV_QQQ(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)%(rhs)) #define VL_MODDIV_WWW(lbits,owp,lwp,rwp) (_vl_moddiv_w(lbits,owp,lwp,rwp,1)) -static inline WDataOutP VL_ADD_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_ADD_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { QData carry = 0; for (int i=0; i(lwp[i]) + static_cast(rwp[i]); - owp[i] = (carry & VL_ULL(0xffffffff)); - carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); + carry = carry + static_cast(lwp[i]) + static_cast(rwp[i]); + owp[i] = (carry & VL_ULL(0xffffffff)); + carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); } - return(owp); + return owp; } -static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_SUB_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { QData carry = 0; for (int i=0; i(lwp[i]) + static_cast(static_cast(~rwp[i])); - if (i==0) carry++; // Negation of temp2 - owp[i] = (carry & VL_ULL(0xffffffff)); - carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); + carry = carry + static_cast(lwp[i]) + static_cast(static_cast(~rwp[i])); + if (i==0) ++carry; // Negation of temp2 + owp[i] = (carry & VL_ULL(0xffffffff)); + carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); } - return(owp); + return owp; } // Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround, @@ -1309,42 +1309,42 @@ static inline QData VL_NEGATE_Q(QData data) VL_PURE { return -data; } static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { QData carry = 0; for (int i=0; i(static_cast(~lwp[i])); - if (i==0) carry++; // Negation of temp2 - owp[i] = (carry & VL_ULL(0xffffffff)); - carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); + carry = carry + static_cast(static_cast(~lwp[i])); + if (i==0) ++carry; // Negation of temp2 + owp[i] = (carry & VL_ULL(0xffffffff)); + carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); } - return(owp); + return owp; } -static inline WDataOutP VL_MUL_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_MUL_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=0; i(lwp[lword]) * static_cast(rwp[rword]); - for (int qword=lword+rword; qword(owp[qword]); - owp[qword] = (mul & VL_ULL(0xffffffff)); - mul = (mul >> VL_ULL(32)) & VL_ULL(0xffffffff); - } - } + for (int rword=0; rword(lwp[lword]) * static_cast(rwp[rword]); + for (int qword=lword+rword; qword(owp[qword]); + owp[qword] = (mul & VL_ULL(0xffffffff)); + mul = (mul >> VL_ULL(32)) & VL_ULL(0xffffffff); + } + } } // Last output word is dirty - return(owp); + return owp; } -static inline IData VL_MULS_III(int,int lbits,int, IData lhs,IData rhs) VL_PURE { +static inline IData VL_MULS_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE { vlsint32_t lhs_signed = VL_EXTENDS_II(32, lbits, lhs); vlsint32_t rhs_signed = VL_EXTENDS_II(32, lbits, rhs); return lhs_signed * rhs_signed; } -static inline QData VL_MULS_QQQ(int,int lbits,int, QData lhs,QData rhs) VL_PURE { +static inline QData VL_MULS_QQQ(int, int lbits, int, QData lhs, QData rhs) VL_PURE { vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); return lhs_signed * rhs_signed; } -static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lwp,WDataInP rwp) VL_MT_SAFE { +static inline WDataOutP VL_MULS_WWW(int, int lbits, int, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { int words = VL_WORDS_I(lbits); // cppcheck-suppress variableScope WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here @@ -1352,63 +1352,63 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw WData rwstore[VL_MULS_MAX_WORDS]; WDataInP lwusp = lwp; WDataInP rwusp = rwp; - IData lneg = VL_SIGN_I(lbits,lwp[words-1]); + IData lneg = VL_SIGN_I(lbits, lwp[words-1]); if (lneg) { // Negate lhs lwusp = lwstore; VL_NEGATE_W(words, lwstore, lwp); lwstore[words-1] &= VL_MASK_I(lbits); // Clean it } - IData rneg = VL_SIGN_I(lbits,rwp[words-1]); + IData rneg = VL_SIGN_I(lbits, rwp[words-1]); if (rneg) { // Negate rhs rwusp = rwstore; VL_NEGATE_W(words, rwstore, rwp); rwstore[words-1] &= VL_MASK_I(lbits); // Clean it } - VL_MUL_W(words,owp,lwusp,rwusp); + VL_MUL_W(words, owp, lwusp, rwusp); owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp) - QData carry = 0; - for (int i=0; i(static_cast(~owp[i])); - if (i==0) carry++; // Negation of temp2 - owp[i] = (carry & VL_ULL(0xffffffff)); - carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); - } - //Not needed: owp[words-1] |= 1<(static_cast(~owp[i])); + if (i==0) ++carry; // Negation of temp2 + owp[i] = (carry & VL_ULL(0xffffffff)); + carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); + } + //Not needed: owp[words-1] |= 1<0) power = power*power; - if (rhs & (VL_ULL(1)<0) power = power*power; + if (rhs & (VL_ULL(1)<0) power = power*power; - if (rhs & (VL_ULL(1)<0) power = power*power; + if (rhs & (VL_ULL(1)<>nbitsonright) & hinsmask); - } + owp[lword] = (owp[lword] & ~insmask) | ((ld<>nbitsonright) & hinsmask); + } } } @@ -1577,49 +1577,49 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int int lword = VL_BITWORD_I(lbit); int words = VL_WORDS_I(hbit-lbit+1); if (hoffset==VL_SIZEBITS_I && loffset==0) { - // Fast and common case, word based insertion - for (int i=0; i>nbitsonright; - IData od = (d & ~linsmask) | (owp[oword] & linsmask); - if (oword==hword) owp[oword] = (owp[oword] & ~hinsmask) | (od & hinsmask); - else owp[oword] = od; - } - } - } + IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0; + IData linsmask = (VL_MASK_I(31-loffset+1))<>nbitsonright; + IData od = (d & ~linsmask) | (owp[oword] & linsmask); + if (oword==hword) owp[oword] = (owp[oword] & ~hinsmask) | (od & hinsmask); + else owp[oword] = od; + } + } + } } } static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit, int lbit) VL_MT_SAFE { - WData lwp[2]; VL_SET_WQ(lwp,ld); - _VL_INSERT_WW(obits,owp,lwp,hbit,lbit); + WData lwp[2]; VL_SET_WQ(lwp, ld); + _VL_INSERT_WW(obits, owp, lwp, hbit, lbit); } // EMIT_RULE: VL_REPLICATE: oclean=clean>width32, dirty<=width32; lclean=clean; rclean==clean; @@ -1630,16 +1630,16 @@ static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit, i static inline IData VL_REPLICATE_III(int, int lbits, int, IData ld, IData rep) VL_PURE { IData returndata = ld; for (unsigned i=1; i < rep; ++i){ - returndata = returndata << lbits; - returndata |= ld; + returndata = returndata << lbits; + returndata |= ld; } return (returndata); } static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) VL_PURE { QData returndata = ld; for (unsigned i=1; i < rep; ++i){ - returndata = returndata << lbits; - returndata |= static_cast(ld); + returndata = returndata << lbits; + returndata |= static_cast(ld); } return (returndata); } @@ -1647,25 +1647,25 @@ static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int, WDataOutP owp, IData ld, IData rep) VL_MT_SAFE { owp[0] = ld; for (unsigned i=1; i < rep; ++i){ - _VL_INSERT_WI(obits,owp,ld,i*lbits+lbits-1,i*lbits); + _VL_INSERT_WI(obits, owp, ld, i*lbits+lbits-1, i*lbits); } - return(owp); + return owp; } static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int, WDataOutP owp, QData ld, IData rep) VL_MT_SAFE { - VL_SET_WQ(owp,ld); + VL_SET_WQ(owp, ld); for (unsigned i=1; i < rep; ++i){ - _VL_INSERT_WQ(obits,owp,ld,i*lbits+lbits-1,i*lbits); + _VL_INSERT_WQ(obits, owp, ld, i*lbits+lbits-1, i*lbits); } - return(owp); + return owp; } static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP owp, WDataInP lwp, IData rep) VL_MT_SAFE { for (int i=0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i]; for (unsigned i=1; i < rep; ++i){ - _VL_INSERT_WW(obits,owp,lwp,i*lbits+lbits-1,i*lbits); + _VL_INSERT_WW(obits, owp, lwp, i*lbits+lbits-1, i*lbits); } - return(owp); + return owp; } // Left stream operator. Output will always be clean. LHS and RHS must be clean. @@ -1712,8 +1712,8 @@ static inline IData VL_STREAML_FAST_III(int, int lbits, int, IData ld, IData rd_ case 3: ret = ((ret >> 8) & VL_UL(0x00ff00ff)) | ((ret & VL_UL(0x00ff00ff)) << 8); // FALLTHRU - case 4: - ret = ((ret >> 16) | (ret << 16)); + case 4: + ret = ((ret >> 16) | (ret << 16)); } return ret >> (VL_WORDSIZE - lbits); } @@ -1728,23 +1728,23 @@ static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_ ret = (ret & ~msbMask) | ((ret & msbMask) << ((VL_ULL(1) << rd_log2) - lbitsRem)); } switch (rd_log2) { - case 0: + case 0: ret = (((ret >> 1) & VL_ULL(0x5555555555555555)) | ((ret & VL_ULL(0x5555555555555555)) << 1)); // FALLTHRU - case 1: + case 1: ret = (((ret >> 2) & VL_ULL(0x3333333333333333)) | ((ret & VL_ULL(0x3333333333333333)) << 2)); // FALLTHRU - case 2: + case 2: ret = (((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f)) | ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4)); // FALLTHRU - case 3: + case 3: ret = (((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff)) | ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8)); // FALLTHRU - case 4: + case 4: ret = (((ret >> 16) & VL_ULL(0x0000ffff0000ffff)) | ((ret & VL_ULL(0x0000ffff0000ffff)) << 16)); // FALLTHRU - case 5: - ret = ((ret >> 32) | (ret << 32)); + case 5: + ret = ((ret >> 32) | (ret << 32)); } return ret >> (VL_QUADSIZE - lbits); } @@ -1755,7 +1755,7 @@ static inline IData VL_STREAML_III(int, int lbits, int, IData ld, IData rd) VL_P // Slice size should never exceed the lhs width IData mask = VL_MASK_I(rd); for (int istart=0; istart 0 ? ostart : 0; ret |= ((ld >> istart) & mask) << ostart; } @@ -1767,7 +1767,7 @@ static inline QData VL_STREAML_QQI(int, int lbits, int, QData ld, IData rd) VL_P // Slice size should never exceed the lhs width QData mask = VL_MASK_Q(rd); for (int istart=0; istart 0 ? ostart : 0; ret |= ((ld >> istart) & mask) << ostart; } @@ -1779,14 +1779,14 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData // Slice size should never exceed the lhs width int ssize = (rd < static_cast(lbits)) ? rd : (static_cast(lbits)); for (int istart=0; istart 0 ? ostart : 0; - for (int sbit=0; sbit(ld)<<(rbits) | static_cast(rd)) static inline WDataOutP VL_CONCAT_WII(int obits, int lbits, int rbits, - WDataOutP owp, IData ld,IData rd) VL_MT_SAFE { + WDataOutP owp, IData ld, IData rd) VL_MT_SAFE { owp[0] = rd; for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0; - _VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits); - return(owp); + _VL_INSERT_WI(obits, owp, ld, rbits+lbits-1, rbits); + return owp; } static inline WDataOutP VL_CONCAT_WWI(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE { owp[0] = rd; for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0; - _VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits); - return(owp); + _VL_INSERT_WW(obits, owp, lwp, rbits+lbits-1, rbits); + return owp; } static inline WDataOutP VL_CONCAT_WIW(int obits, int lbits, int rbits, WDataOutP owp, IData ld, WDataInP rwp) VL_MT_SAFE { for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i]; for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0; - _VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits); - return(owp); + _VL_INSERT_WI(obits, owp, ld, rbits+lbits-1, rbits); + return owp; } static inline WDataOutP VL_CONCAT_WIQ(int obits, int lbits, int rbits, WDataOutP owp, IData ld, QData rd) VL_MT_SAFE { - VL_SET_WQ(owp,rd); + VL_SET_WQ(owp, rd); for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0; - _VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits); - return(owp); + _VL_INSERT_WI(obits, owp, ld, rbits+lbits-1, rbits); + return owp; } static inline WDataOutP VL_CONCAT_WQI(int obits, int lbits, int rbits, WDataOutP owp, QData ld, IData rd) VL_MT_SAFE { owp[0] = rd; for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0; - _VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits); - return(owp); + _VL_INSERT_WQ(obits, owp, ld, rbits+lbits-1, rbits); + return owp; } static inline WDataOutP VL_CONCAT_WQQ(int obits, int lbits, int rbits, WDataOutP owp, QData ld, QData rd) VL_MT_SAFE { - VL_SET_WQ(owp,rd); + VL_SET_WQ(owp, rd); for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0; - _VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits); - return(owp); + _VL_INSERT_WQ(obits, owp, ld, rbits+lbits-1, rbits); + return owp; } static inline WDataOutP VL_CONCAT_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rd) VL_MT_SAFE { - VL_SET_WQ(owp,rd); + VL_SET_WQ(owp, rd); for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0; - _VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits); - return(owp); + _VL_INSERT_WW(obits, owp, lwp, rbits+lbits-1, rbits); + return owp; } static inline WDataOutP VL_CONCAT_WQW(int obits, int lbits, int rbits, WDataOutP owp, QData ld, WDataInP rwp) VL_MT_SAFE { for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i]; for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0; - _VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits); - return(owp); + _VL_INSERT_WQ(obits, owp, ld, rbits+lbits-1, rbits); + return owp; } static inline WDataOutP VL_CONCAT_WWW(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i]; for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0; - _VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits); - return(owp); + _VL_INSERT_WW(obits, owp, lwp, rbits+lbits-1, rbits); + return owp; } //=================================================================== @@ -1875,11 +1875,11 @@ static inline WDataOutP VL_CONCAT_WWW(int obits, int lbits, int rbits, // Static shift, used by internal functions // The output is the same as the input - it overlaps! -static inline void _VL_SHIFTL_INPLACE_W(int obits,WDataOutP iowp,IData rd/*1 or 4*/) VL_MT_SAFE { +static inline void _VL_SHIFTL_INPLACE_W(int obits, WDataOutP iowp, IData rd/*1 or 4*/) VL_MT_SAFE { int words = VL_WORDS_I(obits); IData linsmask = VL_MASK_I(rd); for (int i=words-1; i>=1; --i) { - iowp[i] = ((iowp[i]<> (32-rd)) & linsmask); + iowp[i] = ((iowp[i]<> (32-rd)) & linsmask); } iowp[0] = ((iowp[0]<= static_cast(obits)) { // rd may be huge with MSB set - for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0; + for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0; } else if (bit_shift==0) { // Aligned word shift (<<0,<<32,<<64 etc) - for (int i=0; i < word_shift; ++i) owp[i] = 0; - for (int i=word_shift; i < VL_WORDS_I(obits); ++i) owp[i] = lwp[i-word_shift]; + for (int i=0; i < word_shift; ++i) owp[i] = 0; + for (int i=word_shift; i < VL_WORDS_I(obits); ++i) owp[i] = lwp[i-word_shift]; } else { - for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0; - _VL_INSERT_WW(obits,owp,lwp,obits-1,rd); + for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0; + _VL_INSERT_WW(obits, owp, lwp, obits-1, rd); } - return(owp); + return owp; } static inline WDataOutP VL_SHIFTL_WWW(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { @@ -1909,15 +1909,15 @@ static inline WDataOutP VL_SHIFTL_WWW(int obits, int lbits, int rbits, return VL_ZERO_W(obits, owp); } } - return VL_SHIFTL_WWI(obits,lbits,32,owp,lwp,rwp[0]); + return VL_SHIFTL_WWI(obits, lbits, 32, owp, lwp, rwp[0]); } -static inline IData VL_SHIFTL_IIW(int obits,int,int rbits,IData lhs, WDataInP rwp) VL_MT_SAFE { +static inline IData VL_SHIFTL_IIW(int obits, int, int rbits, IData lhs, WDataInP rwp) VL_MT_SAFE { for (int i=1; i < VL_WORDS_I(rbits); ++i) { if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more return 0; } } - return VL_CLEAN_II(obits,obits,lhs<= static_cast(obits)) { // rd may be huge with MSB set - for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0; + for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0; } else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc) - int copy_words = (VL_WORDS_I(obits)-word_shift); - for (int i=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift]; - for (int i=copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = 0; + int copy_words = (VL_WORDS_I(obits)-word_shift); + for (int i=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift]; + for (int i=copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = 0; } else { - int loffset = rd & VL_SIZEBITS_I; - int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0) - // Middle words - int words = VL_WORDS_I(obits-rd); - for (int i=0; i>loffset; - int upperword = i+word_shift+1; - if (upperword < VL_WORDS_I(obits)) { - owp[i] |= lwp[upperword]<< nbitsonright; - } - } - for (int i=words; i>loffset; + int upperword = i+word_shift+1; + if (upperword < VL_WORDS_I(obits)) { + owp[i] |= lwp[upperword]<< nbitsonright; + } + } + for (int i=words; i>rwp[0]); + return VL_CLEAN_II(obits, obits, lhs>>rwp[0]); } static inline QData VL_SHIFTR_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE { for (int i=1; i < VL_WORDS_I(rbits); ++i) { @@ -1993,12 +1993,12 @@ static inline IData VL_SHIFTRS_III(int obits, int lbits, int, IData lhs, IData r // an EXTEND(SHIFTRS(...)) can became a SHIFTRS(...) within same 32/64 bit word length IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative IData signext = ~(VL_MASK_I(lbits) >> rhs); // One with bits where we've shifted "past" - return (lhs >> rhs) | (sign & VL_CLEAN_II(obits,obits,signext)); + return (lhs >> rhs) | (sign & VL_CLEAN_II(obits, obits, signext)); } static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData rhs) VL_PURE { QData sign = -(lhs >> (lbits-1)); QData signext = ~(VL_MASK_Q(lbits) >> rhs); - return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext)); + return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits, obits, signext)); } static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, QData lhs, IData rhs) VL_PURE { @@ -2009,74 +2009,74 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int, int word_shift = VL_BITWORD_I(rd); int bit_shift = VL_BITBIT_I(rd); int lmsw = VL_WORDS_I(obits)-1; - IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]); + IData sign = VL_SIGNONES_I(lbits, lwp[lmsw]); if (rd >= static_cast(obits)) { // Shifting past end, sign in all of lbits - for (int i=0; i <= lmsw; ++i) owp[i] = sign; - owp[lmsw] &= VL_MASK_I(lbits); + for (int i=0; i <= lmsw; ++i) owp[i] = sign; + owp[lmsw] &= VL_MASK_I(lbits); } else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc) - int copy_words = (VL_WORDS_I(obits)-word_shift); - for (int i=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift]; - if (copy_words>=0) owp[copy_words-1] |= ~VL_MASK_I(obits) & sign; - for (int i=copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = sign; - owp[lmsw] &= VL_MASK_I(lbits); + int copy_words = (VL_WORDS_I(obits)-word_shift); + for (int i=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift]; + if (copy_words>=0) owp[copy_words-1] |= ~VL_MASK_I(obits) & sign; + for (int i=copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = sign; + owp[lmsw] &= VL_MASK_I(lbits); } else { - int loffset = rd & VL_SIZEBITS_I; - int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0) - // Middle words - int words = VL_WORDS_I(obits-rd); - for (int i=0; i>loffset; - int upperword = i+word_shift+1; - if (upperword < VL_WORDS_I(obits)) { - owp[i] |= lwp[upperword]<< nbitsonright; - } - } - if (words) owp[words-1] |= sign & ~VL_MASK_I(obits-loffset); - for (int i=words; i>loffset; + int upperword = i+word_shift+1; + if (upperword < VL_WORDS_I(obits)) { + owp[i] |= lwp[upperword]<< nbitsonright; + } + } + if (words) owp[words-1] |= sign & ~VL_MASK_I(obits-loffset); + for (int i=words; i>32 or more int lmsw = VL_WORDS_I(obits)-1; - IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]); - for (int j=0; j <= lmsw; ++j) owp[j] = sign; - owp[lmsw] &= VL_MASK_I(lbits); - return owp; - } + IData sign = VL_SIGNONES_I(lbits, lwp[lmsw]); + for (int j=0; j <= lmsw; ++j) owp[j] = sign; + owp[lmsw] &= VL_MASK_I(lbits); + return owp; + } } - return VL_SHIFTRS_WWI(obits,lbits,32,owp,lwp,rwp[0]); + return VL_SHIFTRS_WWI(obits, lbits, 32, owp, lwp, rwp[0]); } static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits, IData lhs, WDataInP rwp) VL_MT_SAFE { for (int i=1; i < VL_WORDS_I(rbits); ++i) { if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative - return VL_CLEAN_II(obits,obits,sign); + return VL_CLEAN_II(obits, obits, sign); } } - return VL_SHIFTRS_III(obits,lbits,32,lhs,rwp[0]); + return VL_SHIFTRS_III(obits, lbits, 32, lhs, rwp[0]); } static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE { for (int i=1; i < VL_WORDS_I(rbits); ++i) { if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more QData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative - return VL_CLEAN_QQ(obits,obits,sign); + return VL_CLEAN_QQ(obits, obits, sign); } } - return VL_SHIFTRS_QQI(obits,lbits,32,lhs,rwp[0]); + return VL_SHIFTRS_QQI(obits, lbits, 32, lhs, rwp[0]); } -static inline IData VL_SHIFTRS_IIQ(int obits,int lbits,int rbits,IData lhs, QData rhs) VL_PURE { - WData rwp[2]; VL_SET_WQ(rwp,rhs); - return VL_SHIFTRS_IIW(obits,lbits,rbits,lhs,rwp); +static inline IData VL_SHIFTRS_IIQ(int obits, int lbits, int rbits, IData lhs, QData rhs) VL_PURE { + WData rwp[2]; VL_SET_WQ(rwp, rhs); + return VL_SHIFTRS_IIW(obits, lbits, rbits, lhs, rwp); } -static inline QData VL_SHIFTRS_QQQ(int obits,int lbits,int rbits,QData lhs, QData rhs) VL_PURE { - WData rwp[2]; VL_SET_WQ(rwp,rhs); - return VL_SHIFTRS_QQW(obits,lbits,rbits,lhs,rwp); +static inline QData VL_SHIFTRS_QQQ(int obits, int lbits, int rbits, QData lhs, QData rhs) VL_PURE { + WData rwp[2]; VL_SET_WQ(rwp, rhs); + return VL_SHIFTRS_QQW(obits, lbits, rbits, lhs, rwp); } //=================================================================== @@ -2094,7 +2094,7 @@ static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData return ~0; // Spec says you can go outside the range of a array. Don't coredump if so. // We return all 1's as that's more likely to find bugs (?) than 0's. } else { - return (lwp[word]>>VL_BITBIT_I(rd)); + return (lwp[word]>>VL_BITBIT_I(rd)); } } @@ -2112,9 +2112,9 @@ static inline IData VL_SEL_IWII(int, int lbits, int, int, } else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast(lsb))) { return VL_BITRSHIFT_W(lwp, lsb); } else { - // 32 bit extraction may span two words - int nbitsfromlow = 32-VL_BITBIT_I(lsb); // bits that come from low word - return ((lwp[VL_BITWORD_I(msb)]<(lsb))) { return VL_BITRSHIFT_W(lwp, lsb); } else if (VL_BITWORD_I(msb)==1+VL_BITWORD_I(static_cast(lsb))) { - int nbitsfromlow = 32-VL_BITBIT_I(lsb); - QData hi = (lwp[VL_BITWORD_I(msb)]); - QData lo = VL_BITRSHIFT_W(lwp, lsb); - return (hi<>loffset; - int upperword = i+word_shift+1; - if (upperword <= static_cast(VL_BITWORD_I(msb))) { - owp[i] |= lwp[upperword]<< nbitsfromlow; - } - } - for (int i=words; i>loffset; + int upperword = i+word_shift+1; + if (upperword <= static_cast(VL_BITWORD_I(msb))) { + owp[i] |= lwp[upperword]<< nbitsfromlow; + } + } + for (int i=words; i= rhs width static inline void VL_ASSIGNSEL_WIII(int obits, int lsb, WDataOutP owp, IData rhs) VL_MT_SAFE { _VL_INSERT_WI(obits, owp, rhs, lsb+obits-1, lsb); @@ -2207,10 +2207,11 @@ static inline void VL_ASSIGNSEL_WIIW(int obits, int lsb, WDataOutP owp, WDataInP // Triops static inline WDataOutP VL_COND_WIWW(int obits, int, int, int, - WDataOutP owp, int cond, WDataInP w1p, WDataInP w2p) VL_MT_SAFE { + WDataOutP owp, int cond, + WDataInP w1p, WDataInP w2p) VL_MT_SAFE { int words = VL_WORDS_I(obits); for (int i=0; i < words; ++i) owp[i] = cond ? w1p[i] : w2p[i]; - return(owp); + return owp; } //====================================================================== @@ -2227,40 +2228,44 @@ static inline WDataOutP VL_COND_WIWW(int obits, int, int, int, return o static inline WDataOutP VL_CONST_W_1X(int obits, WDataOutP o, - IData d0) VL_MT_SAFE { + IData d0) VL_MT_SAFE { o[0]=d0; _END(obits,1); } static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o, - IData d1,IData d0) VL_MT_SAFE { + IData d1, IData d0) VL_MT_SAFE { o[0]=d0; o[1]=d1; _END(obits,2); } static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o, - IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d2, IData d1, IData d0) VL_MT_SAFE { o[0]=d0; o[1]=d1; o[2]=d2; _END(obits,3); } static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o, - IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; _END(obits,4); } static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o, - IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d4, + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; _END(obits,5); } static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o, - IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d5, IData d4, + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; _END(obits,6); } static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o, - IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d6, IData d5, IData d4, + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; _END(obits,7); } static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o, - IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE { + IData d7, IData d6, IData d5, IData d4, + IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; _END(obits,8); } // static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase, - IData d0) VL_MT_SAFE { + IData d0) VL_MT_SAFE { WDataOutP o = obase + VL_WORDS_I(lsb); o[0]=d0; _END(obits,1); } diff --git a/include/verilated_imp.h b/include/verilated_imp.h index 34164636d..35eb12d0a 100644 --- a/include/verilated_imp.h +++ b/include/verilated_imp.h @@ -92,32 +92,32 @@ public: // METHODS //// Add message to queue (called by producer) void post(const VerilatedMsg& msg) VL_EXCLUDES(m_mutex) { - VerilatedLockGuard lock(m_mutex); - m_queue.insert(msg); // Pass by value to copy the message into queue - ++m_depth; + VerilatedLockGuard lock(m_mutex); + m_queue.insert(msg); // Pass by value to copy the message into queue + ++m_depth; } /// Service queue until completion (called by consumer) void process() VL_EXCLUDES(m_mutex) { - // Tracking m_depth is redundant to e.g. getting the mutex and looking at queue size, - // but on the reader side it's 4x faster to test an atomic then getting a mutex - while (m_depth) { - // Wait for a message to be added to the queue - // We don't use unique_lock as want to unlock with the message copy still in scope + // Tracking m_depth is redundant to e.g. getting the mutex and looking at queue size, + // but on the reader side it's 4x faster to test an atomic then getting a mutex + while (m_depth) { + // Wait for a message to be added to the queue + // We don't use unique_lock as want to unlock with the message copy still in scope m_mutex.lock(); assert(!m_queue.empty()); // Otherwise m_depth is wrong // Unfortunately to release the lock we need to copy the message - // (Or have the message be a pointer, but then new/delete cost on each message) - // We assume messages are small, so copy - auto it = m_queue.begin(); - const VerilatedMsg msg = *(it); - m_queue.erase(it); - m_mutex.unlock(); - m_depth--; // Ok if outside critical section as only this code checks the value - { + // (Or have the message be a pointer, but then new/delete cost on each message) + // We assume messages are small, so copy + auto it = m_queue.begin(); + const VerilatedMsg msg = *(it); + m_queue.erase(it); + m_mutex.unlock(); + m_depth--; // Ok if outside critical section as only this code checks the value + { VL_DEBUG_IF(VL_DBG_MSGF("Executing callback from mtaskId=%d\n", msg.mtaskId());); msg.run(); - } - } + } + } } }; @@ -128,15 +128,15 @@ public: // CONSTRUCTORS VerilatedThreadMsgQueue() { } ~VerilatedThreadMsgQueue() { - // The only call of this with a non-empty queue is a fatal error. - // So this does not flush the queue, as the destination queue is not known to this class. + // The only call of this with a non-empty queue is a fatal error. + // So this does not flush the queue, as the destination queue is not known to this class. } private: VL_UNCOPYABLE(VerilatedThreadMsgQueue); // METHODS static VerilatedThreadMsgQueue& threadton() { - static VL_THREAD_LOCAL VerilatedThreadMsgQueue t_s; - return t_s; + static VL_THREAD_LOCAL VerilatedThreadMsgQueue t_s; + return t_s; } public: /// Add message to queue, called by producer @@ -153,11 +153,11 @@ public: } /// Push all messages to the eval's queue static void flush(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE { - while (!threadton().m_queue.empty()) { - evalMsgQp->post(threadton().m_queue.front()); - threadton().m_queue.pop(); - Verilated::endOfEvalReqdDec(); - } + while (!threadton().m_queue.empty()) { + evalMsgQp->post(threadton().m_queue.front()); + threadton().m_queue.pop(); + Verilated::endOfEvalReqdDec(); + } } }; #endif // VL_THREADED @@ -200,11 +200,11 @@ class VerilatedImp { public: // But only for verilated*.cpp // CONSTRUCTORS VerilatedImp() - : m_argVecLoaded(false), m_exportNext(0) { - m_fdps.resize(3); - m_fdps[0] = stdin; - m_fdps[1] = stdout; - m_fdps[2] = stderr; + : m_argVecLoaded(false), m_exportNext(0) { + m_fdps.resize(3); + m_fdps[0] = stdin; + m_fdps[1] = stdout; + m_fdps[2] = stderr; } ~VerilatedImp() {} private: @@ -219,21 +219,21 @@ public: static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex); static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex); static std::string argPlusMatch(const char* prefixp) VL_EXCLUDES(s_s.m_argMutex) { - VerilatedLockGuard lock(s_s.m_argMutex); - // Note prefixp does not include the leading "+" - size_t len = strlen(prefixp); - if (VL_UNLIKELY(!s_s.m_argVecLoaded)) { - s_s.m_argVecLoaded = true; // Complain only once - VL_FATAL_MT("unknown",0,"", - "%Error: Verilog called $test$plusargs or $value$plusargs without" - " testbench C first calling Verilated::commandArgs(argc,argv)."); - } - for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) { - if ((*it)[0]=='+') { - if (0==strncmp(prefixp, it->c_str()+1, len)) return *it; - } - } - return ""; + VerilatedLockGuard lock(s_s.m_argMutex); + // Note prefixp does not include the leading "+" + size_t len = strlen(prefixp); + if (VL_UNLIKELY(!s_s.m_argVecLoaded)) { + s_s.m_argVecLoaded = true; // Complain only once + VL_FATAL_MT("unknown", 0, "", + "%Error: Verilog called $test$plusargs or $value$plusargs without" + " testbench C first calling Verilated::commandArgs(argc,argv)."); + } + for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) { + if ((*it)[0]=='+') { + if (0==strncmp(prefixp, it->c_str()+1, len)) return *it; + } + } + return ""; } private: static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex); @@ -247,75 +247,77 @@ public: // There's often many more scopes than userdata's and thus having a ~48byte // per map overhead * N scopes would take much more space and cache thrashing. static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE { - VerilatedLockGuard lock(s_s.m_userMapMutex); - UserMap::iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey)); - if (it != s_s.m_userMap.end()) it->second = userData; - // When we support VL_THREADs, we need a lock around this insert, as it's runtime - else s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep,userKey),userData)); + VerilatedLockGuard lock(s_s.m_userMapMutex); + UserMap::iterator it=s_s.m_userMap.find(std::make_pair(scopep, userKey)); + if (it != s_s.m_userMap.end()) it->second = userData; + // When we support VL_THREADs, we need a lock around this insert, as it's runtime + else s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), userData)); } static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE { - VerilatedLockGuard lock(s_s.m_userMapMutex); - UserMap::const_iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey)); - if (VL_LIKELY(it != s_s.m_userMap.end())) return it->second; - else return NULL; + VerilatedLockGuard lock(s_s.m_userMapMutex); + UserMap::const_iterator it=s_s.m_userMap.find(std::make_pair(scopep, userKey)); + if (VL_LIKELY(it != s_s.m_userMap.end())) return it->second; + else return NULL; } private: /// Symbol table destruction cleans up the entries for each scope. static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE { - // Slow ok - called once/scope on destruction, so we simply iterate. - VerilatedLockGuard lock(s_s.m_userMapMutex); - for (UserMap::iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ) { - if (it->first.first == scopep) { - s_s.m_userMap.erase(it++); - } else { - ++it; - } - } + // Slow ok - called once/scope on destruction, so we simply iterate. + VerilatedLockGuard lock(s_s.m_userMapMutex); + for (UserMap::iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ) { + if (it->first.first == scopep) { + s_s.m_userMap.erase(it++); + } else { + ++it; + } + } } static void userDump() VL_MT_SAFE { - VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump - bool first = true; - for (UserMap::const_iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) { - if (first) { VL_PRINTF_MT(" userDump:\n"); first=false; } - VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n", - it->first.first, it->first.second, it->second); - } + VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump + bool first = true; + for (UserMap::const_iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) { + if (first) { VL_PRINTF_MT(" userDump:\n"); first=false; } + VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n", + it->first.first, it->first.second, it->second); + } } public: // But only for verilated*.cpp // METHODS - scope name static void scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE { - // Slow ok - called once/scope at construction - VerilatedLockGuard lock(s_s.m_nameMutex); - VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name()); - if (it == s_s.m_nameMap.end()) { - s_s.m_nameMap.insert(it, std::make_pair(scopep->name(),scopep)); - } + // Slow ok - called once/scope at construction + VerilatedLockGuard lock(s_s.m_nameMutex); + VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name()); + if (it == s_s.m_nameMap.end()) { + s_s.m_nameMap.insert(it, std::make_pair(scopep->name(), scopep)); + } } static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE { - VerilatedLockGuard lock(s_s.m_nameMutex); // If too slow, can assume this is only VL_MT_SAFE_POSINIT - VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.find(namep); - if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second; - else return NULL; + VerilatedLockGuard lock(s_s.m_nameMutex); + // If too slow, can assume this is only VL_MT_SAFE_POSINIT + VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.find(namep); + if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second; + else return NULL; } static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE { - // Slow ok - called once/scope at destruction - VerilatedLockGuard lock(s_s.m_nameMutex); - userEraseScope(scopep); - VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name()); - if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it); + // Slow ok - called once/scope at destruction + VerilatedLockGuard lock(s_s.m_nameMutex); + userEraseScope(scopep); + VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name()); + if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it); } static void scopesDump() VL_MT_SAFE { - VerilatedLockGuard lock(s_s.m_nameMutex); - VL_PRINTF_MT(" scopesDump:\n"); - for (VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) { - const VerilatedScope* scopep = it->second; - scopep->scopeDump(); - } - VL_PRINTF_MT("\n"); + VerilatedLockGuard lock(s_s.m_nameMutex); + VL_PRINTF_MT(" scopesDump:\n"); + for (VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.begin(); + it!=s_s.m_nameMap.end(); ++it) { + const VerilatedScope* scopep = it->second; + scopep->scopeDump(); + } + VL_PRINTF_MT("\n"); } static const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE_POSTINIT { - // Thread save only assuming this is called only after model construction completed + // Thread save only assuming this is called only after model construction completed return &s_s.m_nameMap; } @@ -329,40 +331,42 @@ public: // But only for verilated*.cpp // Rather than a 2D map, the integer scheme saves 500ish ns on a likely // miss at the cost of a multiply, and all lookups move to slowpath. static int exportInsert(const char* namep) VL_MT_SAFE { - // Slow ok - called once/function at creation - VerilatedLockGuard lock(s_s.m_exportMutex); - ExportNameMap::iterator it=s_s.m_exportMap.find(namep); - if (it == s_s.m_exportMap.end()) { - s_s.m_exportMap.insert(it, std::make_pair(namep, s_s.m_exportNext++)); - return s_s.m_exportNext++; - } else { - return it->second; - } + // Slow ok - called once/function at creation + VerilatedLockGuard lock(s_s.m_exportMutex); + ExportNameMap::iterator it=s_s.m_exportMap.find(namep); + if (it == s_s.m_exportMap.end()) { + s_s.m_exportMap.insert(it, std::make_pair(namep, s_s.m_exportNext++)); + return s_s.m_exportNext++; + } else { + return it->second; + } } static int exportFind(const char* namep) VL_MT_SAFE { - VerilatedLockGuard lock(s_s.m_exportMutex); - ExportNameMap::const_iterator it=s_s.m_exportMap.find(namep); - if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second; - std::string msg = (std::string("%Error: Testbench C called ")+namep - +" but no such DPI export function name exists in ANY model"); - VL_FATAL_MT("unknown",0,"", msg.c_str()); - return -1; + VerilatedLockGuard lock(s_s.m_exportMutex); + ExportNameMap::const_iterator it=s_s.m_exportMap.find(namep); + if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second; + std::string msg = (std::string("%Error: Testbench C called ")+namep + +" but no such DPI export function name exists in ANY model"); + VL_FATAL_MT("unknown", 0, "", msg.c_str()); + return -1; } static const char* exportName(int funcnum) VL_MT_SAFE { - // Slowpath; find name for given export; errors only so no map to reverse-map it - VerilatedLockGuard lock(s_s.m_exportMutex); - for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) { - if (it->second == funcnum) return it->first; - } - return "*UNKNOWN*"; + // Slowpath; find name for given export; errors only so no map to reverse-map it + VerilatedLockGuard lock(s_s.m_exportMutex); + for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); + it!=s_s.m_exportMap.end(); ++it) { + if (it->second == funcnum) return it->first; + } + return "*UNKNOWN*"; } static void exportsDump() VL_MT_SAFE { - VerilatedLockGuard lock(s_s.m_exportMutex); - bool first = true; - for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) { - if (first) { VL_PRINTF_MT(" exportDump:\n"); first=false; } - VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first); - } + VerilatedLockGuard lock(s_s.m_exportMutex); + bool first = true; + for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); + it!=s_s.m_exportMap.end(); ++it) { + if (first) { VL_PRINTF_MT(" exportDump:\n"); first=false; } + VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first); + } } // We don't free up m_exportMap until the end, because we can't be sure // what other models are using the assigned funcnum's. @@ -370,32 +374,32 @@ public: // But only for verilated*.cpp public: // But only for verilated*.cpp // METHODS - file IO static IData fdNew(FILE* fp) VL_MT_SAFE { - if (VL_UNLIKELY(!fp)) return 0; - // Bit 31 indicates it's a descriptor not a MCD - VerilatedLockGuard lock(s_s.m_fdMutex); - if (s_s.m_fdFree.empty()) { - // Need to create more space in m_fdps and m_fdFree - size_t start = s_s.m_fdps.size(); - s_s.m_fdps.resize(start*2); - for (size_t i=start; i(i)); - } - IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back(); - s_s.m_fdps[idx] = fp; - return (idx | (1UL<<31)); // bit 31 indicates not MCD + if (VL_UNLIKELY(!fp)) return 0; + // Bit 31 indicates it's a descriptor not a MCD + VerilatedLockGuard lock(s_s.m_fdMutex); + if (s_s.m_fdFree.empty()) { + // Need to create more space in m_fdps and m_fdFree + size_t start = s_s.m_fdps.size(); + s_s.m_fdps.resize(start*2); + for (size_t i=start; i(i)); + } + IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back(); + s_s.m_fdps[idx] = fp; + return (idx | (1UL<<31)); // bit 31 indicates not MCD } static void fdDelete(IData fdi) VL_MT_SAFE { - IData idx = VL_MASK_I(31) & fdi; - VerilatedLockGuard lock(s_s.m_fdMutex); - if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return; - if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free - s_s.m_fdps[idx] = NULL; - s_s.m_fdFree.push_back(idx); + IData idx = VL_MASK_I(31) & fdi; + VerilatedLockGuard lock(s_s.m_fdMutex); + if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return; + if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free + s_s.m_fdps[idx] = NULL; + s_s.m_fdFree.push_back(idx); } static inline FILE* fdToFp(IData fdi) VL_MT_SAFE { - IData idx = VL_MASK_I(31) & fdi; - VerilatedLockGuard lock(s_s.m_fdMutex); // This might get slow, if it does we can cache it - if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL; - return s_s.m_fdps[idx]; + IData idx = VL_MASK_I(31) & fdi; + VerilatedLockGuard lock(s_s.m_fdMutex); // This might get slow, if it does we can cache it + if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL; + return s_s.m_fdps[idx]; } }; diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 82c600118..8de67d383 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -16,8 +16,8 @@ /// \file /// \brief Verilator: VPI implementation code /// -/// This file must be compiled and linked against all objects -/// created from Verilator or called by Verilator that use the VPI. +/// This file must be compiled and linked against all objects +/// created from Verilator or called by Verilator that use the VPI. /// /// Use "verilator --vpi" to add this to the Makefile for the linker. /// @@ -54,7 +54,7 @@ // Not supported yet #define _VL_VPI_UNIMP() \ - _VL_VPI_ERROR(__FILE__,__LINE__,Verilated::catName("Unsupported VPI function: ",VL_FUNC)); + _VL_VPI_ERROR(__FILE__, __LINE__, Verilated::catName("Unsupported VPI function: ", VL_FUNC)); //====================================================================== // Implementation @@ -74,7 +74,7 @@ public: // We reserve word zero for the next pointer, as that's safer in case a // dangling reference to the original remains around. static const size_t chunk = 96; - if (VL_UNLIKELY(size>chunk)) VL_FATAL_MT(__FILE__,__LINE__,"", "increase chunk"); + if (VL_UNLIKELY(size>chunk)) VL_FATAL_MT(__FILE__, __LINE__, "", "increase chunk"); if (VL_LIKELY(t_freeHead)) { vluint8_t* newp = t_freeHead; t_freeHead = *((vluint8_t**)newp); @@ -186,7 +186,7 @@ class VerilatedVpioVar : public VerilatedVpio { protected: void* m_varDatap; // varp()->datap() adjusted for array entries vlsint32_t m_index; - const VerilatedRange& get_range() const { + const VerilatedRange& get_range() const { // Determine number of dimensions and return outermost return (m_varp->dims()>1) ? m_varp->unpacked() : m_varp->packed(); } @@ -247,7 +247,7 @@ public: virtual const VerilatedRange* rangep() const { return &(varp()->packed()); } virtual const char* fullname() const { static VL_THREAD_LOCAL std::string out; - char num[20]; sprintf(num,"%d",m_index); + char num[20]; sprintf(num, "%d", m_index); out = std::string(scopep()->name())+"."+name()+"["+num+"]"; return out.c_str(); } @@ -295,7 +295,9 @@ public: return dynamic_cast((VerilatedVpio*)h); } virtual vluint32_t type() const { return vpiIterator; } void iterationInc() { - if (!(m_done = (m_iteration == m_varp->unpacked().left()))) m_iteration+=m_direction; + if (!(m_done = (m_iteration == m_varp->unpacked().left()))) { + m_iteration += m_direction; + } } virtual vpiHandle dovpi_scan() { vpiHandle result; @@ -310,8 +312,8 @@ public: struct VerilatedVpiTimedCbsCmp { /// Ordering sets keyed by time, then callback descriptor - bool operator() (const std::pair& a, - const std::pair& b) const { + bool operator()(const std::pair& a, + const std::pair& b) const { if (a.first < b.first) return 1; if (a.first > b.first) return 0; return a.second < b.second; @@ -347,7 +349,7 @@ public: } } if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) { - VL_FATAL_MT(__FILE__,__LINE__,"", "vpi bb reason too large"); + VL_FATAL_MT(__FILE__, __LINE__, "", "vpi bb reason too large"); } s_s.m_cbObjLists[vop->reason()].push_back(vop); } @@ -363,7 +365,7 @@ public: } } static void cbTimedRemove(VerilatedVpioCb* cbp) { - VpioTimedCbs::iterator it=s_s.m_timedCbs.find(std::make_pair(cbp->time(),cbp)); + VpioTimedCbs::iterator it=s_s.m_timedCbs.find(std::make_pair(cbp->time(), cbp)); if (VL_LIKELY(it != s_s.m_timedCbs.end())) { s_s.m_timedCbs.erase(it); } @@ -375,7 +377,7 @@ public: if (VL_UNLIKELY(it->first <= time)) { VerilatedVpioCb* vop = it->second; ++it; // iterator may be deleted by callback - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: timed_callback %p\n",vop);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: timed_callback %p\n", vop);); (vop->cb_rtnp()) (vop->cb_datap()); } else { ++it; } @@ -383,7 +385,7 @@ public: } static QData cbNextDeadline() { VpioTimedCbs::const_iterator it=s_s.m_timedCbs.begin(); - if (VL_LIKELY(it!=s_s.m_timedCbs.end())) { + if (VL_LIKELY(it != s_s.m_timedCbs.end())) { return it->first; } return ~VL_ULL(0); // maxquad @@ -396,7 +398,7 @@ public: continue; } VerilatedVpioCb* vop = *it++; - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback %d %p\n",reason,vop);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback %d %p\n", reason, vop);); (vop->cb_rtnp()) (vop->cb_datap()); } } @@ -419,7 +421,7 @@ public: newDatap, prevDatap);); if (memcmp(prevDatap, newDatap, varop->entSize())) { VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: value_callback %p %s v[0]=%d\n", - vop,varop->fullname(), *((CData*)newDatap));); + vop, varop->fullname(), *((CData*)newDatap));); update.insert(varop); vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value); (vop->cb_rtnp()) (vop->cb_datap()); @@ -438,8 +440,8 @@ class VerilatedVpiError { //// Container for vpi error info t_vpi_error_info m_errorInfo; - bool m_flag; - char m_buff[VL_VPI_LINE_SIZE]; + bool m_flag; + char m_buff[VL_VPI_LINE_SIZE]; void setError(PLI_BYTE8 *message, PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line) { m_errorInfo.message = message; m_errorInfo.file = file; @@ -465,7 +467,7 @@ public: ~VerilatedVpiError() {} static void selfTest() VL_MT_UNSAFE_ONE; VerilatedVpiError* setMessage(PLI_INT32 level) { - m_flag=true; + m_flag = true; m_errorInfo.level = level; return this; } @@ -484,9 +486,7 @@ public: if (m_flag) return &m_errorInfo; return NULL; } - void resetError() { - m_flag=false; - } + void resetError() { m_flag = false; } static void vpi_unsupported() { // Not supported yet p_vpi_error_info error_info_p = VerilatedVpiImp::error_info()->getError(); @@ -556,7 +556,7 @@ const char* VerilatedVpiError::strFromVpiVal(PLI_INT32 vpiVal) VL_MT_SAFE { "vpiRawFourStateVal", }; if (vpiVal < 0) return names[0]; - return names[(vpiVal<=vpiRawFourStateVal)?vpiVal:0]; + return names[(vpiVal<=vpiRawFourStateVal) ? vpiVal : 0]; } const char* VerilatedVpiError::strFromVpiObjType(PLI_INT32 vpiVal) VL_MT_SAFE { static const char* const names[] = { @@ -698,7 +698,7 @@ const char* VerilatedVpiError::strFromVpiObjType(PLI_INT32 vpiVal) VL_MT_SAFE { "vpiGenVar" }; if (vpiVal < 0) return names[0]; - return names[(vpiVal<=vpiGenVar)?vpiVal:0]; + return names[(vpiVal<=vpiGenVar) ? vpiVal : 0]; } const char* VerilatedVpiError::strFromVpiMethod(PLI_INT32 vpiVal) VL_MT_SAFE { static const char* const names[] = { @@ -779,7 +779,7 @@ const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) VL_MT_ "cbAtEndOfSimTime" }; if (vpiVal < 0) return names[0]; - return names[(vpiVal<=cbAtEndOfSimTime)?vpiVal:0]; + return names[(vpiVal<=cbAtEndOfSimTime) ? vpiVal : 0]; } const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) VL_MT_SAFE { @@ -863,20 +863,20 @@ const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) VL_MT_SAFE { if (vpiVal == vpiUndefined) { return "vpiUndefined"; } - return names[(vpiVal<=vpiIsProtected)?vpiVal:0]; + return names[(vpiVal<=vpiIsProtected) ? vpiVal : 0]; } #define CHECK_RESULT_CSTR(got, exp) \ - if (strcmp((got),(exp))) { \ - std::string msg = std::string("%Error: ") \ - + "GOT = '"+((got)?(got):"")+"'" \ - + " EXP = '"+((exp)?(exp):"")+"'"; \ - VL_FATAL_MT(__FILE__,__LINE__,"",msg.c_str()); \ + if (strcmp((got), (exp))) { \ + std::string msg = std::string("%Error: ") \ + + "GOT = '"+((got)?(got):"")+"'" \ + + " EXP = '"+((exp)?(exp):"")+"'"; \ + VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str()); \ } #define CHECK_ENUM_STR(fn, enum) \ do { \ - const char* strVal = VerilatedVpiError::fn(enum); \ + const char* strVal = VerilatedVpiError::fn(enum); \ CHECK_RESULT_CSTR(strVal, #enum); \ } while (0) @@ -929,46 +929,46 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) { } switch (cb_data_p->reason) { case cbAfterDelay: { - QData time = 0; - if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low); - VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q()+time); + QData time = 0; + if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low); + VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q()+time); VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb %d %p delay=%" VL_PRI64 "u\n", cb_data_p->reason, vop, time);); - VerilatedVpiImp::cbTimedAdd(vop); - return vop->castVpiHandle(); + VerilatedVpiImp::cbTimedAdd(vop); + return vop->castVpiHandle(); } - case cbReadWriteSynch: // FALLTHRU // Supported via vlt_main.cpp - case cbReadOnlySynch: // FALLTHRU // Supported via vlt_main.cpp - case cbNextSimTime: // FALLTHRU // Supported via vlt_main.cpp - case cbStartOfSimulation: // FALLTHRU // Supported via vlt_main.cpp - case cbEndOfSimulation: // FALLTHRU // Supported via vlt_main.cpp - case cbValueChange: // FALLTHRU // Supported via vlt_main.cpp - case cbPLIError: // 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 cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object - VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, 0); - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb %d %p\n",cb_data_p->reason,vop);); - VerilatedVpiImp::cbReasonAdd(vop); - return vop->castVpiHandle(); + case cbReadWriteSynch: // FALLTHRU // Supported via vlt_main.cpp + case cbReadOnlySynch: // FALLTHRU // Supported via vlt_main.cpp + case cbNextSimTime: // FALLTHRU // Supported via vlt_main.cpp + case cbStartOfSimulation: // FALLTHRU // Supported via vlt_main.cpp + case cbEndOfSimulation: // FALLTHRU // Supported via vlt_main.cpp + case cbValueChange: // FALLTHRU // Supported via vlt_main.cpp + case cbPLIError: // 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 cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object + VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, 0); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb %d %p\n", cb_data_p->reason, vop);); + VerilatedVpiImp::cbReasonAdd(vop); + return vop->castVpiHandle(); } default: _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported callback type %s", - VL_FUNC, VerilatedVpiError::strFromVpiCallbackReason(cb_data_p->reason)); - return NULL; + VL_FUNC, VerilatedVpiError::strFromVpiCallbackReason(cb_data_p->reason)); + return NULL; }; } PLI_INT32 vpi_remove_cb(vpiHandle object) { - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_remove_cb %p\n",object);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_remove_cb %p\n", object);); VerilatedVpiImp::assertOneCheck(); VerilatedVpioCb* vop = VerilatedVpioCb::castp(object); _VL_VPI_ERROR_RESET(); if (VL_UNLIKELY(!vop)) return 0; if (vop->cb_datap()->reason == cbAfterDelay) { - VerilatedVpiImp::cbTimedRemove(vop); + VerilatedVpiImp::cbTimedRemove(vop); } else { - VerilatedVpiImp::cbReasonRemove(vop); + VerilatedVpiImp::cbReasonRemove(vop); } return 1; } @@ -989,31 +989,31 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) { VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); if (VL_UNLIKELY(!namep)) return NULL; - 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);); VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope); const VerilatedVar* varp; const VerilatedScope* scopep; std::string scopeAndName = namep; if (voScopep) { - scopeAndName = std::string(voScopep->fullname()) + "." + namep; - namep = (PLI_BYTE8*)scopeAndName.c_str(); + scopeAndName = std::string(voScopep->fullname()) + "." + namep; + namep = (PLI_BYTE8*)scopeAndName.c_str(); } { - // This doesn't yet follow the hierarchy in the proper way - scopep = Verilated::scopeFind(namep); - if (scopep) { // Whole thing found as a scope - return (new VerilatedVpioScope(scopep))->castVpiHandle(); - } - const char* baseNamep = scopeAndName.c_str(); - std::string scopename; - const char* dotp = strrchr(namep, '.'); - if (VL_LIKELY(dotp)) { - baseNamep = dotp+1; - scopename = std::string(namep,dotp-namep); - } - scopep = Verilated::scopeFind(scopename.c_str()); - if (!scopep) return NULL; - varp = scopep->varFind(baseNamep); + // This doesn't yet follow the hierarchy in the proper way + scopep = Verilated::scopeFind(namep); + if (scopep) { // Whole thing found as a scope + return (new VerilatedVpioScope(scopep))->castVpiHandle(); + } + const char* baseNamep = scopeAndName.c_str(); + std::string scopename; + const char* dotp = strrchr(namep, '.'); + if (VL_LIKELY(dotp)) { + baseNamep = dotp+1; + scopename = std::string(namep, dotp-namep); + } + scopep = Verilated::scopeFind(scopename.c_str()); + if (!scopep) return NULL; + varp = scopep->varFind(baseNamep); } if (!varp) return NULL; return (new VerilatedVpioVar(varp, scopep))->castVpiHandle(); @@ -1021,19 +1021,19 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) { vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) { // Used to get array entries - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle_by_index %p %d\n",object, indx);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle_by_index %p %d\n", object, indx);); VerilatedVpiImp::assertOneCheck(); VerilatedVpioVar* varop = VerilatedVpioVar::castp(object); _VL_VPI_ERROR_RESET(); if (VL_LIKELY(varop)) { - if (varop->varp()->dims()<2) return 0; + if (varop->varp()->dims()<2) return 0; if (VL_LIKELY(varop->varp()->unpacked().left() >= varop->varp()->unpacked().right())) { if (VL_UNLIKELY(indx > varop->varp()->unpacked().left() || indx < varop->varp()->unpacked().right())) return 0; - return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, + return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, indx - varop->varp()->unpacked().right())) - ->castVpiHandle(); - } + ->castVpiHandle(); + } if (VL_UNLIKELY(indx < varop->varp()->unpacked().left() || indx > varop->varp()->unpacked().right())) return 0; return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, @@ -1047,41 +1047,41 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) { // for traversing relationships vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) { - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle %d %p\n",type,object);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle %d %p\n", type, object);); VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); switch (type) { case vpiLeftRange: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - if (VL_UNLIKELY(!vop->rangep())) return 0; + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + if (VL_UNLIKELY(!vop->rangep())) return 0; return (new VerilatedVpioConst(vop->rangep()->left()))->castVpiHandle(); } case vpiRightRange: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - if (VL_UNLIKELY(!vop->rangep())) return 0; + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + if (VL_UNLIKELY(!vop->rangep())) return 0; return (new VerilatedVpioConst(vop->rangep()->right()))->castVpiHandle(); } case vpiIndex: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; return (new VerilatedVpioConst(vop->index()))->castVpiHandle(); } case vpiScope: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return (new VerilatedVpioScope(vop->scopep()))->castVpiHandle(); + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return (new VerilatedVpioScope(vop->scopep()))->castVpiHandle(); } case vpiParent: { - VerilatedVpioMemoryWord* vop = VerilatedVpioMemoryWord::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return (new VerilatedVpioVar(vop->varp(), vop->scopep()))->castVpiHandle(); + VerilatedVpioMemoryWord* vop = VerilatedVpioMemoryWord::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return (new VerilatedVpioVar(vop->varp(), vop->scopep()))->castVpiHandle(); } default: _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", - VL_FUNC, VerilatedVpiError::strFromVpiMethod(type)); - return 0; + VL_FUNC, VerilatedVpiError::strFromVpiMethod(type)); + return 0; } } @@ -1090,45 +1090,47 @@ vpiHandle vpi_handle_multi(PLI_INT32 type, vpiHandle refHandle1, vpiHandle refHa } vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) { - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_iterate %d %p\n",type,object);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_iterate %d %p\n", type, object);); VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); switch (type) { case vpiMemoryWord: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - if (vop->varp()->dims() < 2) return 0; - if (vop->varp()->dims() > 2) { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: %s, object %s has unsupported number of indices (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), vop->fullname() , vop->varp()->dims()); - } - return (new VerilatedVpioMemoryWordIter(object, vop->varp()))->castVpiHandle(); + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + if (vop->varp()->dims() < 2) return 0; + if (vop->varp()->dims() > 2) { + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: %s, object %s has unsupported number of indices (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), + vop->fullname() , vop->varp()->dims()); + } + return (new VerilatedVpioMemoryWordIter(object, vop->varp()))->castVpiHandle(); } case vpiRange: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - if (vop->varp()->dims() < 2) return 0; - // Unsupported is multidim list + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + if (vop->varp()->dims() < 2) return 0; + // Unsupported is multidim list if (vop->varp()->dims() > 2) { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: %s, object %s has unsupported number of indices (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), vop->fullname() , vop->varp()->dims()); - } - return ((new VerilatedVpioRange(vop->rangep()))->castVpiHandle()); + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: %s, object %s has unsupported number of indices (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), + vop->fullname() , vop->varp()->dims()); + } + return ((new VerilatedVpioRange(vop->rangep()))->castVpiHandle()); } case vpiReg: { - VerilatedVpioScope* vop = VerilatedVpioScope::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return ((new VerilatedVpioVarIter(vop->scopep())) - ->castVpiHandle()); + VerilatedVpioScope* vop = VerilatedVpioScope::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return ((new VerilatedVpioVarIter(vop->scopep())) + ->castVpiHandle()); } default: _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", - VL_FUNC, VerilatedVpiError::strFromVpiObjType(type)); - return 0; + VL_FUNC, VerilatedVpiError::strFromVpiObjType(type)); + return 0; } } vpiHandle vpi_scan(vpiHandle object) { - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_scan %p\n",object);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_scan %p\n", object);); VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); VerilatedVpio* vop = VerilatedVpio::castp(object); @@ -1140,39 +1142,39 @@ vpiHandle vpi_scan(vpiHandle object) { PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) { // Leave this in the header file - in many cases the compiler can constant propagate "object" - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get %d %p\n",property,object);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get %d %p\n", property, object);); VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); switch (property) { case vpiTimePrecision: { - return VL_TIME_PRECISION; + return VL_TIME_PRECISION; } case vpiType: { - VerilatedVpio* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return vop->type(); + VerilatedVpio* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return vop->type(); } case vpiDirection: { - // By forthought, the directions already are vpi enumerated - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return vop->varp()->vldir(); + // By forthought, the directions already are vpi enumerated + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return vop->varp()->vldir(); } case vpiScalar: // FALLTHRU case vpiVector: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return (property==vpiVector)^(vop->varp()->dims()==0); + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return (property==vpiVector) ^ (vop->varp()->dims()==0); } case vpiSize: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return vop->size(); + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return vop->size(); } default: _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", - VL_FUNC, VerilatedVpiError::strFromVpiProp(property)); - return 0; + VL_FUNC, VerilatedVpiError::strFromVpiProp(property)); + return 0; } } @@ -1182,25 +1184,25 @@ PLI_INT64 vpi_get64(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(); VerilatedVpio* vop = VerilatedVpio::castp(object); _VL_VPI_ERROR_RESET(); if (VL_UNLIKELY(!vop)) return NULL; switch (property) { case vpiName: { - return (PLI_BYTE8*)vop->name(); + return (PLI_BYTE8*)vop->name(); } case vpiFullName: { - return (PLI_BYTE8*)vop->fullname(); + return (PLI_BYTE8*)vop->fullname(); } case vpiDefName: { - return (PLI_BYTE8*)vop->defname(); + return (PLI_BYTE8*)vop->defname(); } default: _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", - VL_FUNC, VerilatedVpiError::strFromVpiProp(property)); - return 0; + VL_FUNC, VerilatedVpiError::strFromVpiProp(property)); + return 0; } } @@ -1222,271 +1224,275 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) { static VL_THREAD_LOCAL char outStr[1+VL_MULS_MAX_WORDS*32]; // cppcheck-suppress variableScope static VL_THREAD_LOCAL int outStrSz = sizeof(outStr)-1; - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_value %p\n",object);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_value %p\n", object);); VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); if (VL_UNLIKELY(!value_p)) return; if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) { - // We used to presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal + // We used to presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal // This may cause backward compatability issues with older code. - if (value_p->format == vpiVectorVal) { - // Vector pointer must come from our memory pool - // It only needs to persist until the next vpi_get_value - static VL_THREAD_LOCAL t_vpi_vecval out[VL_MULS_MAX_WORDS*2]; - value_p->value.vector = out; - switch (vop->varp()->vltype()) { - case VLVT_UINT8: - out[0].aval = *(reinterpret_cast(vop->varDatap())); - out[0].bval = 0; - return; - case VLVT_UINT16: - out[0].aval = *(reinterpret_cast(vop->varDatap())); - out[0].bval = 0; - return; - case VLVT_UINT32: - out[0].aval = *(reinterpret_cast(vop->varDatap())); - out[0].bval = 0; - return; - case VLVT_WDATA: { + if (value_p->format == vpiVectorVal) { + // Vector pointer must come from our memory pool + // It only needs to persist until the next vpi_get_value + static VL_THREAD_LOCAL t_vpi_vecval out[VL_MULS_MAX_WORDS*2]; + value_p->value.vector = out; + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + out[0].aval = *(reinterpret_cast(vop->varDatap())); + out[0].bval = 0; + return; + case VLVT_UINT16: + out[0].aval = *(reinterpret_cast(vop->varDatap())); + out[0].bval = 0; + return; + case VLVT_UINT32: + out[0].aval = *(reinterpret_cast(vop->varDatap())); + out[0].bval = 0; + return; + case VLVT_WDATA: { int words = VL_WORDS_I(vop->varp()->packed().elements()); - if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) { - VL_FATAL_MT(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile"); - } - WDataInP datap = (reinterpret_cast(vop->varDatap())); - for (int i=0; i(vop->varDatap())); - out[1].aval = static_cast(data>>VL_ULL(32)); - out[1].bval = 0; - out[0].aval = static_cast(data); - out[0].bval = 0; - return; - } - default: { + if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) { + VL_FATAL_MT(__FILE__, __LINE__, "", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile"); + } + WDataInP datap = (reinterpret_cast(vop->varDatap())); + for (int i=0; i(vop->varDatap())); + out[1].aval = static_cast(data>>VL_ULL(32)); + out[1].bval = 0; + out[0].aval = static_cast(data); + out[0].bval = 0; + return; + } + default: { _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - } - } else if (value_p->format == vpiBinStrVal) { - value_p->value.str = outStr; - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } + } else if (value_p->format == vpiBinStrVal) { + value_p->value.str = outStr; + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { int bits = vop->varp()->packed().elements(); - CData* datap = (reinterpret_cast(vop->varDatap())); - int i; - if (bits > outStrSz) { - // limit maximum size of output to size of buffer to prevent overrun. - bits = outStrSz; + CData* datap = (reinterpret_cast(vop->varDatap())); + int i; + if (bits > outStrSz) { + // limit maximum size of output to size of buffer to prevent overrun. + bits = outStrSz; _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits); - } - for (i=0; i>3]>>(i&7))&1; - outStr[bits-i-1] = val?'1':'0'; + } + for (i=0; i>3]>>(i&7))&1; + outStr[bits-i-1] = val?'1':'0'; } outStr[i] = '\0'; return; } - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - } else if (value_p->format == vpiOctStrVal) { - value_p->value.str = outStr; - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { + return; + } + } else if (value_p->format == vpiOctStrVal) { + value_p->value.str = outStr; + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { int chars = (vop->varp()->packed().elements()+2)/3; int bytes = VL_BYTES_I(vop->varp()->packed().elements()); - CData* datap = (reinterpret_cast(vop->varDatap())); - int i; - if (chars > outStrSz) { - // limit maximum size of output to size of buffer to prevent overrun. + CData* datap = (reinterpret_cast(vop->varDatap())); + int i; + if (chars > outStrSz) { + // limit maximum size of output to size of buffer to prevent overrun. _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); - chars = outStrSz; - } - for (i=0; i>= idx.rem; + val >>= idx.rem; 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 3 unsigned int rem = vop->varp()->packed().elements() % 3; if (rem) { - // generate bit mask & zero non existant bits + // generate bit mask & zero non existant bits val &= (1<format), vop->fullname()); - return; - } - } else if (value_p->format == vpiDecStrVal) { - value_p->value.str = outStr; - switch (vop->varp()->vltype()) { - // outStrSz does not include NULL termination so add one - case VLVT_UINT8 : VL_SNPRINTF(outStr, outStrSz+1, "%hhu", - static_cast(*(reinterpret_cast(vop->varDatap())))); return; - case VLVT_UINT16: VL_SNPRINTF(outStr, outStrSz+1, "%hu", - static_cast(*(reinterpret_cast(vop->varDatap())))); return; - case VLVT_UINT32: VL_SNPRINTF(outStr, outStrSz+1, "%u", - static_cast(*(reinterpret_cast(vop->varDatap())))); return; - case VLVT_UINT64: VL_SNPRINTF(outStr, outStrSz+1, "%llu", - static_cast(*(reinterpret_cast(vop->varDatap())))); return; - default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } else if (value_p->format == vpiDecStrVal) { + value_p->value.str = outStr; + switch (vop->varp()->vltype()) { + // outStrSz does not include NULL termination so add one + case VLVT_UINT8: + VL_SNPRINTF(outStr, outStrSz+1, "%hhu", + static_cast(*(reinterpret_cast(vop->varDatap())))); return; + case VLVT_UINT16: + VL_SNPRINTF(outStr, outStrSz+1, "%hu", + static_cast(*(reinterpret_cast(vop->varDatap())))); return; + case VLVT_UINT32: + VL_SNPRINTF(outStr, outStrSz+1, "%u", + static_cast(*(reinterpret_cast(vop->varDatap())))); return; + case VLVT_UINT64: + VL_SNPRINTF(outStr, outStrSz+1, "%llu", + static_cast(*(reinterpret_cast(vop->varDatap())))); return; + default: strcpy(outStr, "-1"); - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - } else if (value_p->format == vpiHexStrVal) { - value_p->value.str = outStr; - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } else if (value_p->format == vpiHexStrVal) { + value_p->value.str = outStr; + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { int chars = (vop->varp()->packed().elements()+3)>>2; - CData* datap = (reinterpret_cast(vop->varDatap())); - int i; - if (chars > outStrSz) { - // limit maximum size of output to size of buffer to prevent overrun. + CData* datap = (reinterpret_cast(vop->varDatap())); + int i; + if (chars > outStrSz) { + // limit maximum size of output to size of buffer to prevent overrun. _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); - chars = outStrSz; - } - for (i=0; i>1]>>((i&1)<<2))&15; + chars = outStrSz; + } + for (i=0; i>1]>>((i&1)<<2))&15; 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 unsigned int rem = vop->varp()->packed().elements() & 3; if (rem) { - // generate bit mask & zero non existant bits + // generate bit mask & zero non existant bits val &= (1<(val)]; + } + } + outStr[chars-i-1] = "0123456789abcdef"[static_cast(val)]; } outStr[i] = '\0'; return; } - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - } else if (value_p->format == vpiStringVal) { - value_p->value.str = outStr; - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } else if (value_p->format == vpiStringVal) { + value_p->value.str = outStr; + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { int bytes = VL_BYTES_I(vop->varp()->packed().elements()); - CData* datap = (reinterpret_cast(vop->varDatap())); - int i; - if (bytes > outStrSz) { - // limit maximum size of output to size of buffer to prevent overrun. + CData* datap = (reinterpret_cast(vop->varDatap())); + int i; + if (bytes > outStrSz) { + // limit maximum size of output to size of buffer to prevent overrun. _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), - vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes); - bytes = outStrSz; - } - for (i=0; iformat), + vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes); + bytes = outStrSz; + } + for (i=0; iformat), vop->fullname()); - return; - } - } else if (value_p->format == vpiIntVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8: - value_p->value.integer = *(reinterpret_cast(vop->varDatap())); - return; - case VLVT_UINT16: - value_p->value.integer = *(reinterpret_cast(vop->varDatap())); - return; - case VLVT_UINT32: - value_p->value.integer = *(reinterpret_cast(vop->varDatap())); - return; + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } else if (value_p->format == vpiIntVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + value_p->value.integer = *(reinterpret_cast(vop->varDatap())); + return; + case VLVT_UINT16: + value_p->value.integer = *(reinterpret_cast(vop->varDatap())); + return; + case VLVT_UINT32: + value_p->value.integer = *(reinterpret_cast(vop->varDatap())); + return; case VLVT_WDATA: // FALLTHRU case VLVT_UINT64: // FALLTHRU default: - value_p->value.integer = 0; + value_p->value.integer = 0; _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - } else if (value_p->format == vpiSuppressVal) { - return; - } + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } else if (value_p->format == vpiSuppressVal) { + return; + } _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; } else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) { - if (value_p->format == vpiIntVal) { - value_p->value.integer = vop->num(); - return; - } + if (value_p->format == vpiIntVal) { + value_p->value.integer = vop->num(); + return; + } _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); return; } _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format)); + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format)); } vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, - p_vpi_time time_p, PLI_INT32 flags) { - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_put_value %p %p\n",object, value_p);); + p_vpi_time time_p, PLI_INT32 flags) { + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_put_value %p %p\n", object, value_p);); VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); if (VL_UNLIKELY(!value_p)) { @@ -1494,111 +1500,114 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, return 0; } if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) { - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_put_value name=%s fmt=%d vali=%d\n", - vop->fullname(), value_p->format, value_p->value.integer); - VL_DBG_MSGF("- vpi: varp=%p putatp=%p\n", - vop->varp()->datap(), vop->varDatap());); - if (VL_UNLIKELY(!vop->varp()->isPublicRW())) { + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_put_value name=%s fmt=%d vali=%d\n", + vop->fullname(), value_p->format, value_p->value.integer); + VL_DBG_MSGF("- vpi: varp=%p putatp=%p\n", + vop->varp()->datap(), vop->varDatap());); + if (VL_UNLIKELY(!vop->varp()->isPublicRW())) { _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value to signal marked read-only," " use public_flat_rw instead: ", vop->fullname()); - return 0; - } - if (value_p->format == vpiVectorVal) { - if (VL_UNLIKELY(!value_p->value.vector)) return NULL; - switch (vop->varp()->vltype()) { - case VLVT_UINT8: - *(reinterpret_cast(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask(); - return object; - case VLVT_UINT16: - *(reinterpret_cast(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask(); - return object; - case VLVT_UINT32: - *(reinterpret_cast(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask(); - return object; - case VLVT_WDATA: { + return 0; + } + if (value_p->format == vpiVectorVal) { + if (VL_UNLIKELY(!value_p->value.vector)) return NULL; + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + *(reinterpret_cast(vop->varDatap())) + = value_p->value.vector[0].aval & vop->mask(); + return object; + case VLVT_UINT16: + *(reinterpret_cast(vop->varDatap())) + = value_p->value.vector[0].aval & vop->mask(); + return object; + case VLVT_UINT32: + *(reinterpret_cast(vop->varDatap())) + = value_p->value.vector[0].aval & vop->mask(); + return object; + case VLVT_WDATA: { int words = VL_WORDS_I(vop->varp()->packed().elements()); - WDataOutP datap = (reinterpret_cast(vop->varDatap())); - for (int i=0; ivalue.vector[i].aval; + WDataOutP datap = (reinterpret_cast(vop->varDatap())); + for (int i=0; ivalue.vector[i].aval; if (i==(words-1)) { - datap[i] &= vop->mask(); - } - } - return object; - } - case VLVT_UINT64: { - *(reinterpret_cast(vop->varDatap())) = _VL_SET_QII( - value_p->value.vector[1].aval & vop->mask(), - value_p->value.vector[0].aval); - return object; - } - default: { + datap[i] &= vop->mask(); + } + } + return object; + } + case VLVT_UINT64: { + *(reinterpret_cast(vop->varDatap())) = _VL_SET_QII( + value_p->value.vector[1].aval & vop->mask(), + value_p->value.vector[0].aval); + return object; + } + default: { _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return NULL; - } - } - } else if (value_p->format == vpiBinStrVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return NULL; + } + } + } else if (value_p->format == vpiBinStrVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { int bits = vop->varp()->packed().elements(); - int len = strlen(value_p->value.str); - CData* datap = (reinterpret_cast(vop->varDatap())); - for (int i=0; ivalue.str); + CData* datap = (reinterpret_cast(vop->varDatap())); + for (int i=0; ivalue.str[len-i-1]=='1'):0; // zero bits 7:1 of byte when assigning to bit 0, else // or in 1 if bit set - if (i&7) { - datap[i>>3] |= set<<(i&7); - } else { - datap[i>>3] = set; - } - } - return object; - } - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } - } else if (value_p->format == vpiOctStrVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { + if (i&7) { + datap[i>>3] |= set<<(i&7); + } else { + datap[i>>3] = set; + } + } + return object; + } + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return 0; + } + } else if (value_p->format == vpiOctStrVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { int chars = (vop->varp()->packed().elements()+2)/3; int bytes = VL_BYTES_I(vop->varp()->packed().elements()); - int len = strlen(value_p->value.str); - CData* datap = (reinterpret_cast(vop->varDatap())); + int len = strlen(value_p->value.str); + CData* datap = (reinterpret_cast(vop->varDatap())); div_t idx; datap[0] = 0; // reset zero'th byte for (int i=0; ivalue.str[len-i-1]; if (digit >= '0' && digit <= '7') { val.half = digit-'0'; - } else { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Non octal character '%c' in '%s' as value %s for %s", - VL_FUNC, digit, value_p->value.str, - VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + } else { + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Non octal character '%c' in '%s' as value %s for %s", + VL_FUNC, digit, value_p->value.str, + VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); val.half = 0; - } - } else { + } + } else { val.half = 0; - } + } // align octal character to position within vector, note that // the three bits may straddle a byte bounday so two byte wide // assignments are made to adjacent bytes - but not if the least @@ -1608,70 +1617,73 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, datap[idx.quot] |= val.byte[0]; // or in value if ((idx.quot+1) < bytes) { datap[idx.quot+1] = val.byte[1]; // this also resets - // all bits to 0 prior to or'ing above + // all bits to 0 prior to or'ing above } } // mask off non existant bits in the most significant byte if (idx.quot == (bytes-1)) { datap[idx.quot] &= vop->mask_byte(idx.quot); - } else if (idx.quot+1 == (bytes-1)) { + } else if (idx.quot+1 == (bytes-1)) { datap[idx.quot+1] &= vop->mask_byte(idx.quot+1); - } + } // zero off remaining top bytes for (int i=idx.quot+2; iformat), vop->fullname()); - return 0; - } - } else if (value_p->format == vpiDecStrVal) { + datap[i] = 0; + } + return object; + } + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return 0; + } + } else if (value_p->format == vpiDecStrVal) { char remainder[16]; unsigned long long val; int success = sscanf(value_p->value.str, "%30llu%15s", &val, remainder); if (success < 1) { - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Parsing failed for '%s' as value %s for %s", - VL_FUNC, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Parsing failed for '%s' as value %s for %s", + VL_FUNC, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); return 0; - } + } if (success > 1) { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Trailing garbage '%s' in '%s' as value %s for %s", + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Trailing garbage '%s' in '%s' as value %s for %s", VL_FUNC, remainder, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - } - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : *(reinterpret_cast(vop->varDatap())) = val & vop->mask(); break; - case VLVT_UINT16: *(reinterpret_cast(vop->varDatap())) = val & vop->mask(); break; - case VLVT_UINT32: *(reinterpret_cast(vop->varDatap())) = val & vop->mask(); break; - case VLVT_UINT64: *(reinterpret_cast(vop->varDatap())) = val; - (reinterpret_cast(vop->varDatap()))[1] &= vop->mask(); break; - case VLVT_WDATA: - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } + } + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + *(reinterpret_cast(vop->varDatap())) = val & vop->mask(); break; + case VLVT_UINT16: + *(reinterpret_cast(vop->varDatap())) = val & vop->mask(); break; + case VLVT_UINT32: + *(reinterpret_cast(vop->varDatap())) = val & vop->mask(); break; + case VLVT_UINT64: *(reinterpret_cast(vop->varDatap())) = val; + (reinterpret_cast(vop->varDatap()))[1] &= vop->mask(); break; + case VLVT_WDATA: + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return 0; + } return object; - } else if (value_p->format == vpiHexStrVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { + } else if (value_p->format == vpiHexStrVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { int chars = (vop->varp()->packed().elements()+3)>>2; - CData* datap = (reinterpret_cast(vop->varDatap())); + CData* datap = (reinterpret_cast(vop->varDatap())); char* val = value_p->value.str; // 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; - } - int len = strlen(val); - for (int i=0; i= 'a' && digit <= 'f') hex = digit - 'a' + 10; else if (digit >= 'A' && digit <= 'F') hex = digit - 'A' + 10; else { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Non hex character '%c' in '%s' as value %s for %s", + _VL_VPI_WARNING(__FILE__, __LINE__, + "%s: Non hex character '%c' in '%s' as value %s for %s", VL_FUNC, digit, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - hex = 0; - } - } else { - hex = 0; - } + hex = 0; + } + } else { + hex = 0; + } // assign hex digit value to destination - if (i&1) { - datap[i>>1] |= hex<<4; - } else { + if (i&1) { + datap[i>>1] |= hex<<4; + } else { datap[i>>1] = hex; // this also resets all - // bits to 0 prior to or'ing above of the msb + // bits to 0 prior to or'ing above of the msb } } // apply bit mask to most significant byte datap[(chars-1)>>1] &= vop->mask_byte((chars-1)>>1); - return object; - } - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } - } else if (value_p->format == vpiStringVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { + return object; + } + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), + vop->fullname()); + return 0; + } + } else if (value_p->format == vpiStringVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { int bytes = VL_BYTES_I(vop->varp()->packed().elements()); - int len = strlen(value_p->value.str); - CData* datap = (reinterpret_cast(vop->varDatap())); - for (int i=0; ivalue.str); + CData* datap = (reinterpret_cast(vop->varDatap())); + for (int i=0; ivalue.str[len-i-1]:0; - } - return object; - } - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } - } else if (value_p->format == vpiIntVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8: - *(reinterpret_cast(vop->varDatap())) = vop->mask() & value_p->value.integer; - return object; - case VLVT_UINT16: - *(reinterpret_cast(vop->varDatap())) = vop->mask() & value_p->value.integer; - return object; - case VLVT_UINT32: - *(reinterpret_cast(vop->varDatap())) = vop->mask() & value_p->value.integer; - return object; + } + return object; + } + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), + vop->fullname()); + return 0; + } + } else if (value_p->format == vpiIntVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + *(reinterpret_cast(vop->varDatap())) + = vop->mask() & value_p->value.integer; + return object; + case VLVT_UINT16: + *(reinterpret_cast(vop->varDatap())) + = vop->mask() & value_p->value.integer; + return object; + case VLVT_UINT32: + *(reinterpret_cast(vop->varDatap())) + = vop->mask() & value_p->value.integer; + return object; case VLVT_WDATA: // FALLTHRU case VLVT_UINT64: // FALLTHRU default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } - } + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC, + VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return 0; + } + } _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return NULL; + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return NULL; } _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for ??", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format)); + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format)); return NULL; } void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, - PLI_INT32 *index_p, PLI_UINT32 num) { + PLI_INT32 *index_p, PLI_UINT32 num) { _VL_VPI_UNIMP(); return; } void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, - PLI_INT32 *index_p, PLI_UINT32 num) { + PLI_INT32 *index_p, PLI_UINT32 num) { _VL_VPI_UNIMP(); return; } @@ -1771,19 +1789,19 @@ void vpi_get_time(vpiHandle object, p_vpi_time time_p) { VerilatedVpiImp::assertOneCheck(); // cppcheck-suppress nullPointer if (VL_UNLIKELY(!time_p)) { - _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_get_time with NULL value pointer"); - return; + _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_get_time with NULL value pointer"); + return; } if (time_p->type == vpiSimTime) { - QData qtime = VL_TIME_Q(); - WData itime[2]; - VL_SET_WQ(itime, qtime); - time_p->low = itime[0]; - time_p->high = itime[1]; - return; + QData qtime = VL_TIME_Q(); + WData itime[2]; + VL_SET_WQ(itime, qtime); + time_p->low = itime[0]; + time_p->high = itime[1]; + return; } _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported type (%d)", - VL_FUNC, time_p->type); + VL_FUNC, time_p->type); return; } @@ -1792,7 +1810,7 @@ void vpi_get_time(vpiHandle object, p_vpi_time time_p) { PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) { VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); - return VL_FOPEN_S(filenamep,"wb"); + return VL_FOPEN_S(filenamep, "wb"); } PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) { @@ -1809,7 +1827,7 @@ PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) { VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); int chars = vpi_mcd_vprintf(mcd, formatp, ap); va_end(ap); return chars; @@ -1819,7 +1837,7 @@ PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) { VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); va_list ap; - va_start(ap,formatp); + va_start(ap, formatp); int chars = vpi_vprintf(formatp, ap); va_end(ap); return chars; @@ -1881,7 +1899,7 @@ PLI_INT32 vpi_free_object(vpiHandle object) { } PLI_INT32 vpi_release_handle(vpiHandle object) { - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_release_handle %p\n",object);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_release_handle %p\n", object);); VerilatedVpiImp::assertOneCheck(); VerilatedVpio* vop = VerilatedVpio::castp(object); _VL_VPI_ERROR_RESET(); @@ -1917,21 +1935,21 @@ PLI_INT32 vpi_put_userdata(vpiHandle obj, void *userdata) { } PLI_INT32 vpi_control(PLI_INT32 operation, ...) { - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_control %d\n",operation);); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_control %d\n", operation);); VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); switch (operation) { case vpiFinish: { - VL_FINISH_MT(__FILE__,__LINE__,"*VPI*"); - return 1; + VL_FINISH_MT(__FILE__, __LINE__, "*VPI*"); + return 1; } case vpiStop: { - VL_STOP_MT(__FILE__,__LINE__,"*VPI*"); - return 1; + VL_STOP_MT(__FILE__, __LINE__, "*VPI*"); + return 1; } } _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, ignoring", - VL_FUNC, VerilatedVpiError::strFromVpiProp(operation)); + VL_FUNC, VerilatedVpiError::strFromVpiProp(operation)); return 0; }