diff --git a/include/verilated.cpp b/include/verilated.cpp index 53dfcdad8..de2e6412f 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -311,7 +311,7 @@ WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE { if (i<(VL_WORDS_I(obits)-1)) { outwp[i] = vl_rand64(); } else { - outwp[i] = vl_rand64() & VL_MASK_I(obits); + outwp[i] = vl_rand64() & VL_MASK_E(obits); } } return outwp; @@ -323,7 +323,7 @@ IData VL_RAND_RESET_I(int obits) VL_MT_SAFE { if (Verilated::randReset()!=1) { // if 2, randomize data = VL_RANDOM_I(obits); } - if (obits<32) data &= VL_MASK_I(obits); + data &= VL_MASK_I(obits); return data; } QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE { @@ -332,7 +332,7 @@ QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE { if (Verilated::randReset()!=1) { // if 2, randomize data = VL_RANDOM_Q(obits); } - if (obits<64) data &= VL_MASK_Q(obits); + data &= VL_MASK_Q(obits); return data; } WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE { @@ -340,7 +340,7 @@ WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE { if (i<(VL_WORDS_I(obits)-1)) { outwp[i] = VL_RAND_RESET_I(32); } else { - outwp[i] = VL_RAND_RESET_I(32) & VL_MASK_I(obits); + outwp[i] = VL_RAND_RESET_I(32) & VL_MASK_E(obits); } } return outwp; @@ -356,7 +356,9 @@ WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE { void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) VL_MT_SAFE { VL_PRINTF_MT(" Data: w%d: ", lbits); - for (int i=VL_WORDS_I(lbits)-1; i>=0; --i) { VL_PRINTF_MT("%08x ", iwp[i]); } + for (int i = VL_WORDS_I(lbits) - 1; i >= 0; --i) { + VL_PRINTF_MT("%08x ", iwp[i]); + } VL_PRINTF_MT("\n"); } @@ -499,7 +501,7 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, } 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); + WData rhsw[VL_WQ_WORDS_E]; VL_SET_WQ(rhsw, rhs); 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 { @@ -520,14 +522,14 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W if (rsign && VL_SIGN_W(rbits, rwp)) { int words = VL_WORDS_I(obits); VL_ZERO_W(obits, owp); - IData lor = 0; // 0=all zeros, ~0=all ones, else mix + EData lor = 0; // 0=all zeros, ~0=all ones, else mix for (int i=1; i < (words-1); ++i) { lor |= lwp[i]; } - lor |= ( (lwp[words-1] == VL_MASK_I(rbits)) ? ~VL_UL(0) : 0); + lor |= ( (lwp[words-1] == VL_MASK_E(rbits)) ? ~VL_EUL(0) : 0); if (lor==0 && lwp[0]==0) { return owp; } // "X" so return 0 else if (lor==0 && lwp[0]==1) { owp[0] = 1; return owp; } // 1 - else if (lsign && lor == ~VL_UL(0) && lwp[0]==~VL_UL(0)) { // -1 + else if (lsign && lor == ~VL_EUL(0) && lwp[0] == ~VL_EUL(0)) { // -1 if (rwp[0] & 1) { return VL_ALLONES_W(obits, owp); } // -1^odd=-1 else { owp[0] = 1; return owp; } // -1^even=1 } @@ -538,7 +540,7 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W 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); + WData rhsw[VL_WQ_WORDS_E]; VL_SET_WQ(rhsw, rhs); return VL_POWSS_WWW(obits, lbits, rbits, owp, lwp, rhsw, lsign, rsign); } QData VL_POWSS_QQW(int obits, int, int rbits, @@ -576,7 +578,7 @@ std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE { for (int nibble_bit = 0; nibble_bit < maxdecwidth; nibble_bit+=4) { if ((VL_BITRSHIFT_W(bcd, nibble_bit) & 0xf) >= 5) { VL_ZERO_RESET_W(maxdecwidth, tmp2); - tmp2[VL_BITWORD_I(nibble_bit)] |= 0x3 << VL_BITBIT_I(nibble_bit); + tmp2[VL_BITWORD_E(nibble_bit)] |= VL_EUL(0x3) << VL_BITBIT_E(nibble_bit); VL_ASSIGN_W(maxdecwidth, tmp, bcd); VL_ADD_W(VL_WORDS_I(maxdecwidth), bcd, tmp, tmp2); } @@ -599,7 +601,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_IDATASIZE) ? 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 @@ -691,7 +693,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA // Deal with all read-and-print somethings const int lbits = va_arg(ap, int); QData ld = 0; - WData qlwp[2]; + WData qlwp[VL_WQ_WORDS_E]; WDataInP lwp; if (lbits <= VL_QUADSIZE) { ld = _VL_VA_ARG_Q(ap, lbits); @@ -724,7 +726,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA static_cast(VL_EXTENDS_QQ(lbits, lbits, ld))); append = tmp; } else { - if (VL_SIGN_I(lbits, lwp[VL_WORDS_I(lbits)-1])) { + if (VL_SIGN_E(lbits, lwp[VL_WORDS_I(lbits) - 1])) { WData neg[VL_VALUE_STRING_MAX_WIDTH/4+2]; VL_NEGATE_W(VL_WORDS_I(lbits), neg, lwp); append = std::string("-") + VL_DECIMAL_NW(lbits, neg); @@ -966,7 +968,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf // 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}; + WData qowp[VL_WQ_WORDS_E]; VL_SET_WQ(qowp, VL_ULL(0)); WDataOutP owp = qowp; if (obits > VL_QUADSIZE) { owp = va_arg(ap, WDataOutP); @@ -1055,7 +1057,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf 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) { + } else if (obits <= VL_IDATASIZE) { 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); @@ -1112,9 +1114,9 @@ IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE { // any read data. This means we can't know in what location the first // character will finally live, so we need to copy. Yuk. IData bytes = VL_BYTES_I(obits); - char buffer[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; + char buffer[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1]; // V3Emit has static check that bytes < VL_TO_STRING_MAX_WORDS, but be safe - if (VL_UNCOVERABLE(bytes > VL_TO_STRING_MAX_WORDS*VL_WORDSIZE)) { + if (VL_UNCOVERABLE(bytes > VL_TO_STRING_MAX_WORDS * VL_EDATASIZE)) { VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: fgets buffer overrun"); // LCOV_EXCL_LINE } @@ -1135,20 +1137,22 @@ IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE { IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE { // While threadsafe, each thread can only access different file handles char modez[5]; - _VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode); + EData modee = mode; + _VL_VINT_TO_STRING(VL_IDATASIZE, modez, &modee); return VL_FOPEN_S(filename.c_str(), modez); } IData VL_FOPEN_QI(QData filename, IData mode) VL_MT_SAFE { // While threadsafe, each thread can only access different file handles - WData fnw[2]; VL_SET_WQ(fnw, filename); - return VL_FOPEN_WI(2, fnw, mode); + WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, filename); + return VL_FOPEN_WI(VL_WQ_WORDS_E, fnw, mode); } IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) VL_MT_SAFE { // While threadsafe, each thread can only access different file handles - char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; - _VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep); + char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1]; + _VL_VINT_TO_STRING(fnwords * VL_EDATASIZE, filenamez, filenamep); + EData modee = mode; char modez[5]; - _VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode); + _VL_VINT_TO_STRING(4 * sizeof(char), modez, &modee); return VL_FOPEN_S(filenamez, modez); } IData VL_FOPEN_S(const char* filenamep, const char* modep) VL_MT_SAFE { @@ -1277,7 +1281,7 @@ IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE { } IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) VL_MT_SAFE { - WData fnw[2]; VL_SET_WI(fnw, ld); + WData fnw[VL_WQ_WORDS_E]; VL_SET_WI(fnw, ld); va_list ap; va_start(ap, formatp); @@ -1286,7 +1290,7 @@ IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) VL_MT_SAFE { return got; } IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) VL_MT_SAFE { - WData fnw[2]; VL_SET_WQ(fnw, ld); + WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, ld); va_list ap; va_start(ap, formatp); @@ -1312,15 +1316,15 @@ IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_ void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int, QData filename, const void* memp, IData start, IData end) VL_MT_SAFE { - WData fnw[2]; VL_SET_WQ(fnw, filename); - return VL_WRITEMEM_W(hex, width, depth, array_lsb,2, fnw, memp, start, end); + WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, filename); + return VL_WRITEMEM_W(hex, width, depth, array_lsb, VL_WQ_WORDS_E, fnw, memp, start, end); } void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords, WDataInP filenamep, const void* memp, IData start, IData end) VL_MT_SAFE { - char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; - _VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep); + char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1]; + _VL_VINT_TO_STRING(fnwords * VL_EDATASIZE, filenamez, filenamep); std::string filenames(filenamez); return VL_WRITEMEM_N(hex, width, depth, array_lsb, filenames, memp, start, end); } @@ -1425,21 +1429,20 @@ void VL_WRITEMEM_N( } else { WDataInP memDatap = reinterpret_cast(memp); WDataInP datap = &memDatap[row_offset * VL_WORDS_I(width)]; - // output as a sequence of VL_WORDSIZE'd words + // output as a sequence of VL_EDATASIZE'd words // from MSB to LSB. Mask off the MSB word which could // contain junk above the top of valid data. - int word_idx = ((width - 1) / VL_WORDSIZE); + int word_idx = ((width - 1) / VL_EDATASIZE); bool first = true; while (word_idx >= 0) { - IData data = datap[word_idx]; + EData data = datap[word_idx]; if (first) { - data &= VL_MASK_I(width); - int top_word_nbits = ((width - 1) & 0x1f) + 1; + data &= VL_MASK_E(width); + int top_word_nbits = ((width - 1) & (VL_EDATASIZE - 1)) + 1; fprintf(fp, memhFormat(top_word_nbits), data); } else { fprintf(fp, "%08x", data); } - word_idx--; first = false; } @@ -1477,7 +1480,7 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size, SData* datap = &(reinterpret_cast(memp))[entry]; if (shift == start_shift) { *datap = 0; } *datap |= (c << shift) & VL_MASK_I(width); - } else if (width <= VL_WORDSIZE) { + } else if (width <= VL_IDATASIZE) { IData* datap = &(reinterpret_cast(memp))[entry]; if (shift == start_shift) { *datap = 0; } *datap |= (c << shift) & VL_MASK_I(width); @@ -1486,10 +1489,10 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size, if (shift == start_shift) { *datap = 0; } *datap |= ((static_cast(c) << static_cast(shift)) & VL_MASK_Q(width)); - } else { - WDataOutP datap = &(reinterpret_cast(memp))[ entry*VL_WORDS_I(width) ]; + } else { + WDataOutP datap = &(reinterpret_cast(memp))[entry * VL_WORDS_I(width)]; if (shift == start_shift) { VL_ZERO_RESET_W(width, datap); } - datap[VL_BITWORD_I(shift)] |= (c << VL_BITBIT_I(shift)); + datap[VL_BITWORD_E(shift)] |= (static_cast(c) << VL_BITBIT_E(shift)); } // Prep for next ++read_count; @@ -1505,14 +1508,14 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size, void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int, QData filename, void* memp, IData start, IData end) VL_MT_SAFE { - WData fnw[2]; VL_SET_WQ(fnw, filename); - return VL_READMEM_W(hex, width, depth, array_lsb, 2, fnw, memp, start, end); + WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, filename); + return VL_READMEM_W(hex, width, depth, array_lsb, VL_WQ_WORDS_E, fnw, memp, start, end); } void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords, WDataInP filenamep, void* memp, IData start, IData end) VL_MT_SAFE { - char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; - _VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep); + char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1]; + _VL_VINT_TO_STRING(fnwords * VL_EDATASIZE, filenamez, filenamep); std::string filenames(filenamez); return VL_READMEM_N(hex, width, depth, array_lsb, filenames, memp, start, end); } @@ -1601,7 +1604,7 @@ void VL_READMEM_N( SData* datap = &(reinterpret_cast(memp))[entry]; if (!innum) { *datap = 0; } *datap = ((*datap << shift) + value) & VL_MASK_I(width); - } else if (width<=VL_WORDSIZE) { + } else if (width <= VL_IDATASIZE) { IData* datap = &(reinterpret_cast(memp))[entry]; if (!innum) { *datap = 0; } *datap = ((*datap << shift) + value) & VL_MASK_I(width); @@ -1642,12 +1645,12 @@ void VL_READMEM_N( } IData VL_SYSTEM_IQ(QData lhs) VL_MT_SAFE { - WData lhsw[2]; VL_SET_WQ(lhsw, lhs); - return VL_SYSTEM_IW(2, lhsw); + WData lhsw[VL_WQ_WORDS_E]; VL_SET_WQ(lhsw, lhs); + return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw); } IData VL_SYSTEM_IW(int lhswords, WDataInP lhsp) VL_MT_SAFE { - char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; - _VL_VINT_TO_STRING(lhswords*VL_WORDSIZE, filenamez, lhsp); + char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1]; + _VL_VINT_TO_STRING(lhswords * VL_EDATASIZE, filenamez, lhsp); int code = system(filenamez); // Yes, system() is threadsafe return code >> 8; // Want exit status } @@ -1803,8 +1806,8 @@ std::string VL_TOUPPER_NN(const std::string& ld) VL_MT_SAFE { std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE { // See also _VL_VINT_TO_STRING - char destout[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; - int obits = lwords * VL_WORDSIZE; + char destout[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1]; + int obits = lwords * VL_EDATASIZE; int lsb=obits-1; bool start=true; char* destp = destout; diff --git a/include/verilated.h b/include/verilated.h index 51620fc56..7634ef713 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -64,7 +64,8 @@ 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 +typedef vluint32_t EData; ///< Verilated pack element of WData array +typedef EData 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 @@ -671,21 +672,21 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish /// Return true if data[bit] set; not 0/1 return, but 0/non-zero return. #define VL_BITISSET_I(data,bit) ((data) & (VL_UL(1) << VL_BITBIT_I(bit))) #define VL_BITISSET_Q(data,bit) ((data) & (VL_ULL(1) << VL_BITBIT_Q(bit))) -#define VL_BITISSET_W(data,bit) ((data)[VL_BITWORD_I(bit)] & (VL_UL(1) << VL_BITBIT_I(bit))) -#define VL_BITISSETLIMIT_W(data,width,bit) \ - (((bit)<(width)) && (data)[VL_BITWORD_I(bit)] & (VL_UL(1) << VL_BITBIT_I(bit))) +#define VL_BITISSET_E(data,bit) ((data) & (VL_EUL(1) << VL_BITBIT_E(bit))) +#define VL_BITISSET_W(data,bit) ((data)[VL_BITWORD_E(bit)] & (VL_EUL(1) << VL_BITBIT_E(bit))) +#define VL_BITISSETLIMIT_W(data,width,bit) (((bit) < (width)) && VL_BITISSET_W(data,bit)) /// Shift appropriate word by bit. Does not account for wrapping between two words -#define VL_BITRSHIFT_W(data,bit) ((data)[VL_BITWORD_I(bit)] >> VL_BITBIT_I(bit)) +#define VL_BITRSHIFT_W(data,bit) ((data)[VL_BITWORD_E(bit)] >> VL_BITBIT_E(bit)) /// Create two 32-bit words from quadword /// WData is always at least 2 words; does not clean upper bits #define VL_SET_WQ(owp,data) { (owp)[0] = static_cast(data); \ - (owp)[1] = static_cast((data)>>VL_WORDSIZE); } + (owp)[1] = static_cast((data) >> VL_EDATASIZE); } #define VL_SET_WI(owp,data) { (owp)[0] = static_cast(data); (owp)[1] = 0; } #define VL_SET_QW(lwp) \ ( (static_cast((lwp)[0])) \ - | (static_cast((lwp)[1]) << (static_cast(VL_WORDSIZE)) )) + | (static_cast((lwp)[1]) << (static_cast(VL_EDATASIZE)) )) #define _VL_SET_QII(ld,rd) ((static_cast(ld)<(rd)) /// Return FILE* from IData @@ -718,8 +719,10 @@ static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { // (Requires clean input) #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_SIGN_E(nbits,lhs) ((lhs) >> VL_BITBIT_E((nbits) - VL_EUL(1))) +#define VL_SIGN_W(nbits,rwp) \ + ((rwp)[VL_BITWORD_E((nbits) - VL_EUL(1))] >> VL_BITBIT_E((nbits) - VL_EUL(1))) +#define VL_SIGNONES_E(nbits, lhs) (-(VL_SIGN_E(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 @@ -787,13 +790,13 @@ extern double sc_time_stamp(); #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); + owp[words-1] &= VL_MASK_E(obits); 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); + owp[words-1] = lwp[words-1] & VL_MASK_E(obits); return owp; } static inline WDataOutP VL_ZERO_W(int obits, WDataOutP owp) VL_MT_SAFE { @@ -803,8 +806,8 @@ static inline WDataOutP VL_ZERO_W(int obits, WDataOutP owp) VL_MT_SAFE { } static inline WDataOutP VL_ALLONES_W(int obits, WDataOutP owp) VL_MT_SAFE { int words = VL_WORDS_I(obits); - for (int i=0; (i < (words-1)); ++i) owp[i] = ~VL_UL(0); - owp[words-1] = VL_MASK_I(obits); + for (int i = 0; i < (words - 1); ++i) owp[i] = ~VL_EUL(0); + owp[words-1] = VL_MASK_E(obits); return owp; } @@ -832,12 +835,12 @@ static inline void VL_ASSIGNBIT_II(int, int bit, IData& lhsr, IData rhs) VL_PURE } static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) VL_PURE { lhsr = ((lhsr & ~(VL_ULL(1)<(rhs) << VL_BITBIT_Q(bit))); } static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) VL_MT_SAFE { - IData orig = owp[VL_BITWORD_I(bit)]; - owp[VL_BITWORD_I(bit)] = ((orig & ~(VL_UL(1)<(rhs) << VL_BITBIT_E(bit))); } // Alternative form that is an instruction faster when rhs is constant one. static inline void VL_ASSIGNBIT_IO(int, int bit, CData& lhsr, IData) VL_PURE { @@ -853,8 +856,8 @@ static inline void VL_ASSIGNBIT_QO(int, int bit, QData& lhsr, IData) VL_PURE { lhsr = (lhsr | (VL_ULL(1)<((svar).read().get_word(1)))<((svar).read().get_word(1)))< _butemp = (svar).read(); \ for (int i=0; i < words; ++i) { \ - int msb = ((i+1)*VL_WORDSIZE) - 1; \ + int msb = ((i + 1) * VL_IDATASIZE) - 1; \ msb = (msb >= (obits)) ? ((obits)-1) : msb; \ - (owp)[i] = _butemp.range(msb, i*VL_WORDSIZE).to_uint(); \ + (owp)[i] = _butemp.range(msb, i * VL_IDATASIZE).to_uint(); \ } \ - (owp)[words-1] &= VL_MASK_I(obits); \ + (owp)[words-1] &= VL_MASK_E(obits); \ } // Copying verilog format from systemc integers and bit vectors. @@ -906,7 +909,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAF #define VL_ASSIGN_SWQ(obits,svar,rd) { \ sc_bv<(obits)> _bvtemp; \ _bvtemp.set_word(0, static_cast(rd)); \ - _bvtemp.set_word(1, static_cast((rd)>>VL_WORDSIZE)); \ + _bvtemp.set_word(1, static_cast((rd) >> VL_IDATASIZE)); \ (svar).write(_bvtemp); \ } #define VL_ASSIGN_SWW(obits,svar,rwp) { \ @@ -922,9 +925,9 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAF #define VL_ASSIGN_SBW(obits,svar,rwp) { \ sc_biguint<(obits)> _butemp; \ for (int i=0; i < VL_WORDS_I(obits); ++i) { \ - int msb = ((i+1)*VL_WORDSIZE) - 1; \ + int msb = ((i + 1) * VL_IDATASIZE) - 1; \ msb = (msb >= (obits)) ? ((obits)-1) : msb; \ - _butemp.range(msb, i*VL_WORDSIZE) = (rwp)[i]; \ + _butemp.range(msb, i * VL_IDATASIZE) = (rwp)[i]; \ } \ (svar).write(_butemp); \ } @@ -943,17 +946,17 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAF static inline WDataOutP VL_EXTEND_WI(int obits, int, WDataOutP owp, IData ld) VL_MT_SAFE { // Note for extracts that obits != lbits owp[0] = ld; - for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0; + for (int i = 1; i < VL_WORDS_I(obits); ++i) owp[i] = 0; return owp; } static inline WDataOutP VL_EXTEND_WQ(int obits, int, WDataOutP owp, QData ld) VL_MT_SAFE { VL_SET_WQ(owp, ld); - for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0; + for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0; 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; + 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; } @@ -970,24 +973,24 @@ static inline QData VL_EXTENDS_QQ(int, int lbits, QData lhs) VL_PURE { } static inline WDataOutP VL_EXTENDS_WI(int obits, int lbits, WDataOutP owp, IData ld) VL_MT_SAFE { - 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; + EData sign = VL_SIGNONES_E(lbits, static_cast(ld)); + owp[0] = ld | (sign & ~VL_MASK_E(lbits)); + for (int i = 1; i < VL_WORDS_I(obits); ++i) owp[i] = sign; 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]); - owp[1] |= sign & ~VL_MASK_I(lbits); - for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = sign; + EData sign = VL_SIGNONES_E(lbits, owp[1]); + owp[1] |= sign & ~VL_MASK_E(lbits); + for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = sign; 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]); - 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; + for (int i = 0; i < VL_WORDS_I(lbits)-1; ++i) owp[i] = lwp[i]; + int lmsw = VL_WORDS_I(lbits) - 1; + EData sign = VL_SIGNONES_E(lbits, lwp[lmsw]); + owp[lmsw] = lwp[lmsw] | (sign & ~VL_MASK_E(lbits)); + for (int i = VL_WORDS_I(lbits); i < VL_WORDS_I(obits); ++i) owp[i] = sign; return owp; } @@ -999,9 +1002,9 @@ 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]; - for (int i=1; i < words-1; ++i) combine &= lwp[i]; - combine &= ~VL_MASK_I(lbits) | lwp[words-1]; + EData combine = lwp[0]; + for (int i = 1; i < words - 1; ++i) combine &= lwp[i]; + combine &= ~VL_MASK_E(lbits) | lwp[words-1]; return ((~combine)==0); } @@ -1009,7 +1012,7 @@ 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; + EData equal = 0; for (int i=0; i < words; ++i) equal |= lwp[i]; return (equal != 0); } @@ -1061,7 +1064,7 @@ static inline IData VL_REDXOR_64(QData r) VL_PURE { #endif } static inline IData VL_REDXOR_W(int words, WDataInP lwp) VL_MT_SAFE { - IData r = lwp[0]; + EData r = lwp[0]; for (int i=1; i < words; ++i) r ^= lwp[i]; return VL_REDXOR_32(r); } @@ -1078,9 +1081,10 @@ static inline IData VL_COUNTONES_I(IData lhs) VL_PURE { static inline IData VL_COUNTONES_Q(QData lhs) VL_PURE { return VL_COUNTONES_I(static_cast(lhs)) + VL_COUNTONES_I(static_cast(lhs>>32)); } +#define VL_COUNTONES_E VL_COUNTONES_I static inline IData VL_COUNTONES_W(int words, WDataInP lwp) VL_MT_SAFE { - IData r = 0; - for (int i=0; (i < words); ++i) r+=VL_COUNTONES_I(lwp[i]); + EData r = 0; + for (int i = 0; i < words; ++i) r += VL_COUNTONES_E(lwp[i]); return r; } @@ -1091,7 +1095,7 @@ 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; + EData one = 0; for (int i=0; (i < words); ++i) { if (lwp[i]) { if (one) return 0; @@ -1136,12 +1140,12 @@ static inline IData VL_CLOG2_Q(QData lhs) VL_PURE { 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; + EData 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; + for (int bit = VL_EDATASIZE - 1; bit >= 0; --bit) { + if (VL_UNLIKELY(VL_BITISSET_E(lwp[i], bit))) { + return i * VL_EDATASIZE + bit + adjust; } } // Can't get here - one bit must be set @@ -1154,9 +1158,9 @@ 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; + for (int bit = VL_EDATASIZE - 1; bit >= 0; --bit) { + if (VL_UNLIKELY(VL_BITISSET_E(lwp[i], bit))) { + return i * VL_EDATASIZE + bit + 1; } } // Can't get here - one bit must be set @@ -1217,7 +1221,7 @@ static inline WDataOutP VL_NOT_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_S // Output clean, AND MUST BE CLEAN static inline IData VL_EQ_W(int words, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { - int nequal = 0; + EData nequal = 0; for (int i=0; (i < words); ++i) nequal |= (lwp[i] ^ rwp[i]); return (nequal==0); } @@ -1286,8 +1290,8 @@ 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; // We need to flip sense if negative comparison - IData lsign = VL_SIGN_I(lbits, lwp[i]); - IData rsign = VL_SIGN_I(lbits, rwp[i]); + EData lsign = VL_SIGN_E(lbits, lwp[i]); + EData rsign = VL_SIGN_E(lbits, rwp[i]); if (!lsign && rsign) return 1; // + > - if (lsign && !rsign) return -1; // - < + for (; i>=0; --i) { @@ -1300,6 +1304,22 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { //========================================================================= // Math +// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround, +// we can't just +//# define VL_NEGATE_I(data) (-(data)) +static inline IData VL_NEGATE_I(IData data) VL_PURE { return -data; } +static inline QData VL_NEGATE_Q(QData data) VL_PURE { return -data; } +static inline EData VL_NEGATE_E(EData data) VL_PURE { return -data; } + +static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { + EData carry = 1; + for (int i = 0; i < words; ++i) { + owp[i] = ~lwp[i] + carry; + carry = (owp[i] < ~lwp[i]); + } + return owp; +} + // 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; @@ -1312,40 +1332,25 @@ static inline int _VL_CMPS_W(int lbits, 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); } + // Last output word is dirty return owp; } 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); - } - return owp; -} - -// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround, -// we can't just -//# define VL_NEGATE_I(data) (-(data)) -static inline IData VL_NEGATE_I(IData data) VL_PURE { return -data; } -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 + if (i==0) ++carry; // Negation of rwp owp[i] = (carry & VL_ULL(0xffffffff)); carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); } + // Last output word is dirty return owp; } @@ -1385,20 +1390,20 @@ static inline WDataOutP VL_MULS_WWW(int, int lbits, int, WData rwstore[VL_MULS_MAX_WORDS]; WDataInP lwusp = lwp; WDataInP rwusp = rwp; - IData lneg = VL_SIGN_I(lbits, lwp[words-1]); + EData lneg = VL_SIGN_E(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 + lwstore[words-1] &= VL_MASK_E(lbits); // Clean it } - IData rneg = VL_SIGN_I(lbits, rwp[words-1]); + EData rneg = VL_SIGN_E(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 + rwstore[words-1] &= VL_MASK_E(lbits); // Clean it } 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 + owp[words-1] &= VL_MASK_E(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> VL_ULL(32)) & VL_ULL(0xffffffff); } - //Not needed: owp[words-1] |= 1<(ld); + if (hword == lword) { // know < EData bits because above checks it + EData insmask = (VL_MASK_E(hoffset - loffset + 1)) << loffset; + owp[lword] = (owp[lword] & ~insmask) | ((lde << loffset) & insmask); } else { - IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0; - IData linsmask = (VL_MASK_I(31-loffset+1))<>nbitsonright) & hinsmask); + EData hinsmask = (VL_MASK_E(hoffset - 0 + 1)) << 0; + EData linsmask = (VL_MASK_E((VL_EDATASIZE - 1) - loffset + 1)) << loffset; + int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword + owp[lword] = (owp[lword] & ~linsmask) | ((lde << loffset) & linsmask); + owp[hword] = (owp[hword] & ~hinsmask) | ((lde >> nbitsonright) & hinsmask); } } } @@ -1605,11 +1611,11 @@ static inline void _VL_INSERT_WI(int, WDataOutP owp, IData ld, int hbit, int lbi // INTERNAL: Stuff large LHS bit 0++ into OUTPUT at specified offset // lwp may be "dirty" static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int lbit) VL_MT_SAFE { - int hoffset = hbit & VL_SIZEBITS_I; - int loffset = lbit & VL_SIZEBITS_I; - int lword = VL_BITWORD_I(lbit); - int words = VL_WORDS_I(hbit-lbit+1); - if (hoffset==VL_SIZEBITS_I && loffset==0) { + int hoffset = hbit & VL_SIZEBITS_E; + int loffset = lbit & VL_SIZEBITS_E; + int lword = VL_BITWORD_E(lbit); + int words = VL_WORDS_I(hbit - lbit + 1); + if (hoffset == VL_SIZEBITS_E && 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); + EData d = lwp[i] >> nbitsonright; + EData od = (d & ~linsmask) | (owp[oword] & linsmask); + if (oword == hword) + owp[oword] = (owp[oword] & ~hinsmask) | (od & hinsmask); else owp[oword] = od; } } @@ -1651,7 +1661,7 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int } 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); + WData lwp[VL_WQ_WORDS_E]; VL_SET_WQ(lwp, ld); _VL_INSERT_WW(obits, owp, lwp, hbit, lbit); } @@ -1748,7 +1758,7 @@ static inline IData VL_STREAML_FAST_III(int, int lbits, int, IData ld, IData rd_ case 4: ret = ((ret >> 16) | (ret << 16)); } - return ret >> (VL_WORDSIZE - lbits); + return ret >> (VL_IDATASIZE - lbits); } static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_log2) VL_PURE { @@ -1818,8 +1828,8 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, for (int sbit=0; sbit=1; --i) { - iowp[i] = ((iowp[i]<> (32-rd)) & linsmask); + iowp[i] = ((iowp[i]<> (VL_EDATASIZE - 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; } else if (bit_shift==0) { // Aligned word shift (<<0,<<32,<<64 etc) @@ -1969,8 +1979,8 @@ static inline QData VL_SHIFTL_QQW(int obits, int, int rbits, QData lhs, WDataInP // expression. Thus consider this when optimizing. (And perhaps have 2 funcs?) static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int, WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE { - int word_shift = VL_BITWORD_I(rd); // Maybe 0 - int bit_shift = VL_BITBIT_I(rd); + int word_shift = VL_BITWORD_E(rd); // Maybe 0 + int bit_shift = VL_BITBIT_E(rd); if (rd >= static_cast(obits)) { // rd may be huge with MSB set 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) @@ -1978,8 +1988,8 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int, 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) + int loffset = rd & VL_SIZEBITS_E; + int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword (know loffset!=0) // Middle words int words = VL_WORDS_I(obits-rd); for (int i=0; i= 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); + owp[lmsw] &= VL_MASK_E(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); + if (copy_words >= 0) owp[copy_words - 1] |= ~VL_MASK_E(obits) & sign; + for (int i = copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = sign; + owp[lmsw] &= VL_MASK_E(lbits); } else { - int loffset = rd & VL_SIZEBITS_I; - int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0) + int loffset = rd & VL_SIZEBITS_E; + int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword (know loffset!=0) // Middle words int words = VL_WORDS_I(obits-rd); for (int i=0; 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; - } + EData overshift = 0; // Huge shift 1>>32 or more + for (int i = 1; i < VL_WORDS_I(rbits); ++i) { + overshift |= rwp[i]; + } + if (VL_UNLIKELY(overshift)) { + int lmsw = VL_WORDS_I(obits) - 1; + EData sign = VL_SIGNONES_E(lbits, lwp[lmsw]); + for (int j = 0; j <= lmsw; ++j) owp[j] = sign; + owp[lmsw] &= VL_MASK_E(lbits); + return owp; } 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); - } + EData overshift = 0; // Huge shift 1>>32 or more + for (int i = 1; i < VL_WORDS_I(rbits); ++i) { + overshift |= rwp[i]; + } + if (VL_UNLIKELY(overshift)) { + IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative + return VL_CLEAN_II(obits, obits, sign); } 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); - } + EData overshift = 0; // Huge shift 1>>32 or more + for (int i = 1; i < VL_WORDS_I(rbits); ++i) { + overshift |= rwp[i]; + } + if (VL_UNLIKELY(overshift)) { + QData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative + return VL_CLEAN_QQ(obits, obits, sign); } 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); + WData rwp[VL_WQ_WORDS_E]; 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); + WData rwp[VL_WQ_WORDS_E]; VL_SET_WQ(rwp, rhs); return VL_SHIFTRS_QQW(obits, lbits, rbits, lhs, rwp); } @@ -2124,12 +2140,12 @@ static inline QData VL_SHIFTRS_QQQ(int obits, int lbits, int rbits, QData lhs, Q #define VL_BITSEL_IQII(obits,lbits,rbits,zbits,lhs,rhs) (static_cast((lhs)>>(rhs))) static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData rd) VL_MT_SAFE { - int word = VL_BITWORD_I(rd); + int word = VL_BITWORD_E(rd); if (VL_UNLIKELY(rd > static_cast(lbits))) { 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_E(rd)); } } @@ -2144,12 +2160,12 @@ static inline IData VL_SEL_IWII(int, int lbits, int, int, int msb = lsb+width-1; if (VL_UNLIKELY(msb>lbits)) { return ~0; // Spec says you can go outside the range of a array. Don't coredump if so. - } else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast(lsb))) { + } else if (VL_BITWORD_E(msb) == VL_BITWORD_E(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)]<lbits)) { return ~0; // Spec says you can go outside the range of a array. Don't coredump if so. - } else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast(lsb))) { + } else if (VL_BITWORD_E(msb) == VL_BITWORD_E(static_cast(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)]); + } else if (VL_BITWORD_E(msb) == 1 + VL_BITWORD_E(static_cast(lsb))) { + int nbitsfromlow = VL_EDATASIZE - VL_BITBIT_E(lsb); + QData hi = (lwp[VL_BITWORD_E(msb)]); QData lo = VL_BITRSHIFT_W(lwp, lsb); return (hi<lbits)) { // Outside bounds, for (int i=0; i>loffset; int upperword = i+word_shift+1; - if (upperword <= static_cast(VL_BITWORD_I(msb))) { - owp[i] |= lwp[upperword]<< nbitsfromlow; + if (upperword <= static_cast(VL_BITWORD_E(msb))) { + owp[i] |= lwp[upperword] << nbitsfromlow; } } for (int i=words; i= 0; --w) { v = newval[w]; - for (int i = 28; i >= 0; i-=4) { + for (int i = (32 - 4); i >= 0; i-=4) { s[0] = '0' + ((v>>(i+3))&1); s[1] = '0' + ((v>>(i+2))&1); s[2] = '0' + ((v>>(i+1))&1); diff --git a/include/verilated_fst_c.h b/include/verilated_fst_c.h index a61a2c199..bda5a66be 100644 --- a/include/verilated_fst_c.h +++ b/include/verilated_fst_c.h @@ -65,7 +65,7 @@ private: std::vector m_valueStrBuffer; char* word2Str(vluint32_t newval, int bits); char* quad2Str(vluint64_t newval, int bits); - char* array2Str(const vluint32_t *newval, int bits); + char* array2Str(const vluint32_t* newval, int bits); public: explicit VerilatedFst(void* fst=NULL); ~VerilatedFst() { if (m_fst == NULL) { fstWriterClose(m_fst); } } diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index 03d1824ca..699326971 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -278,14 +278,14 @@ std::string VL_TO_STRING(const VlQueue& obj) { extern std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE; inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE { - WData lw[2]; VL_SET_WQ(lw, lhs); - return VL_CVT_PACK_STR_NW(2, lw); + WData lw[VL_WQ_WORDS_E]; VL_SET_WQ(lw, lhs); + return VL_CVT_PACK_STR_NW(VL_WQ_WORDS_E, lw); } inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) VL_PURE { return lhs; } inline std::string VL_CVT_PACK_STR_NI(IData lhs) VL_PURE { - WData lw[1]; lw[0] = lhs; + WData lw[1]; VL_SET_WI(lw, lhs); return VL_CVT_PACK_STR_NW(1, lw); } inline std::string VL_CONCATN_NNN(const std::string& lhs, const std::string& rhs) VL_PURE { @@ -331,7 +331,7 @@ inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, SData& rdr) return got; } inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, IData& rdr) VL_MT_SAFE { - WData rwp[2]; // WData must always be at least 2 + WData rwp[2]; IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp); if (got) rdr = rwp[0]; return got; diff --git a/include/verilated_threads.h b/include/verilated_threads.h index bb7ef2650..b5e4817d7 100644 --- a/include/verilated_threads.h +++ b/include/verilated_threads.h @@ -153,7 +153,7 @@ public: #elif defined(__APPLE__) vluint32_t info[4]; __cpuid_count(1, 0, info[0], info[1], info[2], info[3]); - /* info[1] is EBX, bits 24-31 are APIC ID */ + // info[1] is EBX, bits 24-31 are APIC ID if ((info[3] & (1 << 9)) == 0) { return -1; // no APIC on chip } else { diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index f6c780dcd..439b9d555 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -1333,7 +1333,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) { VL_FATAL_MT(__FILE__, __LINE__, "", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile"); } - WDataInP datap = (reinterpret_cast(vop->varDatap())); + WDataInP datap = (reinterpret_cast(vop->varDatap())); for (int i=0; ivarp()->packed().elements()); - WDataOutP datap = (reinterpret_cast(vop->varDatap())); + WDataOutP datap = (reinterpret_cast(vop->varDatap())); for (int i=0; ivalue.vector[i].aval; if (i==(words-1)) { diff --git a/include/verilatedos.h b/include/verilatedos.h index 5be639aee..856b539a0 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -317,16 +317,20 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type //========================================================================= // Integer size macros -#define VL_BYTESIZE 8 ///< Bits in a byte -#define VL_SHORTSIZE 16 ///< Bits in a short -#define VL_WORDSIZE 32 ///< Bits in a word -#define VL_QUADSIZE 64 ///< Bits in a quadword -#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE) +#define VL_BYTESIZE 8 ///< Bits in a CData / byte +#define VL_SHORTSIZE 16 ///< Bits in a SData / short +#define VL_IDATASIZE 32 ///< Bits in a IData / word +#define VL_WORDSIZE IDATASIZE ///< Legacy define +#define VL_QUADSIZE 64 ///< Bits in a QData / quadword +#define VL_EDATASIZE 32 ///< Bits in a EData (WData entry) +#define VL_EDATASIZE_LOG2 5 ///< log2(VL_EDATASIZE) /// Bytes this number of bits needs (1 bit=1 byte) #define VL_BYTES_I(nbits) (((nbits) + (VL_BYTESIZE - 1)) / VL_BYTESIZE) -/// Words this number of bits needs (1 bit=1 word) -#define VL_WORDS_I(nbits) (((nbits) + (VL_WORDSIZE - 1)) / VL_WORDSIZE) +/// Words/EDatas this number of bits needs (1 bit=1 word) +#define VL_WORDS_I(nbits) (((nbits) + (VL_EDATASIZE - 1)) / VL_EDATASIZE) +/// Words/EDatas a quad requires +#define VL_WQ_WORDS_E VL_WORDS_I(VL_QUADSIZE) //========================================================================= // Class definition helpers @@ -345,8 +349,9 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type //========================================================================= // Base macros -#define VL_SIZEBITS_I (VL_WORDSIZE - 1) ///< Bit mask for bits in a word +#define VL_SIZEBITS_I (VL_IDATASIZE - 1) ///< Bit mask for bits in a word #define VL_SIZEBITS_Q (VL_QUADSIZE - 1) ///< Bit mask for bits in a quad +#define VL_SIZEBITS_E (VL_EDATASIZE - 1) ///< Bit mask for bits in a quad /// Mask for words with 1's where relevant bits are (0=all bits) #define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) \ @@ -354,9 +359,15 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type /// Mask for quads with 1's where relevant bits are (0=all bits) #define VL_MASK_Q(nbits) (((nbits) & VL_SIZEBITS_Q) \ ? ((VL_ULL(1) << ((nbits) & VL_SIZEBITS_Q) )-VL_ULL(1)) : VL_ULL(~0)) -#define VL_BITWORD_I(bit) ((bit)/VL_WORDSIZE) ///< Word number for a wide quantity -#define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long -#define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad +/// Mask for EData with 1's where relevant bits are (0=all bits) +#define VL_MASK_E(nbits) VL_MASK_I(nbits) +#define VL_EUL(n) VL_UL(n) ///< Make constant number EData sized + +#define VL_BITWORD_I(bit) ((bit) / VL_IDATASIZE) ///< Word number for sv DPI vectors +#define VL_BITWORD_E(bit) ((bit) >> VL_EDATASIZE_LOG2) ///< Word number for a wide quantity +#define VL_BITBIT_I(bit) ((bit) & VL_SIZEBITS_I) ///< Bit number for a bit in a long +#define VL_BITBIT_Q(bit) ((bit) & VL_SIZEBITS_Q) ///< Bit number for a bit in a quad +#define VL_BITBIT_E(bit) ((bit) & VL_SIZEBITS_E) ///< Bit number for a bit in a EData //========================================================================= // Floating point diff --git a/src/V3Ast.h b/src/V3Ast.h index f8ebc2afb..72cd16bab 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1312,8 +1312,8 @@ public: int widthMin() const; int widthMinV() const { return v3Global.widthMinUsage()==VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width(); } int widthWords() const { return VL_WORDS_I(width()); } - bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); } - bool isWide() const { return (width()>VL_QUADSIZE); } + bool isQuad() const { return (width() > VL_IDATASIZE && width() <= VL_QUADSIZE); } + bool isWide() const { return (width() > VL_QUADSIZE); } bool isDouble() const; bool isSigned() const; bool isString() const; diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 562b4baca..648fc09ff 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -104,14 +104,14 @@ int AstBasicDType::widthTotalBytes() const { if (width()<=8) return 1; else if (width()<=16) return 2; else if (isQuad()) return 8; - else return widthWords()*(VL_WORDSIZE/8); + else return widthWords() * (VL_EDATASIZE / 8); } int AstNodeClassDType::widthTotalBytes() const { if (width()<=8) return 1; else if (width()<=16) return 2; else if (isQuad()) return 8; - else return widthWords()*(VL_WORDSIZE/8); + else return widthWords() * (VL_EDATASIZE / 8); } int AstNodeClassDType::widthAlignBytes() const { @@ -319,7 +319,7 @@ AstVar::VlArgTypeRecursed AstVar::vlArgTypeRecurse(bool forFunc, const AstNodeDT otype += "CData"+bitvec; } else if (dtypep->widthMin() <= 16) { otype += "SData"+bitvec; - } else if (dtypep->widthMin() <= VL_WORDSIZE) { + } else if (dtypep->widthMin() <= VL_IDATASIZE) { otype += "IData"+bitvec; } else if (dtypep->isQuad()) { otype += "QData"+bitvec; @@ -367,7 +367,7 @@ string AstVar::vlEnumType() const { arg += "VLVT_UINT8"; } else if (widthMin() <= 16) { arg += "VLVT_UINT16"; - } else if (widthMin() <= VL_WORDSIZE) { + } else if (widthMin() <= VL_IDATASIZE) { arg += "VLVT_UINT32"; } else if (isQuad()) { arg += "VLVT_UINT64"; @@ -429,12 +429,12 @@ string AstVar::cPubArgType(bool named, bool forReturn) const { if (isWide() && isReadOnly()) arg += "const "; if (widthMin() == 1) { arg += "bool"; - } else if (widthMin() <= VL_WORDSIZE) { + } else if (widthMin() <= VL_IDATASIZE) { arg += "uint32_t"; - } else if (isWide()) { - arg += "uint32_t"; // []'s added later - } else { + } else if (widthMin() <= VL_QUADSIZE) { arg += "vluint64_t"; + } else { + arg += "uint32_t"; // []'s added later } if (isWide()) { if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead"); @@ -501,7 +501,7 @@ string AstVar::scType() const { return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >> } else if (widthMin() == 1) { return "bool"; - } else if (widthMin() <= VL_WORDSIZE) { + } else if (widthMin() <= VL_IDATASIZE) { if (widthMin() <= 8 && v3Global.opt.pinsUint8()) { return "uint8_t"; } else if (widthMin() <= 16 && v3Global.opt.pinsUint8()) { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index bd39323ea..2cb8edf6c 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -109,6 +109,13 @@ public: m_num.width(32, 32); dtypeSetLogicUnsized(32, m_num.widthMin(), AstNumeric::SIGNED); } + class SizedEData {}; // for creator type-overload selection + AstConst(FileLine* fl, SizedEData, vluint64_t num) + : AstNodeMath(fl) + , m_num(this, VL_EDATASIZE, 0) { + m_num.setQuad(num); + dtypeSetLogicSized(VL_EDATASIZE, AstNumeric::UNSIGNED); + } class RealDouble {}; // for creator type-overload selection AstConst(FileLine* fl, RealDouble, double num) : AstNodeMath(fl) @@ -1119,8 +1126,8 @@ class AstWordSel : public AstNodeSel { // Select a single word from a multi-word wide value public: AstWordSel(FileLine* fl, AstNode* fromp, AstNode* bitp) - :AstNodeSel(fl, fromp, bitp) { - dtypeSetUInt32(); // Always used on IData arrays so returns word entities + : AstNodeSel(fl, fromp, bitp) { + dtypeSetUInt32(); // Always used on WData arrays so returns edata size } ASTNODE_NODE_FUNCS(WordSel) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstWordSel(this->fileline(), lhsp, rhsp); } @@ -3893,7 +3900,8 @@ public: dtypeFrom(valuep); m_code = 0; m_codeInc = ((arrayRange.ranged() ? arrayRange.elements() : 1) - * valuep->dtypep()->widthWords()); + * valuep->dtypep()->widthWords() + * (VL_EDATASIZE / sizeof(uint32_t))); // A code is always 32-bits m_varType = varp->varType(); m_declKwd = varp->declKwd(); m_declDirection = varp->declDirection(); diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index 170b0e3df..7409f3b34 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -80,9 +80,9 @@ private: } int castSize(AstNode* nodep) { if (nodep->isQuad()) return VL_QUADSIZE; - else if (nodep->width()<=8) return 8; - else if (nodep->width()<=16) return 16; - else return VL_WORDSIZE; + else if (nodep->width() <= 8) return 8; + else if (nodep->width() <= 16) return 16; + else return VL_IDATASIZE; } void insureCast(AstNode* nodep) { if (castSize(nodep->backp()) != castSize(nodep) @@ -97,7 +97,7 @@ private: // less than has nondeterministic signedness. if (nodep->isQuad() && !nodep->lhsp()->isQuad() && !VN_IS(nodep->lhsp(), CCast)) { - insertCast(nodep->lhsp(), VL_WORDSIZE); + insertCast(nodep->lhsp(), VL_IDATASIZE); } } diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index e1eb1b9f8..3ea3c435d 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -62,9 +62,9 @@ private: // Width resetting int cppWidth(AstNode* nodep) { - if (nodep->width()<=VL_WORDSIZE) return VL_WORDSIZE; - else if (nodep->width()<=VL_QUADSIZE) return VL_QUADSIZE; - else return nodep->widthWords()*VL_WORDSIZE; + if (nodep->width() <= VL_IDATASIZE) return VL_IDATASIZE; + else if (nodep->width() <= VL_QUADSIZE) return VL_QUADSIZE; + else return nodep->widthWords() * VL_EDATASIZE; } void setCppWidth(AstNode* nodep) { nodep->user2(true); // Don't resize it again @@ -113,8 +113,10 @@ private: } void setClean(AstNode* nodep, bool isClean) { computeCppWidth(nodep); // Just to be sure it's in widthMin - bool wholeUint = ((nodep->widthMin() % VL_WORDSIZE) == 0); // 32,64,... - setCleanState(nodep, ((isClean||wholeUint) ? CS_CLEAN:CS_DIRTY)); + bool wholeUint = (nodep->widthMin() == VL_IDATASIZE + || nodep->widthMin() == VL_QUADSIZE + || (nodep->widthMin() % VL_EDATASIZE) == 0); + setCleanState(nodep, ((isClean || wholeUint) ? CS_CLEAN : CS_DIRTY)); } // Operate on nodes diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 0cc2c266f..967ffd9e9 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -965,15 +965,15 @@ private: V3Number ones (nodep, nodep->width()); ones.setMask(nodep->width()); if (shift1<0) { - mask1.opShiftR(ones, V3Number(nodep, VL_WORDSIZE, -shift1)); + mask1.opShiftR(ones, V3Number(nodep, VL_IDATASIZE, -shift1)); } else { - mask1.opShiftL(ones, V3Number(nodep, VL_WORDSIZE, shift1)); + mask1.opShiftL(ones, V3Number(nodep, VL_IDATASIZE, shift1)); } V3Number mask (nodep, nodep->width()); if (shift2<0) { - mask.opShiftR(mask1, V3Number(nodep, VL_WORDSIZE, -shift2)); + mask.opShiftR(mask1, V3Number(nodep, VL_IDATASIZE, -shift2)); } else { - mask.opShiftL(mask1, V3Number(nodep, VL_WORDSIZE, shift2)); + mask.opShiftL(mask1, V3Number(nodep, VL_IDATASIZE, shift2)); } if (newshift<0) { newp = new AstShiftR(nodep->fileline(), ap, @@ -1016,8 +1016,6 @@ private: if (( con1p->toSInt() != con2p->toSInt() + sel2p->width()) &&(con2p->toSInt() != con1p->toSInt() + sel1p->width())) return false; bool lsbFirstAssign = (con1p->toUInt() < con2p->toUInt()); - // If the user already has nice 32-bit divisions, keep them to aid later subdivision - //if (VL_BITBIT_I(con1p->toUInt()) == 0) return false; UINFO(4,"replaceAssignMultiSel "<dumpTree(cout, "comb1: "); diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index a2b6a8383..ed5e8dc44 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -691,10 +691,10 @@ public: } virtual void visit(AstCCast* nodep) { // Extending a value of the same word width is just a NOP. - if (nodep->size()>VL_WORDSIZE) { - puts("(QData)("); - } else { + if (nodep->size() <= VL_IDATASIZE) { puts("(IData)("); + } else { + puts("(QData)("); } iterateAndNextNull(nodep->lhsp()); puts(")"); @@ -788,11 +788,11 @@ public: } else if (nodep->isWide()) { int upWidth = nodep->num().widthMin(); int chunks = 0; - if (upWidth > EMITC_NUM_CONSTW*VL_WORDSIZE) { + if (upWidth > EMITC_NUM_CONSTW * VL_EDATASIZE) { // Output e.g. 8 words in groups of e.g. 8 - chunks = (upWidth-1) / (EMITC_NUM_CONSTW*VL_WORDSIZE); - upWidth %= (EMITC_NUM_CONSTW*VL_WORDSIZE); - if (upWidth == 0) upWidth = (EMITC_NUM_CONSTW*VL_WORDSIZE); + chunks = (upWidth-1) / (EMITC_NUM_CONSTW * VL_EDATASIZE); + upWidth %= (EMITC_NUM_CONSTW * VL_EDATASIZE); + if (upWidth == 0) upWidth = (EMITC_NUM_CONSTW * VL_EDATASIZE); } { // Upper e.g. 8 words if (chunks) { @@ -801,7 +801,7 @@ public: puts("X("); puts(cvtToStr(nodep->widthMin())); puts(","); - puts(cvtToStr(chunks*EMITC_NUM_CONSTW*VL_WORDSIZE)); + puts(cvtToStr(chunks * EMITC_NUM_CONSTW * VL_EDATASIZE)); } else { putbs("VL_CONST_W_"); puts(cvtToStr(VL_WORDS_I(upWidth))); @@ -820,8 +820,8 @@ public: for (int word=VL_WORDS_I(upWidth)-1; word>=0; word--) { // Only 32 bits - llx + long long here just to appease CPP format warning ofp()->printf(",0x%08" VL_PRI64 "x", - static_cast(nodep->num().dataWord - (word+chunks*EMITC_NUM_CONSTW))); + static_cast(nodep->num().edataWord + (word+chunks * EMITC_NUM_CONSTW))); } puts(")"); } @@ -830,7 +830,7 @@ public: putbs("VL_CONSTLO_W_"); puts(cvtToStr(EMITC_NUM_CONSTW)); puts("X("); - puts(cvtToStr(chunks*EMITC_NUM_CONSTW*VL_WORDSIZE)); + puts(cvtToStr(chunks * EMITC_NUM_CONSTW * VL_EDATASIZE)); puts(","); if (!assigntop) { puts(assignString); @@ -843,8 +843,8 @@ public: for (int word=EMITC_NUM_CONSTW-1; word>=0; word--) { // Only 32 bits - llx + long long here just to appease CPP format warning ofp()->printf(",0x%08" VL_PRI64 "x", - static_cast(nodep->num().dataWord - (word+chunks*EMITC_NUM_CONSTW))); + static_cast(nodep->num().edataWord + (word+chunks * EMITC_NUM_CONSTW))); } puts(")"); } diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 4506fe42f..8f0a456bc 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -55,15 +55,14 @@ private: VL_DEBUG_FUNC; // Declare debug() int longOrQuadWidth(AstNode* nodep) { - // Return 32 or 64... - return (nodep->width()+(VL_WORDSIZE-1)) & ~(VL_WORDSIZE-1); + return (nodep->width() + (VL_EDATASIZE - 1)) & ~(VL_EDATASIZE - 1); } V3Number notWideMask(AstNode* nodep) { - return V3Number(nodep, VL_WORDSIZE, ~VL_MASK_I(nodep->widthMin())); + return V3Number(nodep, VL_EDATASIZE, ~VL_MASK_E(nodep->widthMin())); } V3Number wordMask(AstNode* nodep) { if (nodep->isWide()) { - return V3Number(nodep, VL_WORDSIZE, VL_MASK_I(nodep->widthMin())); + return V3Number(nodep, VL_EDATASIZE, VL_MASK_E(nodep->widthMin())); } else { V3Number mask (nodep, longOrQuadWidth(nodep)); mask.setMask(nodep->widthMin()); @@ -118,13 +117,13 @@ private: return new AstWordSel(nodep->fileline(), nodep->cloneTree(true), new AstConst(nodep->fileline(), word)); - } else if (nodep->isQuad() && word==0) { + } else if (nodep->isQuad() && word == 0) { AstNode* quadfromp = nodep->cloneTree(true); quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(), AstNumeric::UNSIGNED); return new AstCCast(nodep->fileline(), quadfromp, - VL_WORDSIZE); + VL_EDATASIZE); } else if (nodep->isQuad() && word==1) { AstNode* quadfromp = nodep->cloneTree(true); quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(), @@ -132,10 +131,10 @@ private: return new AstCCast(nodep->fileline(), new AstShiftR(nodep->fileline(), quadfromp, - new AstConst(nodep->fileline(), VL_WORDSIZE), - VL_WORDSIZE), - VL_WORDSIZE); - } else if (!nodep->isWide() && !nodep->isQuad() && word==0) { + new AstConst(nodep->fileline(), VL_EDATASIZE), + VL_EDATASIZE), + VL_EDATASIZE); + } else if (!nodep->isWide() && !nodep->isQuad() && word == 0) { return nodep->cloneTree(true); } else { // Out of bounds return new AstConst(nodep->fileline(), 0); @@ -148,25 +147,25 @@ private: AstNode* newp; // Negative word numbers requested for lhs when it's "before" what we want. // We get a 0 then. - int othword = word - shift/VL_WORDSIZE; + int othword = word - shift / VL_EDATASIZE; AstNode* llowp = newAstWordSelClone(lhsp, othword); - if (int loffset = VL_BITBIT_I(shift)) { + if (int loffset = VL_BITBIT_E(shift)) { AstNode* lhip = newAstWordSelClone(lhsp, othword-1); - int nbitsonright = VL_WORDSIZE-loffset; // bits that end up in lword + int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword newp = new AstOr (fl, new AstAnd(fl, - new AstConst(fl, VL_MASK_I(loffset)), + new AstConst(fl, AstConst::SizedEData(), VL_MASK_E(loffset)), new AstShiftR(fl, lhip, new AstConst(fl, nbitsonright), - VL_WORDSIZE)), + VL_EDATASIZE)), new AstAnd(fl, - new AstConst(fl, ~VL_MASK_I(loffset)), + new AstConst(fl, AstConst::SizedEData(), ~VL_MASK_E(loffset)), new AstShiftL(fl, llowp, new AstConst(fl, loffset), - VL_WORDSIZE))); + VL_EDATASIZE))); } else { newp = llowp; } @@ -177,12 +176,12 @@ private: // Return equation to get the VL_BITWORD of a constant or non-constant if (VN_IS(lsbp, Const)) { return new AstConst(lsbp->fileline(), - wordAdder + VL_BITWORD_I(VN_CAST(lsbp, Const)->toUInt())); + wordAdder + VL_BITWORD_E(VN_CAST(lsbp, Const)->toUInt())); } else { AstNode* shiftp = new AstShiftR(lsbp->fileline(), lsbp->cloneTree(true), - new AstConst(lsbp->fileline(), VL_WORDSIZE_LOG2), - VL_WORDSIZE); + new AstConst(lsbp->fileline(), VL_EDATASIZE_LOG2), + VL_EDATASIZE); if (wordAdder != 0) { shiftp = new AstAdd(lsbp->fileline(), // This is indexing a arraysel, so a 32 bit constant is fine @@ -208,10 +207,10 @@ private: // Return equation to get the VL_BITBIT of a constant or non-constant if (VN_IS(lsbp, Const)) { return new AstConst(lsbp->fileline(), - VL_BITBIT_I(VN_CAST(lsbp, Const)->toUInt())); + VL_BITBIT_E(VN_CAST(lsbp, Const)->toUInt())); } else { return new AstAnd(lsbp->fileline(), - new AstConst(lsbp->fileline(), VL_WORDSIZE-1), + new AstConst(lsbp->fileline(), VL_EDATASIZE - 1), dropCondBound(lsbp)->cloneTree(true)); } } @@ -226,8 +225,8 @@ private: } for (int w=0; wwidthWords(); w++) { addWordAssign(nodep, w, new AstConst(nodep->fileline(), - AstConst::WidthedValue(), - VL_WORDSIZE, rhsp->num().dataWord(w))); + AstConst::SizedEData(), + rhsp->num().edataWord(w))); } return true; } @@ -339,7 +338,7 @@ private: addWordAssign(nodep, w, newAstWordSelClone(rhsp->lhsp(), w)); } for (; wwidthWords(); w++) { - addWordAssign(nodep, w, new AstConst(rhsp->fileline(), 0)); + addWordAssign(nodep, w, new AstConst(rhsp->fileline(), AstConst::SizedEData(), 0)); } return true; } @@ -387,7 +386,7 @@ private: // nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb) AstNode* midshiftp = new AstSub(nodep->lsbp()->fileline(), new AstConst(nodep->lsbp()->fileline(), - VL_WORDSIZE), + VL_EDATASIZE), newSelBitBit(nodep->lsbp())); if (nodep->isQuad()) { midshiftp = @@ -395,7 +394,7 @@ private: new AstEq(nodep->fileline(), new AstConst(nodep->fileline(), 0), newSelBitBit(nodep->lsbp())), - new AstConst(nodep->lsbp()->fileline(), VL_WORDSIZE), + new AstConst(nodep->lsbp()->fileline(), VL_EDATASIZE), midshiftp); } AstNode* midmayp = new AstShiftL(nodep->fileline(), @@ -415,7 +414,7 @@ private: } // If > 32 bits, we might be crossing the second word boundary AstNode* hip = NULL; - if (nodep->widthConst() > VL_WORDSIZE) { + if (nodep->widthConst() > VL_EDATASIZE) { AstNode* hiwordp = // SEL(from,[2+wordnum]) new AstWordSel(nodep->fromp()->fileline(), nodep->fromp()->cloneTree(true), @@ -468,11 +467,11 @@ private: bool expandWide(AstNodeAssign* nodep, AstSel* rhsp) { UASSERT_OBJ(nodep->widthMin() == rhsp->widthConst(), nodep, "Width mismatch"); - if (VN_IS(rhsp->lsbp(), Const) && VL_BITBIT_I(rhsp->lsbConst())==0) { + if (VN_IS(rhsp->lsbp(), Const) && VL_BITBIT_E(rhsp->lsbConst()) == 0) { int lsb = rhsp->lsbConst(); UINFO(8," Wordize ASSIGN(SEL,align) "<widthWords(); w++) { - addWordAssign(nodep, w, newAstWordSelClone(rhsp->fromp(), w + VL_BITWORD_I(lsb))); + addWordAssign(nodep, w, newAstWordSelClone(rhsp->fromp(), w + VL_BITWORD_E(lsb))); } return true; } else { @@ -485,20 +484,21 @@ private: AstNode* lowp = new AstShiftR(rhsp->fileline(), lowwordp, newSelBitBit(rhsp->lsbp()), - VL_WORDSIZE); + VL_EDATASIZE); // Upper bits - V3Number zero (nodep, VL_WORDSIZE, 0); + V3Number zero (nodep, VL_EDATASIZE, 0); AstNode* midwordp = // SEL(from,[1+wordnum]) new AstWordSel(rhsp->fromp()->fileline(), rhsp->fromp()->cloneTree(true), newSelBitWord(rhsp->lsbp(), w+1)); AstNode* midshiftp = new AstSub(rhsp->lsbp()->fileline(), - new AstConst(rhsp->lsbp()->fileline(), VL_WORDSIZE), + new AstConst(rhsp->lsbp()->fileline(), + VL_EDATASIZE), newSelBitBit(rhsp->lsbp())); AstNode* midmayp = new AstShiftL(rhsp->fileline(), midwordp, midshiftp, - VL_WORDSIZE); + VL_EDATASIZE); AstNode* midp = new AstCond(rhsp->fileline(), new AstEq(rhsp->fileline(), new AstConst(rhsp->fileline(), 0), @@ -534,14 +534,15 @@ private: if (destwide) { UINFO(8," ASSIGNSEL(const,wide) "<widthWords(); w++) { - if (w>=VL_BITWORD_I(lsb) && w<=VL_BITWORD_I(msb)) { + if (w >= VL_BITWORD_E(lsb) && w <= VL_BITWORD_E(msb)) { // else we would just be setting it to the same exact value AstNode* oldvalp = newAstWordSelClone(destp, w); fixCloneLvalue(oldvalp); if (!ones) { oldvalp = new AstAnd(lhsp->fileline(), new AstConst(lhsp->fileline(), - maskold.dataWord(w)), + AstConst::SizedEData(), + maskold.edataWord(w)), oldvalp); } addWordAssign(nodep, w, @@ -598,18 +599,18 @@ private: // That's ok as we'd just AND with a larger value, // but oldval would clip the upper bits to sanity newSelBitBit(lhsp->lsbp()), - VL_WORDSIZE)), + VL_EDATASIZE)), oldvalp); } // Restrict the shift amount to 0-31, see bug804. AstNode* shiftp = new AstAnd(nodep->fileline(), lhsp->lsbp()->cloneTree(true), - new AstConst(nodep->fileline(), VL_WORDSIZE-1)); + new AstConst(nodep->fileline(), VL_EDATASIZE - 1)); AstNode* newp = new AstOr(lhsp->fileline(), oldvalp, new AstShiftL(lhsp->fileline(), rhsp, shiftp, - VL_WORDSIZE)); + VL_EDATASIZE)); newp = new AstAssign(nodep->fileline(), new AstWordSel(nodep->fileline(), destp, @@ -762,7 +763,7 @@ private: AstNode* newp; if (lhswidth==1) { newp = new AstNegate(nodep->fileline(), lhsp->cloneTree(true)); - newp->dtypeSetLogicSized(VL_WORDSIZE, + newp->dtypeSetLogicSized(VL_EDATASIZE, AstNumeric::UNSIGNED); // Replicate always unsigned } else { newp = newAstWordSelClone(lhsp, w); @@ -808,10 +809,12 @@ private: } if (VN_IS(nodep, Neq)) { newp = new AstNeq(nodep->fileline(), - new AstConst(nodep->fileline(), 0), newp); + new AstConst(nodep->fileline(), AstConst::SizedEData(), 0), + newp); } else { newp = new AstEq(nodep->fileline(), - new AstConst(nodep->fileline(), 0), newp); + new AstConst(nodep->fileline(), AstConst::SizedEData(), 0), + newp); } replaceWithDelete(nodep, newp); VL_DANGLING(nodep); } @@ -831,7 +834,8 @@ private: newp = (newp==NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp)); } newp = new AstNeq(nodep->fileline(), - new AstConst(nodep->fileline(), 0), newp); + new AstConst(nodep->fileline(), AstConst::SizedEData(), 0), + newp); replaceWithDelete(nodep, newp); VL_DANGLING(nodep); } else { UINFO(8," REDOR->EQ "<fileline(), newp, eqp)); } newp = new AstEq(nodep->fileline(), - new AstConst(nodep->fileline(), ~0), newp); + new AstConst(nodep->fileline(), AstConst::SizedEData(), + ~VL_MASK_E(0)), newp); replaceWithDelete(nodep, newp); VL_DANGLING(nodep); } else { UINFO(8," REDAND->EQ "<> ((byte * 8) % VL_EDATASIZE)) & 0xff; } bool V3Number::isEqZero() const { @@ -1656,8 +1660,8 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool return *this; } - int uw = VL_WORDS_I(umsbp1); // aka "m" in the algorithm - int vw = VL_WORDS_I(vmsbp1); // aka "n" in the algorithm + int uw = (umsbp1 + 31) / 32; // aka "m" in the algorithm + int vw = (vmsbp1 + 31) / 32; // aka "n" in the algorithm if (vw == 1) { // Single divisor word breaks rest of algorithm vluint64_t k = 0; @@ -1684,7 +1688,7 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool // Algorithm requires divisor MSB to be set // Copy and shift to normalize divisor so MSB of vn[vw-1] is set - int s = 31-VL_BITBIT_I(vmsbp1-1); // shift amount (0...31) + int s = 31 - ((vmsbp1-1) & 31); // shift amount (0...31) uint32_t shift_mask = s ? 0xffffffff : 0; // otherwise >> 32 won't mask the value for (int i = vw-1; i>0; i--) { vn[i] = (rhs.m_value[i] << s) | (shift_mask & (rhs.m_value[i-1] >> (32-s))); diff --git a/src/V3Number.h b/src/V3Number.h index 6a8af81d6..f40f8616d 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -243,8 +243,8 @@ public: string toDecimalU() const; // return ASCII unsigned decimal number double toDouble() const; uint32_t toHash() const; - uint32_t dataWord(int word) const; - uint8_t dataByte(int byte) const { return (dataWord(byte/4) >> (8*(byte&3))) & 0xff; } + uint32_t edataWord(int eword) const; + uint8_t dataByte(int byte) const; uint32_t countOnes() const; uint32_t mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0. diff --git a/src/V3Task.cpp b/src/V3Task.cpp index fbeb93803..049c0c613 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -630,10 +630,14 @@ private: return new AstCStmt(portp->fileline(), linesp); } // Use a AstCMath, as we want V3Clean to mask off bits that don't make sense. - int cwidth = VL_WORDSIZE; - if (portp->basicp()) cwidth = portp->basicp()->keyword().width(); - if (portp->basicp() - && portp->basicp()->keyword().isBitLogic()) cwidth = VL_WORDSIZE*portp->widthWords(); + int cwidth = VL_IDATASIZE; + if (portp->basicp()) { + if (portp->basicp()->keyword().isBitLogic()) { + cwidth = VL_EDATASIZE * portp->widthWords(); + } else { + cwidth = portp->basicp()->keyword().width(); + } + } AstNode* newp = new AstAssign(portp->fileline(), new AstVarRef(portp->fileline(), portvscp, true), new AstSel(portp->fileline(), diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 94aa4cc6f..6197f8594 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -341,8 +341,8 @@ private: AstVarType::MODULETEMP, "__Vm_traceActivity", newArrDtp); } else { - // For tighter code; round to next 32 bit point. - int activityBits = VL_WORDS_I(m_activityNumber)*VL_WORDSIZE; + // For tighter code; round to next word point. + int activityBits = VL_WORDS_I(m_activityNumber) * VL_EDATASIZE; newvarp = new AstVar(m_chgFuncp->fileline(), AstVarType::MODULETEMP, "__Vm_traceActivity", VFlagBitPacked(), activityBits); } diff --git a/test_regress/t/t_math_repl.v b/test_regress/t/t_math_repl.v index b93d64729..6995ef03c 100644 --- a/test_regress/t/t_math_repl.v +++ b/test_regress/t/t_math_repl.v @@ -56,7 +56,7 @@ module t (/*AUTOARG*/ if (cyc!=0) begin cyc <= cyc + 1; `ifdef TEST_VERBOSE - $write("cyc=%0d d=%x %x %x %x %x %x\n", cyc, b, rf, rf2, dualasr, sl_mask, sr_mask); + $write("cyc=%0d d=%x %x %x %x %x %x %x\n", cyc, b, rf, rf2, dualasr, sl_mask, sr_mask, widerep); `endif if (cyc==1) begin biu <= 64'h12451282_abadee00;