Framework for WDatas being vectors of 64-bit EDatas, but not supporting this at this time.

This commit is contained in:
Wilson Snyder 2019-12-08 21:36:38 -05:00
parent cda5c53cf9
commit 700f2072c0
21 changed files with 449 additions and 397 deletions

View File

@ -311,7 +311,7 @@ WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE {
if (i<(VL_WORDS_I(obits)-1)) { if (i<(VL_WORDS_I(obits)-1)) {
outwp[i] = vl_rand64(); outwp[i] = vl_rand64();
} else { } else {
outwp[i] = vl_rand64() & VL_MASK_I(obits); outwp[i] = vl_rand64() & VL_MASK_E(obits);
} }
} }
return outwp; return outwp;
@ -323,7 +323,7 @@ IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
if (Verilated::randReset()!=1) { // if 2, randomize if (Verilated::randReset()!=1) { // if 2, randomize
data = VL_RANDOM_I(obits); data = VL_RANDOM_I(obits);
} }
if (obits<32) data &= VL_MASK_I(obits); data &= VL_MASK_I(obits);
return data; return data;
} }
QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE { 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 if (Verilated::randReset()!=1) { // if 2, randomize
data = VL_RANDOM_Q(obits); data = VL_RANDOM_Q(obits);
} }
if (obits<64) data &= VL_MASK_Q(obits); data &= VL_MASK_Q(obits);
return data; return data;
} }
WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE { 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)) { if (i<(VL_WORDS_I(obits)-1)) {
outwp[i] = VL_RAND_RESET_I(32); outwp[i] = VL_RAND_RESET_I(32);
} else { } 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; 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 { void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) VL_MT_SAFE {
VL_PRINTF_MT(" Data: w%d: ", lbits); VL_PRINTF_MT(" Data: w%d: ", lbits);
for (int i=VL_WORDS_I(lbits)-1; i>=0; --i) { VL_PRINTF_MT("%08x ", iwp[i]); } for (int i = VL_WORDS_I(lbits) - 1; i >= 0; --i) {
VL_PRINTF_MT("%08x ", iwp[i]);
}
VL_PRINTF_MT("\n"); VL_PRINTF_MT("\n");
} }
@ -499,7 +501,7 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits,
} }
WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, QData rhs) VL_MT_SAFE { 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); return VL_POW_WWW(obits, lbits, rbits, owp, lwp, rhsw);
} }
QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE { QData VL_POW_QQW(int, int, int rbits, QData lhs, 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)) { if (rsign && VL_SIGN_W(rbits, rwp)) {
int words = VL_WORDS_I(obits); int words = VL_WORDS_I(obits);
VL_ZERO_W(obits, owp); 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) { for (int i=1; i < (words-1); ++i) {
lor |= lwp[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 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 (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 if (rwp[0] & 1) { return VL_ALLONES_W(obits, owp); } // -1^odd=-1
else { owp[0] = 1; return owp; } // -1^even=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 VL_POWSS_WWQ(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, QData rhs, WDataOutP owp, WDataInP lwp, QData rhs,
bool lsign, bool rsign) VL_MT_SAFE { 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); return VL_POWSS_WWW(obits, lbits, rbits, owp, lwp, rhsw, lsign, rsign);
} }
QData VL_POWSS_QQW(int obits, int, int rbits, 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) { for (int nibble_bit = 0; nibble_bit < maxdecwidth; nibble_bit+=4) {
if ((VL_BITRSHIFT_W(bcd, nibble_bit) & 0xf) >= 5) { if ((VL_BITRSHIFT_W(bcd, nibble_bit) & 0xf) >= 5) {
VL_ZERO_RESET_W(maxdecwidth, tmp2); 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_ASSIGN_W(maxdecwidth, tmp, bcd);
VL_ADD_W(VL_WORDS_I(maxdecwidth), bcd, tmp, tmp2); 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 // 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 { 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 // 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 // Deal with all read-and-print somethings
const int lbits = va_arg(ap, int); const int lbits = va_arg(ap, int);
QData ld = 0; QData ld = 0;
WData qlwp[2]; WData qlwp[VL_WQ_WORDS_E];
WDataInP lwp; WDataInP lwp;
if (lbits <= VL_QUADSIZE) { if (lbits <= VL_QUADSIZE) {
ld = _VL_VA_ARG_Q(ap, lbits); 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<vlsint64_t>(VL_EXTENDS_QQ(lbits, lbits, ld))); static_cast<vlsint64_t>(VL_EXTENDS_QQ(lbits, lbits, ld)));
append = tmp; append = tmp;
} else { } 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]; WData neg[VL_VALUE_STRING_MAX_WIDTH/4+2];
VL_NEGATE_W(VL_WORDS_I(lbits), neg, lwp); VL_NEGATE_W(VL_WORDS_I(lbits), neg, lwp);
append = std::string("-") + VL_DECIMAL_NW(lbits, neg); 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 // Deal with all read-and-scan somethings
// Note LSBs are preserved if there's an overflow // Note LSBs are preserved if there's an overflow
const int obits = va_arg(ap, int); 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; WDataOutP owp = qowp;
if (obits > VL_QUADSIZE) { if (obits > VL_QUADSIZE) {
owp = va_arg(ap, WDataOutP); 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]; CData* p = va_arg(ap, CData*); *p = owp[0];
} else if (obits <= VL_SHORTSIZE) { } else if (obits <= VL_SHORTSIZE) {
SData* p = va_arg(ap, SData*); *p = owp[0]; 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]; IData* p = va_arg(ap, IData*); *p = owp[0];
} else if (obits <= VL_QUADSIZE) { } else if (obits <= VL_QUADSIZE) {
QData* p = va_arg(ap, QData*); *p = VL_SET_QW(owp); 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 // any read data. This means we can't know in what location the first
// character will finally live, so we need to copy. Yuk. // character will finally live, so we need to copy. Yuk.
IData bytes = VL_BYTES_I(obits); 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 // 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 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 { IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE {
// While threadsafe, each thread can only access different file handles // While threadsafe, each thread can only access different file handles
char modez[5]; 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); return VL_FOPEN_S(filename.c_str(), modez);
} }
IData VL_FOPEN_QI(QData filename, IData mode) VL_MT_SAFE { IData VL_FOPEN_QI(QData filename, IData mode) VL_MT_SAFE {
// While threadsafe, each thread can only access different file handles // While threadsafe, each thread can only access different file handles
WData fnw[2]; VL_SET_WQ(fnw, filename); WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, filename);
return VL_FOPEN_WI(2, fnw, mode); return VL_FOPEN_WI(VL_WQ_WORDS_E, fnw, mode);
} }
IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) VL_MT_SAFE { IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) VL_MT_SAFE {
// While threadsafe, each thread can only access different file handles // While threadsafe, each thread can only access different file handles
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep); _VL_VINT_TO_STRING(fnwords * VL_EDATASIZE, filenamez, filenamep);
EData modee = mode;
char modez[5]; 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); return VL_FOPEN_S(filenamez, modez);
} }
IData VL_FOPEN_S(const char* filenamep, const char* modep) VL_MT_SAFE { 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 { 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_list ap;
va_start(ap, formatp); va_start(ap, formatp);
@ -1286,7 +1290,7 @@ IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) VL_MT_SAFE {
return got; return got;
} }
IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) VL_MT_SAFE { 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_list ap;
va_start(ap, formatp); 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, void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int,
QData filename, const void* memp, IData start, QData filename, const void* memp, IData start,
IData end) VL_MT_SAFE { IData end) VL_MT_SAFE {
WData fnw[2]; VL_SET_WQ(fnw, filename); WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, filename);
return VL_WRITEMEM_W(hex, width, depth, array_lsb,2, fnw, memp, start, end); 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, void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP filenamep, const void* memp, IData start, WDataInP filenamep, const void* memp, IData start,
IData end) VL_MT_SAFE { IData end) VL_MT_SAFE {
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep); _VL_VINT_TO_STRING(fnwords * VL_EDATASIZE, filenamez, filenamep);
std::string filenames(filenamez); std::string filenames(filenamez);
return VL_WRITEMEM_N(hex, width, depth, array_lsb, filenames, memp, start, end); return VL_WRITEMEM_N(hex, width, depth, array_lsb, filenames, memp, start, end);
} }
@ -1425,21 +1429,20 @@ void VL_WRITEMEM_N(
} else { } else {
WDataInP memDatap = reinterpret_cast<WDataInP>(memp); WDataInP memDatap = reinterpret_cast<WDataInP>(memp);
WDataInP datap = &memDatap[row_offset * VL_WORDS_I(width)]; 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 // from MSB to LSB. Mask off the MSB word which could
// contain junk above the top of valid data. // contain junk above the top of valid data.
int word_idx = ((width - 1) / VL_WORDSIZE); int word_idx = ((width - 1) / VL_EDATASIZE);
bool first = true; bool first = true;
while (word_idx >= 0) { while (word_idx >= 0) {
IData data = datap[word_idx]; EData data = datap[word_idx];
if (first) { if (first) {
data &= VL_MASK_I(width); data &= VL_MASK_E(width);
int top_word_nbits = ((width - 1) & 0x1f) + 1; int top_word_nbits = ((width - 1) & (VL_EDATASIZE - 1)) + 1;
fprintf(fp, memhFormat(top_word_nbits), data); fprintf(fp, memhFormat(top_word_nbits), data);
} else { } else {
fprintf(fp, "%08x", data); fprintf(fp, "%08x", data);
} }
word_idx--; word_idx--;
first = false; first = false;
} }
@ -1477,7 +1480,7 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size,
SData* datap = &(reinterpret_cast<SData*>(memp))[entry]; SData* datap = &(reinterpret_cast<SData*>(memp))[entry];
if (shift == start_shift) { *datap = 0; } if (shift == start_shift) { *datap = 0; }
*datap |= (c << shift) & VL_MASK_I(width); *datap |= (c << shift) & VL_MASK_I(width);
} else if (width <= VL_WORDSIZE) { } else if (width <= VL_IDATASIZE) {
IData* datap = &(reinterpret_cast<IData*>(memp))[entry]; IData* datap = &(reinterpret_cast<IData*>(memp))[entry];
if (shift == start_shift) { *datap = 0; } if (shift == start_shift) { *datap = 0; }
*datap |= (c << shift) & VL_MASK_I(width); *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; } if (shift == start_shift) { *datap = 0; }
*datap |= ((static_cast<QData>(c) << static_cast<QData>(shift)) *datap |= ((static_cast<QData>(c) << static_cast<QData>(shift))
& VL_MASK_Q(width)); & VL_MASK_Q(width));
} else { } else {
WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp))[ entry*VL_WORDS_I(width) ]; WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp))[entry * VL_WORDS_I(width)];
if (shift == start_shift) { VL_ZERO_RESET_W(width, datap); } 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<EData>(c) << VL_BITBIT_E(shift));
} }
// Prep for next // Prep for next
++read_count; ++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, 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 { QData filename, void* memp, IData start, IData end) VL_MT_SAFE {
WData fnw[2]; VL_SET_WQ(fnw, filename); WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, filename);
return VL_READMEM_W(hex, width, depth, array_lsb, 2, fnw, memp, start, end); 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, 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 { WDataInP filenamep, void* memp, IData start, IData end) VL_MT_SAFE {
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep); _VL_VINT_TO_STRING(fnwords * VL_EDATASIZE, filenamez, filenamep);
std::string filenames(filenamez); std::string filenames(filenamez);
return VL_READMEM_N(hex, width, depth, array_lsb, filenames, memp, start, end); 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<SData*>(memp))[entry]; SData* datap = &(reinterpret_cast<SData*>(memp))[entry];
if (!innum) { *datap = 0; } if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(width); *datap = ((*datap << shift) + value) & VL_MASK_I(width);
} else if (width<=VL_WORDSIZE) { } else if (width <= VL_IDATASIZE) {
IData* datap = &(reinterpret_cast<IData*>(memp))[entry]; IData* datap = &(reinterpret_cast<IData*>(memp))[entry];
if (!innum) { *datap = 0; } if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(width); *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 { IData VL_SYSTEM_IQ(QData lhs) VL_MT_SAFE {
WData lhsw[2]; VL_SET_WQ(lhsw, lhs); WData lhsw[VL_WQ_WORDS_E]; VL_SET_WQ(lhsw, lhs);
return VL_SYSTEM_IW(2, lhsw); return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw);
} }
IData VL_SYSTEM_IW(int lhswords, WDataInP lhsp) VL_MT_SAFE { IData VL_SYSTEM_IW(int lhswords, WDataInP lhsp) VL_MT_SAFE {
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
_VL_VINT_TO_STRING(lhswords*VL_WORDSIZE, filenamez, lhsp); _VL_VINT_TO_STRING(lhswords * VL_EDATASIZE, filenamez, lhsp);
int code = system(filenamez); // Yes, system() is threadsafe int code = system(filenamez); // Yes, system() is threadsafe
return code >> 8; // Want exit status 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 { std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE {
// See also _VL_VINT_TO_STRING // See also _VL_VINT_TO_STRING
char destout[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; char destout[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
int obits = lwords * VL_WORDSIZE; int obits = lwords * VL_EDATASIZE;
int lsb=obits-1; int lsb=obits-1;
bool start=true; bool start=true;
char* destp = destout; char* destp = destout;

View File

@ -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 vluint16_t SData; ///< Verilated pack data, 9-16 bits
typedef vluint32_t IData; ///< Verilated pack data, 17-32 bits typedef vluint32_t IData; ///< Verilated pack data, 17-32 bits
typedef vluint64_t QData; ///< Verilated pack data, 33-64 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 // float F // No typedef needed; Verilator uses float
// double D // No typedef needed; Verilator uses double // double D // No typedef needed; Verilator uses double
// string N // No typedef needed; Verilator uses string // 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. /// 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_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_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_BITISSET_E(data,bit) ((data) & (VL_EUL(1) << VL_BITBIT_E(bit)))
#define VL_BITISSETLIMIT_W(data,width,bit) \ #define VL_BITISSET_W(data,bit) ((data)[VL_BITWORD_E(bit)] & (VL_EUL(1) << VL_BITBIT_E(bit)))
(((bit)<(width)) && (data)[VL_BITWORD_I(bit)] & (VL_UL(1) << VL_BITBIT_I(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 /// 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 /// Create two 32-bit words from quadword
/// WData is always at least 2 words; does not clean upper bits /// WData is always at least 2 words; does not clean upper bits
#define VL_SET_WQ(owp,data) { (owp)[0] = static_cast<IData>(data); \ #define VL_SET_WQ(owp,data) { (owp)[0] = static_cast<IData>(data); \
(owp)[1] = static_cast<IData>((data)>>VL_WORDSIZE); } (owp)[1] = static_cast<IData>((data) >> VL_EDATASIZE); }
#define VL_SET_WI(owp,data) { (owp)[0] = static_cast<IData>(data); (owp)[1] = 0; } #define VL_SET_WI(owp,data) { (owp)[0] = static_cast<IData>(data); (owp)[1] = 0; }
#define VL_SET_QW(lwp) \ #define VL_SET_QW(lwp) \
( (static_cast<QData>((lwp)[0])) \ ( (static_cast<QData>((lwp)[0])) \
| (static_cast<QData>((lwp)[1]) << (static_cast<QData>(VL_WORDSIZE)) )) | (static_cast<QData>((lwp)[1]) << (static_cast<QData>(VL_EDATASIZE)) ))
#define _VL_SET_QII(ld,rd) ((static_cast<QData>(ld)<<VL_ULL(32)) | static_cast<QData>(rd)) #define _VL_SET_QII(ld,rd) ((static_cast<QData>(ld)<<VL_ULL(32)) | static_cast<QData>(rd))
/// Return FILE* from IData /// Return FILE* from IData
@ -718,8 +719,10 @@ static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE {
// (Requires clean input) // (Requires clean input)
#define VL_SIGN_I(nbits,lhs) ((lhs) >> VL_BITBIT_I((nbits) - VL_UL(1))) #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_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_SIGN_E(nbits,lhs) ((lhs) >> VL_BITBIT_E((nbits) - VL_EUL(1)))
#define VL_SIGNONES_I(nbits,lhs) (-(VL_SIGN_I(nbits, lhs))) #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 // Sign bit extended up to MSB, doesn't include unsigned portion
// Optimization bug in GCC 3.3 returns different bitmasks to later states for // 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)) #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 { static inline WDataOutP _VL_CLEAN_INPLACE_W(int obits, WDataOutP owp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); int words = VL_WORDS_I(obits);
owp[words-1] &= VL_MASK_I(obits); owp[words-1] &= VL_MASK_E(obits);
return owp; return owp;
} }
static inline WDataOutP VL_CLEAN_WW(int obits, int, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { static inline WDataOutP VL_CLEAN_WW(int obits, int, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); int words = VL_WORDS_I(obits);
for (int i=0; (i < (words-1)); ++i) owp[i] = lwp[i]; for (int i=0; (i < (words-1)); ++i) owp[i] = lwp[i];
owp[words-1] = lwp[words-1] & VL_MASK_I(obits); owp[words-1] = lwp[words-1] & VL_MASK_E(obits);
return owp; return owp;
} }
static inline WDataOutP VL_ZERO_W(int obits, WDataOutP owp) VL_MT_SAFE { 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 { static inline WDataOutP VL_ALLONES_W(int obits, WDataOutP owp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); int words = VL_WORDS_I(obits);
for (int i=0; (i < (words-1)); ++i) owp[i] = ~VL_UL(0); for (int i = 0; i < (words - 1); ++i) owp[i] = ~VL_EUL(0);
owp[words-1] = VL_MASK_I(obits); owp[words-1] = VL_MASK_E(obits);
return owp; 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 { static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) VL_PURE {
lhsr = ((lhsr & ~(VL_ULL(1)<<VL_BITBIT_Q(bit))) lhsr = ((lhsr & ~(VL_ULL(1)<<VL_BITBIT_Q(bit)))
| (rhs<<VL_BITBIT_Q(bit))); | (static_cast<QData>(rhs) << VL_BITBIT_Q(bit)));
} }
static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) VL_MT_SAFE { static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) VL_MT_SAFE {
IData orig = owp[VL_BITWORD_I(bit)]; EData orig = owp[VL_BITWORD_E(bit)];
owp[VL_BITWORD_I(bit)] = ((orig & ~(VL_UL(1)<<VL_BITBIT_I(bit))) owp[VL_BITWORD_E(bit)] = ((orig & ~(VL_EUL(1) << VL_BITBIT_E(bit)))
| (rhs<<VL_BITBIT_I(bit))); | (static_cast<EData>(rhs) << VL_BITBIT_E(bit)));
} }
// Alternative form that is an instruction faster when rhs is constant one. // 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 { 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)<<VL_BITBIT_Q(bit))); lhsr = (lhsr | (VL_ULL(1)<<VL_BITBIT_Q(bit)));
} }
static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAFE { static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAFE {
IData orig = owp[VL_BITWORD_I(bit)]; EData orig = owp[VL_BITWORD_E(bit)];
owp[VL_BITWORD_I(bit)] = (orig | (VL_UL(1)<<VL_BITBIT_I(bit))); owp[VL_BITWORD_E(bit)] = (orig | (VL_EUL(1) << VL_BITBIT_E(bit)));
} }
//=================================================================== //===================================================================
@ -869,14 +872,14 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAF
(od) = ((svar).read().get_word(0)) & VL_MASK_I(obits); \ (od) = ((svar).read().get_word(0)) & VL_MASK_I(obits); \
} }
#define VL_ASSIGN_QSW(obits,od,svar) { \ #define VL_ASSIGN_QSW(obits,od,svar) { \
(od) = ((static_cast<QData>((svar).read().get_word(1)))<<VL_WORDSIZE \ (od) = ((static_cast<QData>((svar).read().get_word(1)))<<VL_IDATASIZE \
| (svar).read().get_word(0)) \ | (svar).read().get_word(0)) \
& VL_MASK_Q(obits); \ & VL_MASK_Q(obits); \
} }
#define VL_ASSIGN_WSW(obits,owp,svar) { \ #define VL_ASSIGN_WSW(obits,owp,svar) { \
int words = VL_WORDS_I(obits); \ int words = VL_WORDS_I(obits); \
for (int i=0; i < words; ++i) (owp)[i] = (svar).read().get_word(i); \ for (int i=0; i < words; ++i) (owp)[i] = (svar).read().get_word(i); \
(owp)[words-1] &= VL_MASK_I(obits); \ (owp)[words-1] &= VL_MASK_E(obits); \
} }
#define VL_ASSIGN_ISU(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits), (obits), (svar).read().to_uint()); } #define VL_ASSIGN_ISU(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits), (obits), (svar).read().to_uint()); }
@ -885,11 +888,11 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAF
int words = VL_WORDS_I(obits); \ int words = VL_WORDS_I(obits); \
sc_biguint<(obits)> _butemp = (svar).read(); \ sc_biguint<(obits)> _butemp = (svar).read(); \
for (int i=0; i < words; ++i) { \ 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; \ 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. // 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) { \ #define VL_ASSIGN_SWQ(obits,svar,rd) { \
sc_bv<(obits)> _bvtemp; \ sc_bv<(obits)> _bvtemp; \
_bvtemp.set_word(0, static_cast<IData>(rd)); \ _bvtemp.set_word(0, static_cast<IData>(rd)); \
_bvtemp.set_word(1, static_cast<IData>((rd)>>VL_WORDSIZE)); \ _bvtemp.set_word(1, static_cast<IData>((rd) >> VL_IDATASIZE)); \
(svar).write(_bvtemp); \ (svar).write(_bvtemp); \
} }
#define VL_ASSIGN_SWW(obits,svar,rwp) { \ #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) { \ #define VL_ASSIGN_SBW(obits,svar,rwp) { \
sc_biguint<(obits)> _butemp; \ sc_biguint<(obits)> _butemp; \
for (int i=0; i < VL_WORDS_I(obits); ++i) { \ 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; \ 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); \ (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 { static inline WDataOutP VL_EXTEND_WI(int obits, int, WDataOutP owp, IData ld) VL_MT_SAFE {
// Note for extracts that obits != lbits // Note for extracts that obits != lbits
owp[0] = ld; 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; return owp;
} }
static inline WDataOutP VL_EXTEND_WQ(int obits, int, WDataOutP owp, QData ld) VL_MT_SAFE { 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; for (int i = VL_WQ_WORDS_E; 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 { 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 = 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 = VL_WORDS_I(lbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
return owp; 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 { static inline WDataOutP VL_EXTENDS_WI(int obits, int lbits, WDataOutP owp, IData ld) VL_MT_SAFE {
IData sign = VL_SIGNONES_I(lbits, ld); EData sign = VL_SIGNONES_E(lbits, static_cast<EData>(ld));
owp[0] = ld | (sign & ~VL_MASK_I(lbits)); owp[0] = ld | (sign & ~VL_MASK_E(lbits));
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = sign; 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 { static inline WDataOutP VL_EXTENDS_WQ(int obits, int lbits, WDataOutP owp, QData ld) VL_MT_SAFE {
VL_SET_WQ(owp, ld); VL_SET_WQ(owp, ld);
IData sign = VL_SIGNONES_I(lbits, owp[1]); EData sign = VL_SIGNONES_E(lbits, owp[1]);
owp[1] |= sign & ~VL_MASK_I(lbits); owp[1] |= sign & ~VL_MASK_E(lbits);
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = sign; for (int i = VL_WQ_WORDS_E; 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 { 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]; for (int i = 0; i < VL_WORDS_I(lbits)-1; ++i) owp[i] = lwp[i];
int lmsw = VL_WORDS_I(lbits)-1; int lmsw = VL_WORDS_I(lbits) - 1;
IData sign = VL_SIGNONES_I(lbits, lwp[lmsw]); EData sign = VL_SIGNONES_E(lbits, lwp[lmsw]);
owp[lmsw] = lwp[lmsw] | (sign & ~VL_MASK_I(lbits)); 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; for (int i = VL_WORDS_I(lbits); i < VL_WORDS_I(obits); ++i) owp[i] = sign;
return owp; 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)) #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 { static inline IData VL_REDAND_IW(int, int lbits, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(lbits); int words = VL_WORDS_I(lbits);
IData combine = lwp[0]; EData combine = lwp[0];
for (int i=1; i < words-1; ++i) combine &= lwp[i]; for (int i = 1; i < words - 1; ++i) combine &= lwp[i];
combine &= ~VL_MASK_I(lbits) | lwp[words-1]; combine &= ~VL_MASK_E(lbits) | lwp[words-1];
return ((~combine)==0); 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_I(lhs) ((lhs)!=0)
#define VL_REDOR_Q(lhs) ((lhs)!=0) #define VL_REDOR_Q(lhs) ((lhs)!=0)
static inline IData VL_REDOR_W(int words, WDataInP lwp) VL_MT_SAFE { 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]; for (int i=0; i < words; ++i) equal |= lwp[i];
return (equal != 0); return (equal != 0);
} }
@ -1061,7 +1064,7 @@ static inline IData VL_REDXOR_64(QData r) VL_PURE {
#endif #endif
} }
static inline IData VL_REDXOR_W(int words, WDataInP lwp) VL_MT_SAFE { 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]; for (int i=1; i < words; ++i) r ^= lwp[i];
return VL_REDXOR_32(r); 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 { static inline IData VL_COUNTONES_Q(QData lhs) VL_PURE {
return VL_COUNTONES_I(static_cast<IData>(lhs)) + VL_COUNTONES_I(static_cast<IData>(lhs>>32)); return VL_COUNTONES_I(static_cast<IData>(lhs)) + VL_COUNTONES_I(static_cast<IData>(lhs>>32));
} }
#define VL_COUNTONES_E VL_COUNTONES_I
static inline IData VL_COUNTONES_W(int words, WDataInP lwp) VL_MT_SAFE { static inline IData VL_COUNTONES_W(int words, WDataInP lwp) VL_MT_SAFE {
IData r = 0; EData r = 0;
for (int i=0; (i < words); ++i) r+=VL_COUNTONES_I(lwp[i]); for (int i = 0; i < words; ++i) r += VL_COUNTONES_E(lwp[i]);
return r; return r;
} }
@ -1091,7 +1095,7 @@ static inline IData VL_ONEHOT_Q(QData lhs) VL_PURE {
return (((lhs & (lhs-1))==0) & (lhs!=0)); return (((lhs & (lhs-1))==0) & (lhs!=0));
} }
static inline IData VL_ONEHOT_W(int words, WDataInP lwp) VL_MT_SAFE { 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) { for (int i=0; (i < words); ++i) {
if (lwp[i]) { if (lwp[i]) {
if (one) return 0; if (one) return 0;
@ -1136,12 +1140,12 @@ static inline IData VL_CLOG2_Q(QData lhs) VL_PURE {
return shifts; return shifts;
} }
static inline IData VL_CLOG2_W(int words, WDataInP lwp) VL_MT_SAFE { 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) { for (int i=words-1; i>=0; --i) {
if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken
for (int bit=31; bit>=0; --bit) { for (int bit = VL_EDATASIZE - 1; bit >= 0; --bit) {
if (VL_UNLIKELY(VL_BITISSET_I(lwp[i], bit))) { if (VL_UNLIKELY(VL_BITISSET_E(lwp[i], bit))) {
return i*VL_WORDSIZE + bit + adjust; return i * VL_EDATASIZE + bit + adjust;
} }
} }
// Can't get here - one bit must be set // 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 // MSB set bit plus one; similar to FLS. 0=value is zero
for (int i=words-1; i>=0; --i) { for (int i=words-1; i>=0; --i) {
if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken
for (int bit=31; bit>=0; --bit) { for (int bit = VL_EDATASIZE - 1; bit >= 0; --bit) {
if (VL_UNLIKELY(VL_BITISSET_I(lwp[i], bit))) { if (VL_UNLIKELY(VL_BITISSET_E(lwp[i], bit))) {
return i*VL_WORDSIZE + bit + 1; return i * VL_EDATASIZE + bit + 1;
} }
} }
// Can't get here - one bit must be set // 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, <lhs> AND <rhs> MUST BE CLEAN // Output clean, <lhs> AND <rhs> MUST BE CLEAN
static inline IData VL_EQ_W(int words, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { 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]); for (int i=0; (i < words); ++i) nequal |= (lwp[i] ^ rwp[i]);
return (nequal==0); 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 words = VL_WORDS_I(lbits);
int i = words-1; int i = words-1;
// We need to flip sense if negative comparison // We need to flip sense if negative comparison
IData lsign = VL_SIGN_I(lbits, lwp[i]); EData lsign = VL_SIGN_E(lbits, lwp[i]);
IData rsign = VL_SIGN_I(lbits, rwp[i]); EData rsign = VL_SIGN_E(lbits, rwp[i]);
if (!lsign && rsign) return 1; // + > - if (!lsign && rsign) return 1; // + > -
if (lsign && !rsign) return -1; // - < + if (lsign && !rsign) return -1; // - < +
for (; i>=0; --i) { for (; i>=0; --i) {
@ -1300,6 +1304,22 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
//========================================================================= //=========================================================================
// Math // 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_MUL: oclean=dirty; lclean==clean; rclean==clean;
// EMIT_RULE: VL_DIV: 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; // 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 { static inline WDataOutP VL_ADD_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
QData carry = 0; QData carry = 0;
for (int i=0; i<words; ++i) { for (int i = 0; i < words; ++i) {
carry = carry + static_cast<QData>(lwp[i]) + static_cast<QData>(rwp[i]); carry = carry + static_cast<QData>(lwp[i]) + static_cast<QData>(rwp[i]);
owp[i] = (carry & VL_ULL(0xffffffff)); owp[i] = (carry & VL_ULL(0xffffffff));
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
} }
// Last output word is dirty
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; QData carry = 0;
for (int i=0; i<words; ++i) { for (int i = 0; i < words; ++i) {
carry = (carry + static_cast<QData>(lwp[i]) carry = (carry + static_cast<QData>(lwp[i])
+ static_cast<QData>(static_cast<IData>(~rwp[i]))); + static_cast<QData>(static_cast<IData>(~rwp[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);
}
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<words; ++i) {
carry = carry + static_cast<QData>(static_cast<IData>(~lwp[i]));
if (i==0) ++carry; // Negation of temp2
owp[i] = (carry & VL_ULL(0xffffffff)); owp[i] = (carry & VL_ULL(0xffffffff));
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
} }
// Last output word is dirty
return owp; return owp;
} }
@ -1385,20 +1390,20 @@ static inline WDataOutP VL_MULS_WWW(int, int lbits, int,
WData rwstore[VL_MULS_MAX_WORDS]; WData rwstore[VL_MULS_MAX_WORDS];
WDataInP lwusp = lwp; WDataInP lwusp = lwp;
WDataInP rwusp = rwp; 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 if (lneg) { // Negate lhs
lwusp = lwstore; lwusp = lwstore;
VL_NEGATE_W(words, lwstore, lwp); 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 if (rneg) { // Negate rhs
rwusp = rwstore; rwusp = rwstore;
VL_NEGATE_W(words, rwstore, rwp); 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); 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) if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
QData carry = 0; QData carry = 0;
for (int i=0; i<words; ++i) { for (int i=0; i<words; ++i) {
@ -1407,7 +1412,7 @@ static inline WDataOutP VL_MULS_WWW(int, int lbits, int,
owp[i] = (carry & VL_ULL(0xffffffff)); owp[i] = (carry & VL_ULL(0xffffffff));
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff); carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
} }
//Not needed: owp[words-1] |= 1<<VL_BITBIT_I(lbits-1); // Set sign bit // Not needed: owp[words-1] |= 1<<VL_BITBIT_E(lbits-1); // Set sign bit
} }
// Last output word is dirty // Last output word is dirty
return owp; return owp;
@ -1415,33 +1420,33 @@ static inline WDataOutP VL_MULS_WWW(int, int lbits, int,
static inline IData VL_DIVS_III(int lbits, IData lhs, IData rhs) VL_PURE { static inline IData VL_DIVS_III(int lbits, IData lhs, IData rhs) VL_PURE {
if (VL_UNLIKELY(rhs==0)) return 0; if (VL_UNLIKELY(rhs==0)) return 0;
vlsint32_t lhs_signed = VL_EXTENDS_II(32, lbits, lhs); vlsint32_t lhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, lhs);
vlsint32_t rhs_signed = VL_EXTENDS_II(32, lbits, rhs); vlsint32_t rhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, rhs);
return lhs_signed / rhs_signed; return lhs_signed / rhs_signed;
} }
static inline QData VL_DIVS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE { static inline QData VL_DIVS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE {
if (VL_UNLIKELY(rhs==0)) return 0; if (VL_UNLIKELY(rhs==0)) return 0;
vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); vlsint64_t lhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, lhs);
vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); vlsint64_t rhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, rhs);
return lhs_signed / rhs_signed; return lhs_signed / rhs_signed;
} }
static inline IData VL_MODDIVS_III(int lbits, IData lhs, IData rhs) VL_PURE { static inline IData VL_MODDIVS_III(int lbits, IData lhs, IData rhs) VL_PURE {
if (VL_UNLIKELY(rhs==0)) return 0; if (VL_UNLIKELY(rhs==0)) return 0;
vlsint32_t lhs_signed = VL_EXTENDS_II(32, lbits, lhs); vlsint32_t lhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, lhs);
vlsint32_t rhs_signed = VL_EXTENDS_II(32, lbits, rhs); vlsint32_t rhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, rhs);
return lhs_signed % rhs_signed; return lhs_signed % rhs_signed;
} }
static inline QData VL_MODDIVS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE { static inline QData VL_MODDIVS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE {
if (VL_UNLIKELY(rhs==0)) return 0; if (VL_UNLIKELY(rhs==0)) return 0;
vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); vlsint64_t lhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, lhs);
vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); vlsint64_t rhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, rhs);
return lhs_signed % rhs_signed; return lhs_signed % rhs_signed;
} }
static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
int words = VL_WORDS_I(lbits); int words = VL_WORDS_I(lbits);
IData lsign = VL_SIGN_I(lbits, lwp[words-1]); EData lsign = VL_SIGN_E(lbits, lwp[words-1]);
IData rsign = VL_SIGN_I(lbits, rwp[words-1]); EData rsign = VL_SIGN_E(lbits, rwp[words-1]);
// cppcheck-suppress variableScope // cppcheck-suppress variableScope
WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope // cppcheck-suppress variableScope
@ -1451,7 +1456,7 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp, WDataInP lwp, WDat
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); } if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); } if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if ((lsign && !rsign) || (!lsign && rsign)) { if ((lsign && !rsign) || (!lsign && rsign)) {
IData qNoSign[VL_MULS_MAX_WORDS]; WData qNoSign[VL_MULS_MAX_WORDS];
VL_DIV_WWW(lbits, qNoSign, ltup, rtup); VL_DIV_WWW(lbits, qNoSign, ltup, rtup);
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign)); _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
return owp; return owp;
@ -1461,8 +1466,8 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp, WDataInP lwp, WDat
} }
static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
int words = VL_WORDS_I(lbits); int words = VL_WORDS_I(lbits);
IData lsign = VL_SIGN_I(lbits, lwp[words-1]); EData lsign = VL_SIGN_E(lbits, lwp[words-1]);
IData rsign = VL_SIGN_I(lbits, rwp[words-1]); EData rsign = VL_SIGN_E(lbits, rwp[words-1]);
// cppcheck-suppress variableScope // cppcheck-suppress variableScope
WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope // cppcheck-suppress variableScope
@ -1580,24 +1585,25 @@ static inline void _VL_INSERT_QQ(int, QData& lhsr, QData ld, int hbit, int lbit)
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask); lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
} }
static inline void _VL_INSERT_WI(int, WDataOutP owp, IData ld, int hbit, int lbit) VL_MT_SAFE { static inline void _VL_INSERT_WI(int, WDataOutP owp, IData ld, int hbit, int lbit) VL_MT_SAFE {
int hoffset = VL_BITBIT_I(hbit); int hoffset = VL_BITBIT_E(hbit);
int loffset = VL_BITBIT_I(lbit); int loffset = VL_BITBIT_E(lbit);
if (hoffset==VL_SIZEBITS_I && loffset==0) { if (hoffset == VL_SIZEBITS_E && loffset == 0) {
// Fast and common case, word based insertion // Fast and common case, word based insertion
owp[VL_BITWORD_I(lbit)] = ld; owp[VL_BITWORD_E(lbit)] = ld;
} }
else { else {
int hword = VL_BITWORD_I(hbit); int hword = VL_BITWORD_E(hbit);
int lword = VL_BITWORD_I(lbit); int lword = VL_BITWORD_E(lbit);
if (hword==lword) { // know < 32 bits because above checks it EData lde = static_cast<EData>(ld);
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset; if (hword == lword) { // know < EData bits because above checks it
owp[lword] = (owp[lword] & ~insmask) | ((ld<<loffset) & insmask); EData insmask = (VL_MASK_E(hoffset - loffset + 1)) << loffset;
owp[lword] = (owp[lword] & ~insmask) | ((lde << loffset) & insmask);
} else { } else {
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0; EData hinsmask = (VL_MASK_E(hoffset - 0 + 1)) << 0;
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset; EData linsmask = (VL_MASK_E((VL_EDATASIZE - 1) - loffset + 1)) << loffset;
int nbitsonright = 32-loffset; // bits that end up in lword int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword
owp[lword] = (owp[lword] & ~linsmask) | ((ld<<loffset) & linsmask); owp[lword] = (owp[lword] & ~linsmask) | ((lde << loffset) & linsmask);
owp[hword] = (owp[hword] & ~hinsmask) | ((ld>>nbitsonright) & hinsmask); 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 // INTERNAL: Stuff large LHS bit 0++ into OUTPUT at specified offset
// lwp may be "dirty" // lwp may be "dirty"
static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int lbit) VL_MT_SAFE { 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 hoffset = hbit & VL_SIZEBITS_E;
int loffset = lbit & VL_SIZEBITS_I; int loffset = lbit & VL_SIZEBITS_E;
int lword = VL_BITWORD_I(lbit); int lword = VL_BITWORD_E(lbit);
int words = VL_WORDS_I(hbit-lbit+1); int words = VL_WORDS_I(hbit - lbit + 1);
if (hoffset==VL_SIZEBITS_I && loffset==0) { if (hoffset == VL_SIZEBITS_E && loffset == 0) {
// Fast and common case, word based insertion // Fast and common case, word based insertion
for (int i=0; i<words; ++i) { for (int i=0; i<words; ++i) {
owp[lword+i] = lwp[i]; owp[lword+i] = lwp[i];
@ -1620,29 +1626,33 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
for (int i=0; i<(words-1); ++i) { for (int i=0; i<(words-1); ++i) {
owp[lword+i] = lwp[i]; owp[lword+i] = lwp[i];
} }
IData hinsmask = (VL_MASK_I(hoffset-0+1)); // Know it's not a full word as above fast case handled it // Know it's not a full word as above fast case handled it
owp[lword+words-1] = (owp[words+lword-1] & ~hinsmask) | (lwp[words-1] & hinsmask); EData hinsmask = (VL_MASK_E(hoffset - 0 + 1));
owp[lword + words - 1]
= (owp[words + lword - 1] & ~hinsmask) | (lwp[words - 1] & hinsmask);
} }
else { else {
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0; EData hinsmask = (VL_MASK_E(hoffset - 0 + 1)) << 0;
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset; EData linsmask = (VL_MASK_E((VL_EDATASIZE - 1) - loffset + 1)) << loffset;
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0) int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword (know loffset!=0)
// Middle words // Middle words
int hword = VL_BITWORD_I(hbit); int hword = VL_BITWORD_E(hbit);
for (int i=0; i<words; ++i) { for (int i=0; i<words; ++i) {
{ // Lower word { // Lower word
int oword = lword+i; int oword = lword+i;
IData d = lwp[i]<<loffset; EData d = lwp[i] << loffset;
IData od = (owp[oword] & ~linsmask) | (d & linsmask); EData od = (owp[oword] & ~linsmask) | (d & linsmask);
if (oword==hword) owp[oword] = (owp[oword] & ~hinsmask) | (od & hinsmask); if (oword == hword)
owp[oword] = (owp[oword] & ~hinsmask) | (od & hinsmask);
else owp[oword] = od; else owp[oword] = od;
} }
{ // Upper word { // Upper word
int oword = lword+i+1; int oword = lword+i+1;
if (oword <= hword) { if (oword <= hword) {
IData d = lwp[i]>>nbitsonright; EData d = lwp[i] >> nbitsonright;
IData od = (d & ~linsmask) | (owp[oword] & linsmask); EData od = (d & ~linsmask) | (owp[oword] & linsmask);
if (oword==hword) owp[oword] = (owp[oword] & ~hinsmask) | (od & hinsmask); if (oword == hword)
owp[oword] = (owp[oword] & ~hinsmask) | (od & hinsmask);
else owp[oword] = od; 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 { 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); _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: case 4:
ret = ((ret >> 16) | (ret << 16)); 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 { 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<ssize && sbit<lbits-istart; ++sbit) { for (int sbit=0; sbit<ssize && sbit<lbits-istart; ++sbit) {
// Extract a single bit from lwp and shift it to the correct // Extract a single bit from lwp and shift it to the correct
// location for owp. // location for owp.
WData bit= (VL_BITRSHIFT_W(lwp, (istart+sbit)) & 1) << VL_BITBIT_I(ostart+sbit); EData bit = (VL_BITRSHIFT_W(lwp, (istart + sbit)) & 1) << VL_BITBIT_E(ostart + sbit);
owp[VL_BITWORD_I(ostart+sbit)] |= bit; owp[VL_BITWORD_E(ostart + sbit)] |= bit;
} }
} }
return owp; return owp;
@ -1864,7 +1874,7 @@ static inline WDataOutP VL_CONCAT_WIW(int obits, int lbits, int rbits,
static inline WDataOutP VL_CONCAT_WIQ(int obits, int lbits, int rbits, static inline WDataOutP VL_CONCAT_WIQ(int obits, int lbits, int rbits,
WDataOutP owp, IData ld, QData rd) VL_MT_SAFE { 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; for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WI(obits, owp, ld, rbits+lbits-1, rbits); _VL_INSERT_WI(obits, owp, ld, rbits+lbits-1, rbits);
return owp; return owp;
} }
@ -1878,14 +1888,14 @@ static inline WDataOutP VL_CONCAT_WQI(int obits, int lbits, int rbits,
static inline WDataOutP VL_CONCAT_WQQ(int obits, int lbits, int rbits, static inline WDataOutP VL_CONCAT_WQQ(int obits, int lbits, int rbits,
WDataOutP owp, QData ld, QData rd) VL_MT_SAFE { 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; for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WQ(obits, owp, ld, rbits+lbits-1, rbits); _VL_INSERT_WQ(obits, owp, ld, rbits+lbits-1, rbits);
return owp; return owp;
} }
static inline WDataOutP VL_CONCAT_WWQ(int obits, int lbits, int rbits, static inline WDataOutP VL_CONCAT_WWQ(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, QData rd) VL_MT_SAFE { 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; for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits, owp, lwp, rbits+lbits-1, rbits); _VL_INSERT_WW(obits, owp, lwp, rbits+lbits-1, rbits);
return owp; return owp;
} }
@ -1911,12 +1921,12 @@ static inline WDataOutP VL_CONCAT_WWW(int obits, int lbits, int rbits,
// The output is the same as the input - it overlaps! // 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); int words = VL_WORDS_I(obits);
IData linsmask = VL_MASK_I(rd); EData linsmask = VL_MASK_E(rd);
for (int i=words-1; i>=1; --i) { for (int i=words-1; i>=1; --i) {
iowp[i] = ((iowp[i]<<rd) & ~linsmask) | ((iowp[i-1] >> (32-rd)) & linsmask); iowp[i] = ((iowp[i]<<rd) & ~linsmask) | ((iowp[i-1] >> (VL_EDATASIZE - rd)) & linsmask);
} }
iowp[0] = ((iowp[0]<<rd) & ~linsmask); iowp[0] = ((iowp[0]<<rd) & ~linsmask);
iowp[VL_WORDS_I(obits)-1] &= VL_MASK_I(obits); iowp[VL_WORDS_I(obits)-1] &= VL_MASK_E(obits);
} }
// EMIT_RULE: VL_SHIFTL: oclean=lclean; rclean==clean; // EMIT_RULE: VL_SHIFTL: oclean=lclean; rclean==clean;
@ -1924,8 +1934,8 @@ static inline void _VL_SHIFTL_INPLACE_W(int obits, WDataOutP iowp, IData rd/*1 o
// expression. Thus consider this when optimizing. (And perhaps have 2 funcs?) // expression. Thus consider this when optimizing. (And perhaps have 2 funcs?)
static inline WDataOutP VL_SHIFTL_WWI(int obits, int, int, static inline WDataOutP VL_SHIFTL_WWI(int obits, int, int,
WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE { WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
int word_shift = VL_BITWORD_I(rd); int word_shift = VL_BITWORD_E(rd);
int bit_shift = VL_BITBIT_I(rd); int bit_shift = VL_BITBIT_E(rd);
if (rd >= static_cast<IData>(obits)) { // rd may be huge with MSB set if (rd >= static_cast<IData>(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) } 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?) // expression. Thus consider this when optimizing. (And perhaps have 2 funcs?)
static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int, static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int,
WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE { WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
int word_shift = VL_BITWORD_I(rd); // Maybe 0 int word_shift = VL_BITWORD_E(rd); // Maybe 0
int bit_shift = VL_BITBIT_I(rd); int bit_shift = VL_BITBIT_E(rd);
if (rd >= static_cast<IData>(obits)) { // rd may be huge with MSB set if (rd >= static_cast<IData>(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) } 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=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; for (int i=copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
} else { } else {
int loffset = rd & VL_SIZEBITS_I; int loffset = rd & VL_SIZEBITS_E;
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0) int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword (know loffset!=0)
// Middle words // Middle words
int words = VL_WORDS_I(obits-rd); int words = VL_WORDS_I(obits-rd);
for (int i=0; i<words; ++i) { for (int i=0; i<words; ++i) {
@ -2041,22 +2051,22 @@ static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits,
} }
static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int, static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int,
WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE { WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
int word_shift = VL_BITWORD_I(rd); int word_shift = VL_BITWORD_E(rd);
int bit_shift = VL_BITBIT_I(rd); int bit_shift = VL_BITBIT_E(rd);
int lmsw = VL_WORDS_I(obits)-1; int lmsw = VL_WORDS_I(obits)-1;
IData sign = VL_SIGNONES_I(lbits, lwp[lmsw]); EData sign = VL_SIGNONES_E(lbits, lwp[lmsw]);
if (rd >= static_cast<IData>(obits)) { // Shifting past end, sign in all of lbits if (rd >= static_cast<IData>(obits)) { // Shifting past end, sign in all of lbits
for (int i=0; i <= lmsw; ++i) owp[i] = sign; 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) } else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
int copy_words = (VL_WORDS_I(obits)-word_shift); 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=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift];
if (copy_words>=0) owp[copy_words-1] |= ~VL_MASK_I(obits) & sign; 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; for (int i = copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits); owp[lmsw] &= VL_MASK_E(lbits);
} else { } else {
int loffset = rd & VL_SIZEBITS_I; int loffset = rd & VL_SIZEBITS_E;
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0) int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword (know loffset!=0)
// Middle words // Middle words
int words = VL_WORDS_I(obits-rd); int words = VL_WORDS_I(obits-rd);
for (int i=0; i<words; ++i) { for (int i=0; i<words; ++i) {
@ -2066,51 +2076,57 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int,
owp[i] |= lwp[upperword]<< nbitsonright; owp[i] |= lwp[upperword]<< nbitsonright;
} }
} }
if (words) owp[words-1] |= sign & ~VL_MASK_I(obits-loffset); if (words) owp[words - 1] |= sign & ~VL_MASK_E(obits - loffset);
for (int i=words; i<VL_WORDS_I(obits); ++i) owp[i] = sign; for (int i = words; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits); owp[lmsw] &= VL_MASK_E(lbits);
} }
return owp; return owp;
} }
static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits, static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
for (int i=1; i < VL_WORDS_I(rbits); ++i) { EData overshift = 0; // Huge shift 1>>32 or more
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more for (int i = 1; i < VL_WORDS_I(rbits); ++i) {
int lmsw = VL_WORDS_I(obits)-1; overshift |= rwp[i];
IData sign = VL_SIGNONES_I(lbits, lwp[lmsw]); }
for (int j=0; j <= lmsw; ++j) owp[j] = sign; if (VL_UNLIKELY(overshift)) {
owp[lmsw] &= VL_MASK_I(lbits); int lmsw = VL_WORDS_I(obits) - 1;
return owp; 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]); return VL_SHIFTRS_WWI(obits, lbits, 32, owp, lwp, rwp[0]);
} }
static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits, static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits,
IData lhs, WDataInP rwp) VL_MT_SAFE { IData lhs, WDataInP rwp) VL_MT_SAFE {
for (int i=1; i < VL_WORDS_I(rbits); ++i) { EData overshift = 0; // Huge shift 1>>32 or more
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more for (int i = 1; i < VL_WORDS_I(rbits); ++i) {
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative overshift |= rwp[i];
return VL_CLEAN_II(obits, obits, sign); }
} 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]); return VL_SHIFTRS_III(obits, lbits, 32, lhs, rwp[0]);
} }
static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits, static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits,
QData lhs, WDataInP rwp) VL_MT_SAFE { QData lhs, WDataInP rwp) VL_MT_SAFE {
for (int i=1; i < VL_WORDS_I(rbits); ++i) { EData overshift = 0; // Huge shift 1>>32 or more
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more for (int i = 1; i < VL_WORDS_I(rbits); ++i) {
QData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative overshift |= rwp[i];
return VL_CLEAN_QQ(obits, obits, sign); }
} 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]); 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 { 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); 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 { 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); 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<IData>((lhs)>>(rhs))) #define VL_BITSEL_IQII(obits,lbits,rbits,zbits,lhs,rhs) (static_cast<IData>((lhs)>>(rhs)))
static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData rd) VL_MT_SAFE { 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<IData>(lbits))) { if (VL_UNLIKELY(rd > static_cast<IData>(lbits))) {
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so. 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. // We return all 1's as that's more likely to find bugs (?) than 0's.
} else { } 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; int msb = lsb+width-1;
if (VL_UNLIKELY(msb>lbits)) { if (VL_UNLIKELY(msb>lbits)) {
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so. 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<int>(lsb))) { } else if (VL_BITWORD_E(msb) == VL_BITWORD_E(static_cast<int>(lsb))) {
return VL_BITRSHIFT_W(lwp, lsb); return VL_BITRSHIFT_W(lwp, lsb);
} else { } else {
// 32 bit extraction may span two words // 32 bit extraction may span two words
int nbitsfromlow = 32-VL_BITBIT_I(lsb); // bits that come from low word int nbitsfromlow = VL_EDATASIZE - VL_BITBIT_E(lsb); // bits that come from low word
return ((lwp[VL_BITWORD_I(msb)]<<nbitsfromlow) return ((lwp[VL_BITWORD_E(msb)] << nbitsfromlow)
| VL_BITRSHIFT_W(lwp, lsb)); | VL_BITRSHIFT_W(lwp, lsb));
} }
} }
@ -2159,20 +2175,20 @@ static inline QData VL_SEL_QWII(int, int lbits, int, int,
int msb = lsb+width-1; int msb = lsb+width-1;
if (VL_UNLIKELY(msb>lbits)) { if (VL_UNLIKELY(msb>lbits)) {
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so. 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<int>(lsb))) { } else if (VL_BITWORD_E(msb) == VL_BITWORD_E(static_cast<int>(lsb))) {
return VL_BITRSHIFT_W(lwp, lsb); return VL_BITRSHIFT_W(lwp, lsb);
} else if (VL_BITWORD_I(msb)==1+VL_BITWORD_I(static_cast<int>(lsb))) { } else if (VL_BITWORD_E(msb) == 1 + VL_BITWORD_E(static_cast<int>(lsb))) {
int nbitsfromlow = 32-VL_BITBIT_I(lsb); int nbitsfromlow = VL_EDATASIZE - VL_BITBIT_E(lsb);
QData hi = (lwp[VL_BITWORD_I(msb)]); QData hi = (lwp[VL_BITWORD_E(msb)]);
QData lo = VL_BITRSHIFT_W(lwp, lsb); QData lo = VL_BITRSHIFT_W(lwp, lsb);
return (hi<<nbitsfromlow) | lo; return (hi<<nbitsfromlow) | lo;
} else { } else {
// 64 bit extraction may span three words // 64 bit extraction may span three words
int nbitsfromlow = 32-VL_BITBIT_I(lsb); int nbitsfromlow = VL_EDATASIZE - VL_BITBIT_E(lsb);
QData hi = (lwp[VL_BITWORD_I(msb)]); QData hi = (lwp[VL_BITWORD_E(msb)]);
QData mid= (lwp[VL_BITWORD_I(lsb)+1]); QData mid = (lwp[VL_BITWORD_E(lsb) + 1]);
QData lo = VL_BITRSHIFT_W(lwp, lsb); QData lo = VL_BITRSHIFT_W(lwp, lsb);
return (hi<<(nbitsfromlow+32)) | (mid<<nbitsfromlow) | lo; return (hi << (nbitsfromlow + VL_EDATASIZE)) | (mid << nbitsfromlow) | lo;
} }
} }
@ -2180,24 +2196,24 @@ static inline WDataOutP VL_SEL_WWII(int obits, int lbits, int, int,
WDataOutP owp, WDataInP lwp, WDataOutP owp, WDataInP lwp,
IData lsb, IData width) VL_MT_SAFE { IData lsb, IData width) VL_MT_SAFE {
int msb = lsb+width-1; int msb = lsb+width-1;
int word_shift = VL_BITWORD_I(lsb); int word_shift = VL_BITWORD_E(lsb);
if (VL_UNLIKELY(msb>lbits)) { // Outside bounds, if (VL_UNLIKELY(msb>lbits)) { // Outside bounds,
for (int i=0; i<VL_WORDS_I(obits)-1; ++i) owp[i] = ~0; for (int i=0; i<VL_WORDS_I(obits)-1; ++i) owp[i] = ~0;
owp[VL_WORDS_I(obits)-1] = VL_MASK_I(obits); owp[VL_WORDS_I(obits) - 1] = VL_MASK_E(obits);
} else if (VL_BITBIT_I(lsb)==0) { } else if (VL_BITBIT_E(lsb) == 0) {
// Just a word extract // Just a word extract
for (int i=0; i<VL_WORDS_I(obits); ++i) owp[i] = lwp[i+word_shift]; for (int i=0; i<VL_WORDS_I(obits); ++i) owp[i] = lwp[i+word_shift];
} else { } else {
// Not a _VL_INSERT because the bits come from any bit number and goto bit 0 // Not a _VL_INSERT because the bits come from any bit number and goto bit 0
int loffset = lsb & VL_SIZEBITS_I; int loffset = lsb & VL_SIZEBITS_E;
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0) int nbitsfromlow = VL_EDATASIZE - loffset; // bits that end up in lword (know loffset!=0)
// Middle words // Middle words
int words = VL_WORDS_I(msb-lsb+1); int words = VL_WORDS_I(msb-lsb+1);
for (int i=0; i<words; ++i) { for (int i=0; i<words; ++i) {
owp[i] = lwp[i+word_shift]>>loffset; owp[i] = lwp[i+word_shift]>>loffset;
int upperword = i+word_shift+1; int upperword = i+word_shift+1;
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) { if (upperword <= static_cast<int>(VL_BITWORD_E(msb))) {
owp[i] |= lwp[upperword]<< nbitsfromlow; owp[i] |= lwp[upperword] << nbitsfromlow;
} }
} }
for (int i=words; i<VL_WORDS_I(obits); ++i) owp[i]=0; for (int i=words; i<VL_WORDS_I(obits); ++i) owp[i]=0;
@ -2264,83 +2280,83 @@ static inline WDataOutP VL_COND_WIWW(int obits, int, int, int,
return o return o
static inline WDataOutP VL_CONST_W_1X(int obits, WDataOutP o, static inline WDataOutP VL_CONST_W_1X(int obits, WDataOutP o,
IData d0) VL_MT_SAFE { EData d0) VL_MT_SAFE {
o[0]=d0; o[0]=d0;
_END(obits,1); } _END(obits,1); }
static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o, static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o,
IData d1, IData d0) VL_MT_SAFE { EData d1, EData d0) VL_MT_SAFE {
o[0]=d0; o[1]=d1; o[0]=d0; o[1]=d1;
_END(obits,2); } _END(obits,2); }
static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o, static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o,
IData d2, IData d1, IData d0) VL_MT_SAFE { EData d2, EData d1, EData d0) VL_MT_SAFE {
o[0]=d0; o[1]=d1; o[2]=d2; o[0]=d0; o[1]=d1; o[2]=d2;
_END(obits,3); } _END(obits,3); }
static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o, static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
_END(obits,4); } _END(obits,4); }
static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o, static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o,
IData d4, EData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
_END(obits,5); } _END(obits,5); }
static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o, static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o,
IData d5, IData d4, EData d5, EData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
_END(obits,6); } _END(obits,6); }
static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o, static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o,
IData d6, IData d5, IData d4, EData d6, EData d5, EData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData 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[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
_END(obits,7); } _END(obits,7); }
static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o, static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o,
IData d7, IData d6, IData d5, IData d4, EData d7, EData d6, EData d5, EData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData 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; 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); } _END(obits,8); }
// //
static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase, static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase,
IData d0) VL_MT_SAFE { EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb); WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[0]=d0;
_END(obits,1); } _END(obits,1); }
static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase, static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase,
IData d1, IData d0) VL_MT_SAFE { EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb); WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[0]=d0; o[1]=d1;
_END(obits,2); } _END(obits,2); }
static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase, static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase,
IData d2, IData d1, IData d0) VL_MT_SAFE { EData d2, EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb); WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[0]=d0; o[1]=d1; o[2]=d2;
_END(obits,3); } _END(obits,3); }
static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase, static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb); WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
_END(obits,4); } _END(obits,4); }
static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase, static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
IData d4, EData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb); WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
_END(obits,5); } _END(obits,5); }
static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase, static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
IData d5, IData d4, EData d5, EData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb); WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
_END(obits,6); } _END(obits,6); }
static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase, static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
IData d6, IData d5, IData d4, EData d6, EData d5, EData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb); WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
_END(obits,7); } _END(obits,7); }
static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase, static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
IData d7, IData d6, IData d5, IData d4, EData d7, EData d6, EData d5, EData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb); WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; 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); } _END(obits,8); }
@ -2349,8 +2365,8 @@ static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
// Partial constant, lower words of vector wider than 8*32, starting at bit number lsb // Partial constant, lower words of vector wider than 8*32, starting at bit number lsb
static inline void VL_CONSTLO_W_8X(int lsb, WDataOutP obase, static inline void VL_CONSTLO_W_8X(int lsb, WDataOutP obase,
IData d7, IData d6, IData d5, IData d4, EData d7, EData d6, EData d5, EData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE { EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb); WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; } o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; }

View File

@ -229,7 +229,8 @@ char* VerilatedFst::quad2Str(vluint64_t newval, int bits) {
} }
char* VerilatedFst::array2Str(const vluint32_t* newval, int bits) { char* VerilatedFst::array2Str(const vluint32_t* newval, int bits) {
int bq = VL_BITWORD_I(bits), br = VL_BITBIT_I(bits); int bq = bits / 32;
int br = bits & 31;
m_valueStrBuffer.reserve(bits+1); m_valueStrBuffer.reserve(bits+1);
char* s = m_valueStrBuffer.data(); char* s = m_valueStrBuffer.data();
vluint32_t v = newval[bq]; vluint32_t v = newval[bq];
@ -238,7 +239,7 @@ char* VerilatedFst::array2Str(const vluint32_t* newval, int bits) {
} }
for (int w = bq-1; w >= 0; --w) { for (int w = bq-1; w >= 0; --w) {
v = newval[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[0] = '0' + ((v>>(i+3))&1);
s[1] = '0' + ((v>>(i+2))&1); s[1] = '0' + ((v>>(i+2))&1);
s[2] = '0' + ((v>>(i+1))&1); s[2] = '0' + ((v>>(i+1))&1);

View File

@ -65,7 +65,7 @@ private:
std::vector<char> m_valueStrBuffer; std::vector<char> m_valueStrBuffer;
char* word2Str(vluint32_t newval, int bits); char* word2Str(vluint32_t newval, int bits);
char* quad2Str(vluint64_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: public:
explicit VerilatedFst(void* fst=NULL); explicit VerilatedFst(void* fst=NULL);
~VerilatedFst() { if (m_fst == NULL) { fstWriterClose(m_fst); } } ~VerilatedFst() { if (m_fst == NULL) { fstWriterClose(m_fst); } }

View File

@ -278,14 +278,14 @@ std::string VL_TO_STRING(const VlQueue<T_Value>& obj) {
extern std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE; extern std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE;
inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE { inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE {
WData lw[2]; VL_SET_WQ(lw, lhs); WData lw[VL_WQ_WORDS_E]; VL_SET_WQ(lw, lhs);
return VL_CVT_PACK_STR_NW(2, lw); 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 { inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) VL_PURE {
return lhs; return lhs;
} }
inline std::string VL_CVT_PACK_STR_NI(IData lhs) VL_PURE { 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); return VL_CVT_PACK_STR_NW(1, lw);
} }
inline std::string VL_CONCATN_NNN(const std::string& lhs, const std::string& rhs) VL_PURE { 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; return got;
} }
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, IData& rdr) VL_MT_SAFE { 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); IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
if (got) rdr = rwp[0]; if (got) rdr = rwp[0];
return got; return got;

View File

@ -153,7 +153,7 @@ public:
#elif defined(__APPLE__) #elif defined(__APPLE__)
vluint32_t info[4]; vluint32_t info[4];
__cpuid_count(1, 0, info[0], info[1], info[2], info[3]); __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) { if ((info[3] & (1 << 9)) == 0) {
return -1; // no APIC on chip return -1; // no APIC on chip
} else { } else {

View File

@ -1333,7 +1333,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
VL_FATAL_MT(__FILE__, __LINE__, "", VL_FATAL_MT(__FILE__, __LINE__, "",
"vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile"); "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
} }
WDataInP datap = (reinterpret_cast<IData*>(vop->varDatap())); WDataInP datap = (reinterpret_cast<EData*>(vop->varDatap()));
for (int i=0; i<words; ++i) { for (int i=0; i<words; ++i) {
out[i].aval = datap[i]; out[i].aval = datap[i];
out[i].bval = 0; out[i].bval = 0;
@ -1617,7 +1617,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
return object; return object;
case VLVT_WDATA: { case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->packed().elements()); int words = VL_WORDS_I(vop->varp()->packed().elements());
WDataOutP datap = (reinterpret_cast<IData*>(vop->varDatap())); WDataOutP datap = (reinterpret_cast<EData*>(vop->varDatap()));
for (int i=0; i<words; ++i) { for (int i=0; i<words; ++i) {
datap[i] = value_p->value.vector[i].aval; datap[i] = value_p->value.vector[i].aval;
if (i==(words-1)) { if (i==(words-1)) {

View File

@ -317,16 +317,20 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
//========================================================================= //=========================================================================
// Integer size macros // Integer size macros
#define VL_BYTESIZE 8 ///< Bits in a byte #define VL_BYTESIZE 8 ///< Bits in a CData / byte
#define VL_SHORTSIZE 16 ///< Bits in a short #define VL_SHORTSIZE 16 ///< Bits in a SData / short
#define VL_WORDSIZE 32 ///< Bits in a word #define VL_IDATASIZE 32 ///< Bits in a IData / word
#define VL_QUADSIZE 64 ///< Bits in a quadword #define VL_WORDSIZE IDATASIZE ///< Legacy define
#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE) #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) /// Bytes this number of bits needs (1 bit=1 byte)
#define VL_BYTES_I(nbits) (((nbits) + (VL_BYTESIZE - 1)) / VL_BYTESIZE) #define VL_BYTES_I(nbits) (((nbits) + (VL_BYTESIZE - 1)) / VL_BYTESIZE)
/// Words this number of bits needs (1 bit=1 word) /// Words/EDatas this number of bits needs (1 bit=1 word)
#define VL_WORDS_I(nbits) (((nbits) + (VL_WORDSIZE - 1)) / VL_WORDSIZE) #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 // Class definition helpers
@ -345,8 +349,9 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
//========================================================================= //=========================================================================
// Base macros // 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_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) /// Mask for words with 1's where relevant bits are (0=all bits)
#define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) \ #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) /// Mask for quads with 1's where relevant bits are (0=all bits)
#define VL_MASK_Q(nbits) (((nbits) & VL_SIZEBITS_Q) \ #define VL_MASK_Q(nbits) (((nbits) & VL_SIZEBITS_Q) \
? ((VL_ULL(1) << ((nbits) & VL_SIZEBITS_Q) )-VL_ULL(1)) : VL_ULL(~0)) ? ((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 /// Mask for EData with 1's where relevant bits are (0=all bits)
#define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long #define VL_MASK_E(nbits) VL_MASK_I(nbits)
#define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad #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 // Floating point

View File

@ -1312,8 +1312,8 @@ public:
int widthMin() const; int widthMin() const;
int widthMinV() const { return v3Global.widthMinUsage()==VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width(); } int widthMinV() const { return v3Global.widthMinUsage()==VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width(); }
int widthWords() const { return VL_WORDS_I(width()); } int widthWords() const { return VL_WORDS_I(width()); }
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); } bool isQuad() const { return (width() > VL_IDATASIZE && width() <= VL_QUADSIZE); }
bool isWide() const { return (width()>VL_QUADSIZE); } bool isWide() const { return (width() > VL_QUADSIZE); }
bool isDouble() const; bool isDouble() const;
bool isSigned() const; bool isSigned() const;
bool isString() const; bool isString() const;

View File

@ -104,14 +104,14 @@ int AstBasicDType::widthTotalBytes() const {
if (width()<=8) return 1; if (width()<=8) return 1;
else if (width()<=16) return 2; else if (width()<=16) return 2;
else if (isQuad()) return 8; else if (isQuad()) return 8;
else return widthWords()*(VL_WORDSIZE/8); else return widthWords() * (VL_EDATASIZE / 8);
} }
int AstNodeClassDType::widthTotalBytes() const { int AstNodeClassDType::widthTotalBytes() const {
if (width()<=8) return 1; if (width()<=8) return 1;
else if (width()<=16) return 2; else if (width()<=16) return 2;
else if (isQuad()) return 8; else if (isQuad()) return 8;
else return widthWords()*(VL_WORDSIZE/8); else return widthWords() * (VL_EDATASIZE / 8);
} }
int AstNodeClassDType::widthAlignBytes() const { int AstNodeClassDType::widthAlignBytes() const {
@ -319,7 +319,7 @@ AstVar::VlArgTypeRecursed AstVar::vlArgTypeRecurse(bool forFunc, const AstNodeDT
otype += "CData"+bitvec; otype += "CData"+bitvec;
} else if (dtypep->widthMin() <= 16) { } else if (dtypep->widthMin() <= 16) {
otype += "SData"+bitvec; otype += "SData"+bitvec;
} else if (dtypep->widthMin() <= VL_WORDSIZE) { } else if (dtypep->widthMin() <= VL_IDATASIZE) {
otype += "IData"+bitvec; otype += "IData"+bitvec;
} else if (dtypep->isQuad()) { } else if (dtypep->isQuad()) {
otype += "QData"+bitvec; otype += "QData"+bitvec;
@ -367,7 +367,7 @@ string AstVar::vlEnumType() const {
arg += "VLVT_UINT8"; arg += "VLVT_UINT8";
} else if (widthMin() <= 16) { } else if (widthMin() <= 16) {
arg += "VLVT_UINT16"; arg += "VLVT_UINT16";
} else if (widthMin() <= VL_WORDSIZE) { } else if (widthMin() <= VL_IDATASIZE) {
arg += "VLVT_UINT32"; arg += "VLVT_UINT32";
} else if (isQuad()) { } else if (isQuad()) {
arg += "VLVT_UINT64"; arg += "VLVT_UINT64";
@ -429,12 +429,12 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
if (isWide() && isReadOnly()) arg += "const "; if (isWide() && isReadOnly()) arg += "const ";
if (widthMin() == 1) { if (widthMin() == 1) {
arg += "bool"; arg += "bool";
} else if (widthMin() <= VL_WORDSIZE) { } else if (widthMin() <= VL_IDATASIZE) {
arg += "uint32_t"; arg += "uint32_t";
} else if (isWide()) { } else if (widthMin() <= VL_QUADSIZE) {
arg += "uint32_t"; // []'s added later
} else {
arg += "vluint64_t"; arg += "vluint64_t";
} else {
arg += "uint32_t"; // []'s added later
} }
if (isWide()) { if (isWide()) {
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead"); 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 >> return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
} else if (widthMin() == 1) { } else if (widthMin() == 1) {
return "bool"; return "bool";
} else if (widthMin() <= VL_WORDSIZE) { } else if (widthMin() <= VL_IDATASIZE) {
if (widthMin() <= 8 && v3Global.opt.pinsUint8()) { if (widthMin() <= 8 && v3Global.opt.pinsUint8()) {
return "uint8_t"; return "uint8_t";
} else if (widthMin() <= 16 && v3Global.opt.pinsUint8()) { } else if (widthMin() <= 16 && v3Global.opt.pinsUint8()) {

View File

@ -109,6 +109,13 @@ public:
m_num.width(32, 32); m_num.width(32, 32);
dtypeSetLogicUnsized(32, m_num.widthMin(), AstNumeric::SIGNED); 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 class RealDouble {}; // for creator type-overload selection
AstConst(FileLine* fl, RealDouble, double num) AstConst(FileLine* fl, RealDouble, double num)
: AstNodeMath(fl) : AstNodeMath(fl)
@ -1119,8 +1126,8 @@ class AstWordSel : public AstNodeSel {
// Select a single word from a multi-word wide value // Select a single word from a multi-word wide value
public: public:
AstWordSel(FileLine* fl, AstNode* fromp, AstNode* bitp) AstWordSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
:AstNodeSel(fl, fromp, bitp) { : AstNodeSel(fl, fromp, bitp) {
dtypeSetUInt32(); // Always used on IData arrays so returns word entities dtypeSetUInt32(); // Always used on WData arrays so returns edata size
} }
ASTNODE_NODE_FUNCS(WordSel) ASTNODE_NODE_FUNCS(WordSel)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstWordSel(this->fileline(), lhsp, rhsp); } virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstWordSel(this->fileline(), lhsp, rhsp); }
@ -3893,7 +3900,8 @@ public:
dtypeFrom(valuep); dtypeFrom(valuep);
m_code = 0; m_code = 0;
m_codeInc = ((arrayRange.ranged() ? arrayRange.elements() : 1) 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_varType = varp->varType();
m_declKwd = varp->declKwd(); m_declKwd = varp->declKwd();
m_declDirection = varp->declDirection(); m_declDirection = varp->declDirection();

View File

@ -80,9 +80,9 @@ private:
} }
int castSize(AstNode* nodep) { int castSize(AstNode* nodep) {
if (nodep->isQuad()) return VL_QUADSIZE; if (nodep->isQuad()) return VL_QUADSIZE;
else if (nodep->width()<=8) return 8; else if (nodep->width() <= 8) return 8;
else if (nodep->width()<=16) return 16; else if (nodep->width() <= 16) return 16;
else return VL_WORDSIZE; else return VL_IDATASIZE;
} }
void insureCast(AstNode* nodep) { void insureCast(AstNode* nodep) {
if (castSize(nodep->backp()) != castSize(nodep) if (castSize(nodep->backp()) != castSize(nodep)
@ -97,7 +97,7 @@ private:
// less than has nondeterministic signedness. // less than has nondeterministic signedness.
if (nodep->isQuad() && !nodep->lhsp()->isQuad() if (nodep->isQuad() && !nodep->lhsp()->isQuad()
&& !VN_IS(nodep->lhsp(), CCast)) { && !VN_IS(nodep->lhsp(), CCast)) {
insertCast(nodep->lhsp(), VL_WORDSIZE); insertCast(nodep->lhsp(), VL_IDATASIZE);
} }
} }

View File

@ -62,9 +62,9 @@ private:
// Width resetting // Width resetting
int cppWidth(AstNode* nodep) { int cppWidth(AstNode* nodep) {
if (nodep->width()<=VL_WORDSIZE) return VL_WORDSIZE; if (nodep->width() <= VL_IDATASIZE) return VL_IDATASIZE;
else if (nodep->width()<=VL_QUADSIZE) return VL_QUADSIZE; else if (nodep->width() <= VL_QUADSIZE) return VL_QUADSIZE;
else return nodep->widthWords()*VL_WORDSIZE; else return nodep->widthWords() * VL_EDATASIZE;
} }
void setCppWidth(AstNode* nodep) { void setCppWidth(AstNode* nodep) {
nodep->user2(true); // Don't resize it again nodep->user2(true); // Don't resize it again
@ -113,8 +113,10 @@ private:
} }
void setClean(AstNode* nodep, bool isClean) { void setClean(AstNode* nodep, bool isClean) {
computeCppWidth(nodep); // Just to be sure it's in widthMin computeCppWidth(nodep); // Just to be sure it's in widthMin
bool wholeUint = ((nodep->widthMin() % VL_WORDSIZE) == 0); // 32,64,... bool wholeUint = (nodep->widthMin() == VL_IDATASIZE
setCleanState(nodep, ((isClean||wholeUint) ? CS_CLEAN:CS_DIRTY)); || nodep->widthMin() == VL_QUADSIZE
|| (nodep->widthMin() % VL_EDATASIZE) == 0);
setCleanState(nodep, ((isClean || wholeUint) ? CS_CLEAN : CS_DIRTY));
} }
// Operate on nodes // Operate on nodes

View File

@ -965,15 +965,15 @@ private:
V3Number ones (nodep, nodep->width()); V3Number ones (nodep, nodep->width());
ones.setMask(nodep->width()); ones.setMask(nodep->width());
if (shift1<0) { if (shift1<0) {
mask1.opShiftR(ones, V3Number(nodep, VL_WORDSIZE, -shift1)); mask1.opShiftR(ones, V3Number(nodep, VL_IDATASIZE, -shift1));
} else { } else {
mask1.opShiftL(ones, V3Number(nodep, VL_WORDSIZE, shift1)); mask1.opShiftL(ones, V3Number(nodep, VL_IDATASIZE, shift1));
} }
V3Number mask (nodep, nodep->width()); V3Number mask (nodep, nodep->width());
if (shift2<0) { if (shift2<0) {
mask.opShiftR(mask1, V3Number(nodep, VL_WORDSIZE, -shift2)); mask.opShiftR(mask1, V3Number(nodep, VL_IDATASIZE, -shift2));
} else { } else {
mask.opShiftL(mask1, V3Number(nodep, VL_WORDSIZE, shift2)); mask.opShiftL(mask1, V3Number(nodep, VL_IDATASIZE, shift2));
} }
if (newshift<0) { if (newshift<0) {
newp = new AstShiftR(nodep->fileline(), ap, newp = new AstShiftR(nodep->fileline(), ap,
@ -1016,8 +1016,6 @@ private:
if (( con1p->toSInt() != con2p->toSInt() + sel2p->width()) if (( con1p->toSInt() != con2p->toSInt() + sel2p->width())
&&(con2p->toSInt() != con1p->toSInt() + sel1p->width())) return false; &&(con2p->toSInt() != con1p->toSInt() + sel1p->width())) return false;
bool lsbFirstAssign = (con1p->toUInt() < con2p->toUInt()); 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 "<<nodep<<endl); UINFO(4,"replaceAssignMultiSel "<<nodep<<endl);
UINFO(4," && "<<nextp<<endl); UINFO(4," && "<<nextp<<endl);
//nodep->dumpTree(cout, "comb1: "); //nodep->dumpTree(cout, "comb1: ");

View File

@ -691,10 +691,10 @@ public:
} }
virtual void visit(AstCCast* nodep) { virtual void visit(AstCCast* nodep) {
// Extending a value of the same word width is just a NOP. // Extending a value of the same word width is just a NOP.
if (nodep->size()>VL_WORDSIZE) { if (nodep->size() <= VL_IDATASIZE) {
puts("(QData)(");
} else {
puts("(IData)("); puts("(IData)(");
} else {
puts("(QData)(");
} }
iterateAndNextNull(nodep->lhsp()); iterateAndNextNull(nodep->lhsp());
puts(")"); puts(")");
@ -788,11 +788,11 @@ public:
} else if (nodep->isWide()) { } else if (nodep->isWide()) {
int upWidth = nodep->num().widthMin(); int upWidth = nodep->num().widthMin();
int chunks = 0; 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 // Output e.g. 8 words in groups of e.g. 8
chunks = (upWidth-1) / (EMITC_NUM_CONSTW*VL_WORDSIZE); chunks = (upWidth-1) / (EMITC_NUM_CONSTW * VL_EDATASIZE);
upWidth %= (EMITC_NUM_CONSTW*VL_WORDSIZE); upWidth %= (EMITC_NUM_CONSTW * VL_EDATASIZE);
if (upWidth == 0) upWidth = (EMITC_NUM_CONSTW*VL_WORDSIZE); if (upWidth == 0) upWidth = (EMITC_NUM_CONSTW * VL_EDATASIZE);
} }
{ // Upper e.g. 8 words { // Upper e.g. 8 words
if (chunks) { if (chunks) {
@ -801,7 +801,7 @@ public:
puts("X("); puts("X(");
puts(cvtToStr(nodep->widthMin())); puts(cvtToStr(nodep->widthMin()));
puts(","); puts(",");
puts(cvtToStr(chunks*EMITC_NUM_CONSTW*VL_WORDSIZE)); puts(cvtToStr(chunks * EMITC_NUM_CONSTW * VL_EDATASIZE));
} else { } else {
putbs("VL_CONST_W_"); putbs("VL_CONST_W_");
puts(cvtToStr(VL_WORDS_I(upWidth))); puts(cvtToStr(VL_WORDS_I(upWidth)));
@ -820,8 +820,8 @@ public:
for (int word=VL_WORDS_I(upWidth)-1; word>=0; word--) { for (int word=VL_WORDS_I(upWidth)-1; word>=0; word--) {
// Only 32 bits - llx + long long here just to appease CPP format warning // Only 32 bits - llx + long long here just to appease CPP format warning
ofp()->printf(",0x%08" VL_PRI64 "x", ofp()->printf(",0x%08" VL_PRI64 "x",
static_cast<vluint64_t>(nodep->num().dataWord static_cast<vluint64_t>(nodep->num().edataWord
(word+chunks*EMITC_NUM_CONSTW))); (word+chunks * EMITC_NUM_CONSTW)));
} }
puts(")"); puts(")");
} }
@ -830,7 +830,7 @@ public:
putbs("VL_CONSTLO_W_"); putbs("VL_CONSTLO_W_");
puts(cvtToStr(EMITC_NUM_CONSTW)); puts(cvtToStr(EMITC_NUM_CONSTW));
puts("X("); puts("X(");
puts(cvtToStr(chunks*EMITC_NUM_CONSTW*VL_WORDSIZE)); puts(cvtToStr(chunks * EMITC_NUM_CONSTW * VL_EDATASIZE));
puts(","); puts(",");
if (!assigntop) { if (!assigntop) {
puts(assignString); puts(assignString);
@ -843,8 +843,8 @@ public:
for (int word=EMITC_NUM_CONSTW-1; word>=0; word--) { for (int word=EMITC_NUM_CONSTW-1; word>=0; word--) {
// Only 32 bits - llx + long long here just to appease CPP format warning // Only 32 bits - llx + long long here just to appease CPP format warning
ofp()->printf(",0x%08" VL_PRI64 "x", ofp()->printf(",0x%08" VL_PRI64 "x",
static_cast<vluint64_t>(nodep->num().dataWord static_cast<vluint64_t>(nodep->num().edataWord
(word+chunks*EMITC_NUM_CONSTW))); (word+chunks * EMITC_NUM_CONSTW)));
} }
puts(")"); puts(")");
} }

View File

@ -55,15 +55,14 @@ private:
VL_DEBUG_FUNC; // Declare debug() VL_DEBUG_FUNC; // Declare debug()
int longOrQuadWidth(AstNode* nodep) { int longOrQuadWidth(AstNode* nodep) {
// Return 32 or 64... return (nodep->width() + (VL_EDATASIZE - 1)) & ~(VL_EDATASIZE - 1);
return (nodep->width()+(VL_WORDSIZE-1)) & ~(VL_WORDSIZE-1);
} }
V3Number notWideMask(AstNode* nodep) { 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) { V3Number wordMask(AstNode* nodep) {
if (nodep->isWide()) { if (nodep->isWide()) {
return V3Number(nodep, VL_WORDSIZE, VL_MASK_I(nodep->widthMin())); return V3Number(nodep, VL_EDATASIZE, VL_MASK_E(nodep->widthMin()));
} else { } else {
V3Number mask (nodep, longOrQuadWidth(nodep)); V3Number mask (nodep, longOrQuadWidth(nodep));
mask.setMask(nodep->widthMin()); mask.setMask(nodep->widthMin());
@ -118,13 +117,13 @@ private:
return new AstWordSel(nodep->fileline(), return new AstWordSel(nodep->fileline(),
nodep->cloneTree(true), nodep->cloneTree(true),
new AstConst(nodep->fileline(), word)); new AstConst(nodep->fileline(), word));
} else if (nodep->isQuad() && word==0) { } else if (nodep->isQuad() && word == 0) {
AstNode* quadfromp = nodep->cloneTree(true); AstNode* quadfromp = nodep->cloneTree(true);
quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(), quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(),
AstNumeric::UNSIGNED); AstNumeric::UNSIGNED);
return new AstCCast(nodep->fileline(), return new AstCCast(nodep->fileline(),
quadfromp, quadfromp,
VL_WORDSIZE); VL_EDATASIZE);
} else if (nodep->isQuad() && word==1) { } else if (nodep->isQuad() && word==1) {
AstNode* quadfromp = nodep->cloneTree(true); AstNode* quadfromp = nodep->cloneTree(true);
quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(), quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(),
@ -132,10 +131,10 @@ private:
return new AstCCast(nodep->fileline(), return new AstCCast(nodep->fileline(),
new AstShiftR(nodep->fileline(), new AstShiftR(nodep->fileline(),
quadfromp, quadfromp,
new AstConst(nodep->fileline(), VL_WORDSIZE), new AstConst(nodep->fileline(), VL_EDATASIZE),
VL_WORDSIZE), VL_EDATASIZE),
VL_WORDSIZE); VL_EDATASIZE);
} else if (!nodep->isWide() && !nodep->isQuad() && word==0) { } else if (!nodep->isWide() && !nodep->isQuad() && word == 0) {
return nodep->cloneTree(true); return nodep->cloneTree(true);
} else { // Out of bounds } else { // Out of bounds
return new AstConst(nodep->fileline(), 0); return new AstConst(nodep->fileline(), 0);
@ -148,25 +147,25 @@ private:
AstNode* newp; AstNode* newp;
// Negative word numbers requested for lhs when it's "before" what we want. // Negative word numbers requested for lhs when it's "before" what we want.
// We get a 0 then. // We get a 0 then.
int othword = word - shift/VL_WORDSIZE; int othword = word - shift / VL_EDATASIZE;
AstNode* llowp = newAstWordSelClone(lhsp, othword); 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); 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 newp = new AstOr
(fl, (fl,
new AstAnd(fl, new AstAnd(fl,
new AstConst(fl, VL_MASK_I(loffset)), new AstConst(fl, AstConst::SizedEData(), VL_MASK_E(loffset)),
new AstShiftR(fl, new AstShiftR(fl,
lhip, lhip,
new AstConst(fl, nbitsonright), new AstConst(fl, nbitsonright),
VL_WORDSIZE)), VL_EDATASIZE)),
new AstAnd(fl, new AstAnd(fl,
new AstConst(fl, ~VL_MASK_I(loffset)), new AstConst(fl, AstConst::SizedEData(), ~VL_MASK_E(loffset)),
new AstShiftL(fl, new AstShiftL(fl,
llowp, llowp,
new AstConst(fl, loffset), new AstConst(fl, loffset),
VL_WORDSIZE))); VL_EDATASIZE)));
} else { } else {
newp = llowp; newp = llowp;
} }
@ -177,12 +176,12 @@ private:
// Return equation to get the VL_BITWORD of a constant or non-constant // Return equation to get the VL_BITWORD of a constant or non-constant
if (VN_IS(lsbp, Const)) { if (VN_IS(lsbp, Const)) {
return new AstConst(lsbp->fileline(), return new AstConst(lsbp->fileline(),
wordAdder + VL_BITWORD_I(VN_CAST(lsbp, Const)->toUInt())); wordAdder + VL_BITWORD_E(VN_CAST(lsbp, Const)->toUInt()));
} else { } else {
AstNode* shiftp = new AstShiftR(lsbp->fileline(), AstNode* shiftp = new AstShiftR(lsbp->fileline(),
lsbp->cloneTree(true), lsbp->cloneTree(true),
new AstConst(lsbp->fileline(), VL_WORDSIZE_LOG2), new AstConst(lsbp->fileline(), VL_EDATASIZE_LOG2),
VL_WORDSIZE); VL_EDATASIZE);
if (wordAdder != 0) { if (wordAdder != 0) {
shiftp = new AstAdd(lsbp->fileline(), shiftp = new AstAdd(lsbp->fileline(),
// This is indexing a arraysel, so a 32 bit constant is fine // 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 // Return equation to get the VL_BITBIT of a constant or non-constant
if (VN_IS(lsbp, Const)) { if (VN_IS(lsbp, Const)) {
return new AstConst(lsbp->fileline(), return new AstConst(lsbp->fileline(),
VL_BITBIT_I(VN_CAST(lsbp, Const)->toUInt())); VL_BITBIT_E(VN_CAST(lsbp, Const)->toUInt()));
} else { } else {
return new AstAnd(lsbp->fileline(), return new AstAnd(lsbp->fileline(),
new AstConst(lsbp->fileline(), VL_WORDSIZE-1), new AstConst(lsbp->fileline(), VL_EDATASIZE - 1),
dropCondBound(lsbp)->cloneTree(true)); dropCondBound(lsbp)->cloneTree(true));
} }
} }
@ -226,8 +225,8 @@ private:
} }
for (int w=0; w<nodep->widthWords(); w++) { for (int w=0; w<nodep->widthWords(); w++) {
addWordAssign(nodep, w, new AstConst(nodep->fileline(), addWordAssign(nodep, w, new AstConst(nodep->fileline(),
AstConst::WidthedValue(), AstConst::SizedEData(),
VL_WORDSIZE, rhsp->num().dataWord(w))); rhsp->num().edataWord(w)));
} }
return true; return true;
} }
@ -339,7 +338,7 @@ private:
addWordAssign(nodep, w, newAstWordSelClone(rhsp->lhsp(), w)); addWordAssign(nodep, w, newAstWordSelClone(rhsp->lhsp(), w));
} }
for (; w<nodep->widthWords(); w++) { for (; w<nodep->widthWords(); w++) {
addWordAssign(nodep, w, new AstConst(rhsp->fileline(), 0)); addWordAssign(nodep, w, new AstConst(rhsp->fileline(), AstConst::SizedEData(), 0));
} }
return true; return true;
} }
@ -387,7 +386,7 @@ private:
// nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb) // nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb)
AstNode* midshiftp = new AstSub(nodep->lsbp()->fileline(), AstNode* midshiftp = new AstSub(nodep->lsbp()->fileline(),
new AstConst(nodep->lsbp()->fileline(), new AstConst(nodep->lsbp()->fileline(),
VL_WORDSIZE), VL_EDATASIZE),
newSelBitBit(nodep->lsbp())); newSelBitBit(nodep->lsbp()));
if (nodep->isQuad()) { if (nodep->isQuad()) {
midshiftp = midshiftp =
@ -395,7 +394,7 @@ private:
new AstEq(nodep->fileline(), new AstEq(nodep->fileline(),
new AstConst(nodep->fileline(), 0), new AstConst(nodep->fileline(), 0),
newSelBitBit(nodep->lsbp())), newSelBitBit(nodep->lsbp())),
new AstConst(nodep->lsbp()->fileline(), VL_WORDSIZE), new AstConst(nodep->lsbp()->fileline(), VL_EDATASIZE),
midshiftp); midshiftp);
} }
AstNode* midmayp = new AstShiftL(nodep->fileline(), AstNode* midmayp = new AstShiftL(nodep->fileline(),
@ -415,7 +414,7 @@ private:
} }
// If > 32 bits, we might be crossing the second word boundary // If > 32 bits, we might be crossing the second word boundary
AstNode* hip = NULL; AstNode* hip = NULL;
if (nodep->widthConst() > VL_WORDSIZE) { if (nodep->widthConst() > VL_EDATASIZE) {
AstNode* hiwordp = // SEL(from,[2+wordnum]) AstNode* hiwordp = // SEL(from,[2+wordnum])
new AstWordSel(nodep->fromp()->fileline(), new AstWordSel(nodep->fromp()->fileline(),
nodep->fromp()->cloneTree(true), nodep->fromp()->cloneTree(true),
@ -468,11 +467,11 @@ private:
bool expandWide(AstNodeAssign* nodep, AstSel* rhsp) { bool expandWide(AstNodeAssign* nodep, AstSel* rhsp) {
UASSERT_OBJ(nodep->widthMin() == rhsp->widthConst(), nodep, "Width mismatch"); 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(); int lsb = rhsp->lsbConst();
UINFO(8," Wordize ASSIGN(SEL,align) "<<nodep<<endl); UINFO(8," Wordize ASSIGN(SEL,align) "<<nodep<<endl);
for (int w=0; w<nodep->widthWords(); w++) { for (int w=0; w<nodep->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; return true;
} else { } else {
@ -485,20 +484,21 @@ private:
AstNode* lowp = new AstShiftR(rhsp->fileline(), AstNode* lowp = new AstShiftR(rhsp->fileline(),
lowwordp, lowwordp,
newSelBitBit(rhsp->lsbp()), newSelBitBit(rhsp->lsbp()),
VL_WORDSIZE); VL_EDATASIZE);
// Upper bits // Upper bits
V3Number zero (nodep, VL_WORDSIZE, 0); V3Number zero (nodep, VL_EDATASIZE, 0);
AstNode* midwordp = // SEL(from,[1+wordnum]) AstNode* midwordp = // SEL(from,[1+wordnum])
new AstWordSel(rhsp->fromp()->fileline(), new AstWordSel(rhsp->fromp()->fileline(),
rhsp->fromp()->cloneTree(true), rhsp->fromp()->cloneTree(true),
newSelBitWord(rhsp->lsbp(), w+1)); newSelBitWord(rhsp->lsbp(), w+1));
AstNode* midshiftp = new AstSub(rhsp->lsbp()->fileline(), AstNode* midshiftp = new AstSub(rhsp->lsbp()->fileline(),
new AstConst(rhsp->lsbp()->fileline(), VL_WORDSIZE), new AstConst(rhsp->lsbp()->fileline(),
VL_EDATASIZE),
newSelBitBit(rhsp->lsbp())); newSelBitBit(rhsp->lsbp()));
AstNode* midmayp = new AstShiftL(rhsp->fileline(), AstNode* midmayp = new AstShiftL(rhsp->fileline(),
midwordp, midwordp,
midshiftp, midshiftp,
VL_WORDSIZE); VL_EDATASIZE);
AstNode* midp = new AstCond(rhsp->fileline(), AstNode* midp = new AstCond(rhsp->fileline(),
new AstEq(rhsp->fileline(), new AstEq(rhsp->fileline(),
new AstConst(rhsp->fileline(), 0), new AstConst(rhsp->fileline(), 0),
@ -534,14 +534,15 @@ private:
if (destwide) { if (destwide) {
UINFO(8," ASSIGNSEL(const,wide) "<<nodep<<endl); UINFO(8," ASSIGNSEL(const,wide) "<<nodep<<endl);
for (int w=0; w<destp->widthWords(); w++) { for (int w=0; w<destp->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 // else we would just be setting it to the same exact value
AstNode* oldvalp = newAstWordSelClone(destp, w); AstNode* oldvalp = newAstWordSelClone(destp, w);
fixCloneLvalue(oldvalp); fixCloneLvalue(oldvalp);
if (!ones) { if (!ones) {
oldvalp = new AstAnd(lhsp->fileline(), oldvalp = new AstAnd(lhsp->fileline(),
new AstConst(lhsp->fileline(), new AstConst(lhsp->fileline(),
maskold.dataWord(w)), AstConst::SizedEData(),
maskold.edataWord(w)),
oldvalp); oldvalp);
} }
addWordAssign(nodep, w, addWordAssign(nodep, w,
@ -598,18 +599,18 @@ private:
// That's ok as we'd just AND with a larger value, // That's ok as we'd just AND with a larger value,
// but oldval would clip the upper bits to sanity // but oldval would clip the upper bits to sanity
newSelBitBit(lhsp->lsbp()), newSelBitBit(lhsp->lsbp()),
VL_WORDSIZE)), VL_EDATASIZE)),
oldvalp); oldvalp);
} }
// Restrict the shift amount to 0-31, see bug804. // Restrict the shift amount to 0-31, see bug804.
AstNode* shiftp = new AstAnd(nodep->fileline(), lhsp->lsbp()->cloneTree(true), 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(), AstNode* newp = new AstOr(lhsp->fileline(),
oldvalp, oldvalp,
new AstShiftL(lhsp->fileline(), new AstShiftL(lhsp->fileline(),
rhsp, rhsp,
shiftp, shiftp,
VL_WORDSIZE)); VL_EDATASIZE));
newp = new AstAssign(nodep->fileline(), newp = new AstAssign(nodep->fileline(),
new AstWordSel(nodep->fileline(), new AstWordSel(nodep->fileline(),
destp, destp,
@ -762,7 +763,7 @@ private:
AstNode* newp; AstNode* newp;
if (lhswidth==1) { if (lhswidth==1) {
newp = new AstNegate(nodep->fileline(), lhsp->cloneTree(true)); newp = new AstNegate(nodep->fileline(), lhsp->cloneTree(true));
newp->dtypeSetLogicSized(VL_WORDSIZE, newp->dtypeSetLogicSized(VL_EDATASIZE,
AstNumeric::UNSIGNED); // Replicate always unsigned AstNumeric::UNSIGNED); // Replicate always unsigned
} else { } else {
newp = newAstWordSelClone(lhsp, w); newp = newAstWordSelClone(lhsp, w);
@ -808,10 +809,12 @@ private:
} }
if (VN_IS(nodep, Neq)) { if (VN_IS(nodep, Neq)) {
newp = new AstNeq(nodep->fileline(), newp = new AstNeq(nodep->fileline(),
new AstConst(nodep->fileline(), 0), newp); new AstConst(nodep->fileline(), AstConst::SizedEData(), 0),
newp);
} else { } else {
newp = new AstEq(nodep->fileline(), 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); replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
} }
@ -831,7 +834,8 @@ private:
newp = (newp==NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp)); newp = (newp==NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp));
} }
newp = new AstNeq(nodep->fileline(), 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); replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
} else { } else {
UINFO(8," REDOR->EQ "<<nodep<<endl); UINFO(8," REDOR->EQ "<<nodep<<endl);
@ -864,7 +868,8 @@ private:
newp = (newp==NULL) ? eqp : (new AstAnd(nodep->fileline(), newp, eqp)); newp = (newp==NULL) ? eqp : (new AstAnd(nodep->fileline(), newp, eqp));
} }
newp = new AstEq(nodep->fileline(), 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); replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
} else { } else {
UINFO(8," REDAND->EQ "<<nodep<<endl); UINFO(8," REDAND->EQ "<<nodep<<endl);

View File

@ -781,9 +781,13 @@ uint32_t V3Number::toHash() const {
return m_value[0]; return m_value[0];
} }
uint32_t V3Number::dataWord(int word) const { uint32_t V3Number::edataWord(int eword) const {
UASSERT(!isFourState(), "dataWord with 4-state "<<*this); UASSERT(!isFourState(), "edataWord with 4-state "<<*this);
return m_value[word]; return m_value[eword];
}
uint8_t V3Number::dataByte(int byte) const {
return (edataWord(byte / (VL_EDATASIZE / 8)) >> ((byte * 8) % VL_EDATASIZE)) & 0xff;
} }
bool V3Number::isEqZero() const { bool V3Number::isEqZero() const {
@ -1656,8 +1660,8 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool
return *this; return *this;
} }
int uw = VL_WORDS_I(umsbp1); // aka "m" in the algorithm int uw = (umsbp1 + 31) / 32; // aka "m" in the algorithm
int vw = VL_WORDS_I(vmsbp1); // aka "n" in the algorithm int vw = (vmsbp1 + 31) / 32; // aka "n" in the algorithm
if (vw == 1) { // Single divisor word breaks rest of algorithm if (vw == 1) { // Single divisor word breaks rest of algorithm
vluint64_t k = 0; vluint64_t k = 0;
@ -1684,7 +1688,7 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool
// Algorithm requires divisor MSB to be set // Algorithm requires divisor MSB to be set
// Copy and shift to normalize divisor so MSB of vn[vw-1] is set // Copy and shift to normalize divisor so MSB of vn[vw-1] is set
int s = 31-VL_BITBIT_I(vmsbp1-1); // shift amount (0...31) int s = 31 - ((vmsbp1-1) & 31); // shift amount (0...31)
uint32_t shift_mask = s ? 0xffffffff : 0; // otherwise >> 32 won't mask the value uint32_t shift_mask = s ? 0xffffffff : 0; // otherwise >> 32 won't mask the value
for (int i = vw-1; i>0; i--) { for (int i = vw-1; i>0; i--) {
vn[i] = (rhs.m_value[i] << s) | (shift_mask & (rhs.m_value[i-1] >> (32-s))); vn[i] = (rhs.m_value[i] << s) | (shift_mask & (rhs.m_value[i-1] >> (32-s)));

View File

@ -243,8 +243,8 @@ public:
string toDecimalU() const; // return ASCII unsigned decimal number string toDecimalU() const; // return ASCII unsigned decimal number
double toDouble() const; double toDouble() const;
uint32_t toHash() const; uint32_t toHash() const;
uint32_t dataWord(int word) const; uint32_t edataWord(int eword) const;
uint8_t dataByte(int byte) const { return (dataWord(byte/4) >> (8*(byte&3))) & 0xff; } uint8_t dataByte(int byte) const;
uint32_t countOnes() const; uint32_t countOnes() const;
uint32_t mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0. uint32_t mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0.

View File

@ -630,10 +630,14 @@ private:
return new AstCStmt(portp->fileline(), linesp); return new AstCStmt(portp->fileline(), linesp);
} }
// Use a AstCMath, as we want V3Clean to mask off bits that don't make sense. // Use a AstCMath, as we want V3Clean to mask off bits that don't make sense.
int cwidth = VL_WORDSIZE; int cwidth = VL_IDATASIZE;
if (portp->basicp()) cwidth = portp->basicp()->keyword().width(); if (portp->basicp()) {
if (portp->basicp() if (portp->basicp()->keyword().isBitLogic()) {
&& portp->basicp()->keyword().isBitLogic()) cwidth = VL_WORDSIZE*portp->widthWords(); cwidth = VL_EDATASIZE * portp->widthWords();
} else {
cwidth = portp->basicp()->keyword().width();
}
}
AstNode* newp = new AstAssign(portp->fileline(), AstNode* newp = new AstAssign(portp->fileline(),
new AstVarRef(portp->fileline(), portvscp, true), new AstVarRef(portp->fileline(), portvscp, true),
new AstSel(portp->fileline(), new AstSel(portp->fileline(),

View File

@ -341,8 +341,8 @@ private:
AstVarType::MODULETEMP, AstVarType::MODULETEMP,
"__Vm_traceActivity", newArrDtp); "__Vm_traceActivity", newArrDtp);
} else { } else {
// For tighter code; round to next 32 bit point. // For tighter code; round to next word point.
int activityBits = VL_WORDS_I(m_activityNumber)*VL_WORDSIZE; int activityBits = VL_WORDS_I(m_activityNumber) * VL_EDATASIZE;
newvarp = new AstVar(m_chgFuncp->fileline(), AstVarType::MODULETEMP, newvarp = new AstVar(m_chgFuncp->fileline(), AstVarType::MODULETEMP,
"__Vm_traceActivity", VFlagBitPacked(), activityBits); "__Vm_traceActivity", VFlagBitPacked(), activityBits);
} }

View File

@ -56,7 +56,7 @@ module t (/*AUTOARG*/
if (cyc!=0) begin if (cyc!=0) begin
cyc <= cyc + 1; cyc <= cyc + 1;
`ifdef TEST_VERBOSE `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 `endif
if (cyc==1) begin if (cyc==1) begin
biu <= 64'h12451282_abadee00; biu <= 64'h12451282_abadee00;