Compare commits

..
11 Commits
30 changed files with 1653 additions and 186 deletions
+13
View File
@@ -3,6 +3,19 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 3.906 2017-06-22
*** Support set_time_unit/set_time_precision in C traces, msg2261.
*** Fix extract of packed array with non-zero LSB, bug1172. [James Pallister]
*** Fix shifts by more than 32-bit numbers, bug1174. [Clifford Wolf]
*** Fix power operator on wide constants, bug761. [Clifford Wolf]
*** Fix .* on interface pins, bug1176. [Maciej Piechotka]
* Verilator 3.904 2017-05-30
*** Fix non-cutable ordering loops on clock arrays, bug1009. [Todd Strader]
+1 -1
View File
@@ -6,7 +6,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[3.904 2017-05-30])
AC_INIT([Verilator],[3.906 2017-06-22])
# When releasing, also update header of Changes file
AC_CONFIG_HEADER(src/config_build.h)
+79 -37
View File
@@ -115,7 +115,7 @@ QData VL_RANDOM_Q(int obits) {
}
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) {
for (int i=0; i<VL_WORDS_I(obits); i++) {
for (int i=0; i<VL_WORDS_I(obits); ++i) {
if (i<(VL_WORDS_I(obits)-1)) {
outwp[i] = VL_RAND32();
} else {
@@ -146,7 +146,7 @@ QData VL_RAND_RESET_Q(int obits) {
}
WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) {
for (int i=0; i<VL_WORDS_I(obits); i++) {
for (int i=0; i<VL_WORDS_I(obits); ++i) {
if (i<(VL_WORDS_I(obits)-1)) {
outwp[i] = VL_RAND_RESET_I(32);
} else {
@@ -157,7 +157,7 @@ WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) {
}
WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) {
for (int i=0; i<VL_WORDS_I(obits); i++) outwp[i] = 0;
for (int i=0; i<VL_WORDS_I(obits); ++i) outwp[i] = 0;
return outwp;
}
@@ -166,7 +166,7 @@ WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) {
void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) {
VL_PRINTF(" Data: w%d: ", lbits);
for (int i=VL_WORDS_I(lbits)-1; i>=0; i--) { VL_PRINTF("%08x ",iwp[i]); }
for (int i=VL_WORDS_I(lbits)-1; i>=0; --i) { VL_PRINTF("%08x ",iwp[i]); }
VL_PRINTF("\n");
}
@@ -179,7 +179,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
// for debug see V3Number version
// Requires clean input
int words = VL_WORDS_I(lbits);
for (int i=0; i<words; i++) owp[i]=0;
for (int i=0; i<words; ++i) owp[i]=0;
// Find MSB and check for zero.
int umsbp1 = VL_MOSTSETBITP1_W(words,lwp); // dividend
int vmsbp1 = VL_MOSTSETBITP1_W(words,rwp); // divisor
@@ -193,14 +193,14 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
if (vw == 1) { // Single divisor word breaks rest of algorithm
vluint64_t k = 0;
for (int j = uw-1; j >= 0; j--) {
for (int j = uw-1; j >= 0; --j) {
vluint64_t unw64 = ((k<<VL_ULL(32)) + (vluint64_t)(lwp[j]));
owp[j] = unw64 / (vluint64_t)(rwp[0]);
k = unw64 - (vluint64_t)(owp[j])*(vluint64_t)(rwp[0]);
}
if (is_modulus) {
owp[0] = k;
for (int i=1; i<words; i++) owp[i]=0;
for (int i=1; i<words; ++i) owp[i]=0;
}
return owp;
}
@@ -211,13 +211,13 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
// Zero for ease of debugging and to save having to zero for shifts
// Note +1 as loop will use extra word
for (int i=0; i<words+1; i++) { un[i]=vn[i]=0; }
for (int i=0; i<words+1; ++i) { un[i]=vn[i]=0; }
// Algorithm requires divisor MSB to be set
// Copy and shift to normalize divisor so MSB of vn[vw-1] is set
int s = 31-VL_BITBIT_I(vmsbp1-1); // shift amount (0...31)
vluint32_t shift_mask = s ? 0xffffffff : 0; // otherwise >> 32 won't mask the value
for (int i = vw-1; i>0; i--) {
for (int i = vw-1; i>0; --i) {
vn[i] = (rwp[i] << s) | (shift_mask & (rwp[i-1] >> (32-s)));
}
vn[0] = rwp[0] << s;
@@ -225,13 +225,13 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
// Copy and shift dividend by same amount; may set new upper word
if (s) un[uw] = lwp[uw-1] >> (32-s);
else un[uw] = 0;
for (int i=uw-1; i>0; i--) {
for (int i=uw-1; i>0; --i) {
un[i] = (lwp[i] << s) | (shift_mask & (lwp[i-1] >> (32-s)));
}
un[0] = lwp[0] << s;
// Main loop
for (int j = uw - vw; j >= 0; j--) {
for (int j = uw - vw; j >= 0; --j) {
// Estimate
vluint64_t unw64 = ((vluint64_t)(un[j+vw])<<VL_ULL(32) | (vluint64_t)(un[j+vw-1]));
vluint64_t qhat = unw64 / (vluint64_t)(vn[vw-1]);
@@ -247,7 +247,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
vlsint64_t t = 0; // Must be signed
vluint64_t k = 0;
for (int i=0; i<vw; i++) {
for (int i=0; i<vw; ++i) {
vluint64_t p = qhat*vn[i]; // Multiply by estimate
t = un[i+j] - k - (p & VL_ULL(0xFFFFFFFF)); // Subtract
un[i+j] = t;
@@ -261,7 +261,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
// Over subtracted; correct by adding back
owp[j]--;
k = 0;
for (int i=0; i<vw; i++) {
for (int i=0; i<vw; ++i) {
t = (vluint64_t)(un[i+j]) + (vluint64_t)(vn[i]) + k;
un[i+j] = t;
k = t >> VL_ULL(32);
@@ -272,16 +272,58 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
if (is_modulus) { // modulus
// Need to reverse normalization on copy to output
for (int i=0; i<vw; i++) {
for (int i=0; i<vw; ++i) {
owp[i] = (un[i] >> s) | (shift_mask & (un[i+1] << (32-s)));
}
for (int i=vw; i<words; i++) owp[i] = 0;
for (int i=vw; i<words; ++i) owp[i] = 0;
return owp;
} else { // division
return owp;
}
}
WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp) {
owp[0] = 1;
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
// cppcheck-suppress variableScope
WData powstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
WData lastpowstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
WData lastoutstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope
VL_ASSIGN_W(obits, powstore, lwp);
for (int bit=0; bit<rbits; bit++) {
if (bit>0) { // power = power*power
VL_ASSIGN_W(obits, lastpowstore, powstore);
VL_MUL_W(VL_WORDS_I(obits), powstore, lastpowstore, lastpowstore);
}
if (VL_BITISSET_W(rwp,bit)) { // out *= power
VL_ASSIGN_W(obits, lastoutstore, owp);
VL_MUL_W(VL_WORDS_I(obits), owp, lastoutstore, powstore);
}
}
return owp;
}
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign) {
if (rsign && VL_SIGN_W(rbits, rwp)) {
int words = VL_WORDS_I(obits);
VL_ZERO_W(obits, owp);
IData lor = 0; // 0=all zeros, ~0=all ones, else mix
for (int i=1; i < (words-1); ++i) {
lor |= lwp[i];
}
lor |= ( (lwp[words-1] == VL_MASK_I(rbits)) ? ~VL_UL(0) : 0);
if (lor==0 && lwp[0]==0) { return owp; } // "X" so return 0
else if (lor==0 && lwp[0]==1) { owp[0] = 1; return owp; } // 1
else if (lsign && lor == ~VL_UL(0) && lwp[0]==~VL_UL(0)) { // -1
if (rwp[0] & 1) { return VL_ALLONES_W(obits, owp); } // -1^odd=-1
else { owp[0] = 1; return owp; } // -1^even=1
}
return 0;
}
return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
}
//===========================================================================
// Formatting
@@ -376,7 +418,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
if (fmt == 'd' || fmt == '#') fmt = 'x'; // Not supported, but show something
}
int lsb=lbits-1;
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) --lsb;
switch (fmt) {
case 'c': {
IData charval = ld & 0xff;
@@ -384,7 +426,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
break;
}
case 's':
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
output += (charval==0)?' ':charval;
@@ -433,13 +475,13 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
break;
}
case 'b':
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
}
break;
break;
case 'o':
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
lsb = (lsb / 3) * 3; // Next digit
// Octal numbers may span more than one wide word,
// so we need to grab each bit separately and check for overrun
@@ -452,7 +494,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
break;
case 'u': // Packed 2-state
output.reserve(output.size() + 4*VL_WORDS_I(lbits));
for (int i=0; i<VL_WORDS_I(lbits); i++) {
for (int i=0; i<VL_WORDS_I(lbits); ++i) {
output += (char)((lwp[i] >> 0) & 0xff);
output += (char)((lwp[i] >> 8) & 0xff);
output += (char)((lwp[i] >> 16) & 0xff);
@@ -460,7 +502,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
}
case 'z': // Packed 4-state
output.reserve(output.size() + 8*VL_WORDS_I(lbits));
for (int i=0; i<VL_WORDS_I(lbits); i++) {
for (int i=0; i<VL_WORDS_I(lbits); ++i) {
output += (char)((lwp[i] >> 0) & 0xff);
output += (char)((lwp[i] >> 8) & 0xff);
output += (char)((lwp[i] >> 16) & 0xff);
@@ -468,12 +510,12 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
output += "\0\0\0\0"; // No tristate
}
case 'v': // Strength; assume always strong
for (lsb=lbits-1; lsb>=0; lsb--) {
for (lsb=lbits-1; lsb>=0; --lsb) {
if ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) output += "St1 ";
else output += "St0 ";
}
case 'x':
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
lsb = (lsb / 4) * 4; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
output += "0123456789abcdef"[charval];
@@ -546,7 +588,7 @@ static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits,
static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, int posstart, int posend) {
// Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
int lsb = 0;
for (int i=0, pos=posend-1; i<obits && pos>=posstart; pos--) {
for (int i=0, pos=posend-1; i<obits && pos>=posstart; --pos) {
switch (tolower (strp[pos])) {
case 'x': case 'z': case '?': //FALLTHRU
case '0': lsb += baseLog2; break;
@@ -614,7 +656,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
if (obits > VL_QUADSIZE) {
owp = va_arg(ap,WDataOutP);
}
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;
switch (fmt) {
case 'c': {
int c = _vl_vsss_peek(fp,floc,fromp,fstr);
@@ -629,7 +671,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
if (!tmp[0]) goto done;
int pos = ((int)strlen(tmp))-1;
int lsb = 0;
for (int i=0; i<obits && pos>=0; pos--) {
for (int i=0; i<obits && pos>=0; --pos) {
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[pos]); lsb+=8;
}
break;
@@ -723,7 +765,7 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
int lsb=obits-1;
bool start=true;
char* destp = destoutp;
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (sourcep[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
if (!start || charval) {
@@ -741,8 +783,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
char* op = ((char*)(destp));
if (srclen > bytes) srclen = bytes; // Don't overflow destination
int i;
for (i=0; i<srclen; i++) { *op++ = srcp[srclen-1-i]; }
for (; i<bytes; i++) { *op++ = 0; }
for (i=0; i<srclen; ++i) { *op++ = srcp[srclen-1-i]; }
for (; i<bytes; ++i) { *op++ = 0; }
}
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
@@ -779,7 +821,7 @@ IData VL_FOPEN_NI(const string& filename, IData mode) {
return VL_FOPEN_S(filename.c_str(), modez);
}
IData VL_FOPEN_QI(QData filename, IData mode) {
IData fnw[2]; VL_SET_WQ(fnw, filename);
WData fnw[2]; VL_SET_WQ(fnw, filename);
return VL_FOPEN_WI(2, fnw, mode);
}
IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
@@ -913,7 +955,7 @@ IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
}
IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) {
IData fnw[2]; VL_SET_WI(fnw, ld);
WData fnw[2]; VL_SET_WI(fnw, ld);
va_list ap;
va_start(ap,formatp);
@@ -922,7 +964,7 @@ IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) {
return got;
}
IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) {
IData fnw[2]; VL_SET_WQ(fnw, ld);
WData fnw[2]; VL_SET_WQ(fnw, ld);
va_list ap;
va_start(ap,formatp);
@@ -947,7 +989,7 @@ IData VL_SSCANF_INX(int, const string& ld, const char* formatp, ...) {
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
QData ofilename, void* memp, IData start, IData end) {
IData fnw[2]; VL_SET_WQ(fnw, ofilename);
WData fnw[2]; VL_SET_WQ(fnw, ofilename);
return VL_READMEM_W(hex,width,depth,array_lsb,2, fnw,memp,start,end);
}
@@ -1060,7 +1102,7 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
}
IData VL_SYSTEM_IQ(QData lhs) {
IData lhsw[2]; VL_SET_WQ(lhsw, lhs);
WData lhsw[2]; VL_SET_WQ(lhsw, lhs);
return VL_SYSTEM_IW(2, lhsw);
}
IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
@@ -1122,7 +1164,7 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const string& ld, WDataOutP rwp) {
_vl_vsss_based(rwp,rbits, 4, dp, 0, (int)strlen(dp));
break;
case 's': // string/no conversion
for (int i=0, lsb=0, posp=((int)strlen(dp))-1; i<rbits && posp>=0; posp--) {
for (int i=0, lsb=0, posp=((int)strlen(dp))-1; i<rbits && posp>=0; --posp) {
_vl_vsss_setbit(rwp,rbits,lsb, 8, dp[posp]); lsb+=8;
}
break;
@@ -1184,7 +1226,7 @@ string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) {
bool start=true;
char* destp = destout;
int len = 0;
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
if (!start || charval) {
@@ -1403,7 +1445,7 @@ void* VerilatedScope::exportFindError(int funcnum) const {
void VerilatedScope::scopeDump() const {
VL_PRINTF(" SCOPE %p: %s\n", this, name());
for (int i=0; i<m_funcnumMax; i++) {
for (int i=0; i<m_funcnumMax; ++i) {
if (m_callbacksp && m_callbacksp[i]) {
VL_PRINTF(" DPI-EXPORT %p: %s\n",
m_callbacksp[i], VerilatedImp::exportName(i));
+184 -101
View File
@@ -349,7 +349,7 @@ extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signa
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal (slow - else use VL_ZERO_W)
/// Math
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
@@ -398,7 +398,7 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
//=========================================================================
// Base macros
/// Return true if data[bit] set
/// Return true if data[bit] set; not 0/1 return, but 0/non-zero return.
#define VL_BITISSET_I(data,bit) (data & (VL_UL(1)<<VL_BITBIT_I(bit)))
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
@@ -433,6 +433,7 @@ static inline IData VL_RTOIROUND_I_D(double lhs) { return ((vlsint32_t)(VL_ROUN
// (Requires clean input)
#define VL_SIGN_I(nbits,lhs) ((lhs) >> VL_BITBIT_I((nbits) - VL_UL(1)))
#define VL_SIGN_Q(nbits,lhs) ((lhs) >> VL_BITBIT_Q((nbits) - VL_ULL(1)))
#define VL_SIGN_W(nbits,rwp) ((rwp)[VL_BITWORD_I((nbits)-VL_UL(1))] >> VL_BITBIT_I((nbits)-VL_UL(1)))
#define VL_SIGNONES_I(nbits,lhs) (-(VL_SIGN_I(nbits,lhs)))
// Sign bit extended up to MSB, doesn't include unsigned portion
@@ -504,17 +505,28 @@ static inline WDataOutP _VL_CLEAN_INPLACE_W(int obits, WDataOutP owp) {
}
static inline WDataOutP VL_CLEAN_WW(int obits, int, WDataOutP owp, WDataInP lwp){
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);
return(owp);
}
static inline WDataOutP VL_ZERO_W(int obits, WDataOutP owp) {
int words = VL_WORDS_I(obits);
for (int i=0; i < words; ++i) owp[i] = 0;
return owp;
}
static inline WDataOutP VL_ALLONES_W(int obits, WDataOutP owp) {
int words = VL_WORDS_I(obits);
for (int i=0; (i < (words-1)); ++i) owp[i] = ~VL_UL(0);
owp[words-1] = VL_MASK_I(obits);
return owp;
}
// EMIT_RULE: VL_ASSIGN: oclean=rclean; obits==lbits;
// For now, we always have a clean rhs.
// Note: If a ASSIGN isn't clean, use VL_ASSIGNCLEAN instead to do the same thing.
static inline WDataOutP VL_ASSIGN_W(int obits, WDataOutP owp,WDataInP lwp){
int words = VL_WORDS_I(obits);
for (int i=0; i < words; i++) owp[i] = lwp[i];
for (int i=0; i < words; ++i) owp[i] = lwp[i];
return(owp);
}
@@ -575,7 +587,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
}
#define VL_ASSIGN_WSW(obits,owp,svar) { \
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); \
}
@@ -584,7 +596,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
#define VL_ASSIGN_WSB(obits,owp,svar) { \
int words = VL_WORDS_I(obits); \
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; \
msb = (msb >= obits) ? (obits-1) : msb; \
owp[i] = _butemp.range(msb,i*VL_WORDSIZE).to_uint(); \
@@ -611,7 +623,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
}
#define VL_ASSIGN_SWW(obits,svar,rwp) { \
sc_bv<obits> _bvtemp; \
for (int i=0; i < VL_WORDS_I(obits); i++) _bvtemp.set_word(i,rwp[i]); \
for (int i=0; i < VL_WORDS_I(obits); ++i) _bvtemp.set_word(i,rwp[i]); \
svar.write(_bvtemp); \
}
@@ -621,7 +633,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
#define VL_ASSIGN_SBQ(obits,svar,rd) { (svar).write(rd); }
#define VL_ASSIGN_SBW(obits,svar,rwp) { \
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; \
msb = (msb >= obits) ? (obits-1) : msb; \
_butemp.range(msb,i*VL_WORDSIZE) = rwp[i]; \
@@ -643,17 +655,17 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
static inline WDataOutP VL_EXTEND_WI(int obits, int, WDataOutP owp, IData ld) {
// Note for extracts that obits != lbits
owp[0] = ld;
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
return(owp);
}
static inline WDataOutP VL_EXTEND_WQ(int obits, int, WDataOutP owp, QData ld) {
VL_SET_WQ(owp,ld);
for (int i=2; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
return(owp);
}
static inline WDataOutP VL_EXTEND_WW(int obits, int lbits, WDataOutP owp, WDataInP lwp) {
for (int i=0; i < VL_WORDS_I(lbits); i++) owp[i] = lwp[i];
for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
return(owp);
}
@@ -672,22 +684,22 @@ static inline QData VL_EXTENDS_QQ(int, int lbits, QData lhs) {
static inline WDataOutP VL_EXTENDS_WI(int obits, int lbits, WDataOutP owp, IData ld) {
IData sign = VL_SIGNONES_I(lbits,ld);
owp[0] = ld | (sign & ~VL_MASK_I(lbits));
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = sign;
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
return(owp);
}
static inline WDataOutP VL_EXTENDS_WQ(int obits, int lbits, WDataOutP owp, QData ld) {
VL_SET_WQ(owp,ld);
IData sign = VL_SIGNONES_I(lbits,owp[1]);
owp[1] |= sign & ~VL_MASK_I(lbits);
for (int i=2; i < VL_WORDS_I(obits); i++) owp[i] = sign;
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
return(owp);
}
static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp, WDataInP lwp) {
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;
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
owp[lmsw] = lwp[lmsw] | (sign & ~VL_MASK_I(lbits));
for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); i++) owp[i] = sign;
for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); ++i) owp[i] = sign;
return(owp);
}
@@ -700,7 +712,7 @@ static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp, WData
static inline IData VL_REDAND_IW(int, int lbits, WDataInP lwp) {
int words = VL_WORDS_I(lbits);
IData 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];
return ((~combine)==0);
}
@@ -710,7 +722,7 @@ static inline IData VL_REDAND_IW(int, int lbits, WDataInP lwp) {
#define VL_REDOR_Q(lhs) (lhs!=0)
static inline IData VL_REDOR_W(int words, WDataInP lwp) {
IData 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);
}
@@ -762,7 +774,7 @@ static inline IData VL_REDXOR_64(QData r) {
}
static inline IData VL_REDXOR_W(int words, WDataInP lwp) {
IData 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);
}
@@ -780,7 +792,7 @@ static inline IData VL_COUNTONES_Q(QData lhs) {
}
static inline IData VL_COUNTONES_W(int words, WDataInP lwp) {
IData 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_I(lwp[i]);
return r;
}
@@ -792,7 +804,7 @@ static inline IData VL_ONEHOT_Q(QData lhs) {
}
static inline IData VL_ONEHOT_W(int words, WDataInP lwp) {
IData one=0;
for (int i=0; (i < words); i++) {
for (int i=0; (i < words); ++i) {
if (lwp[i]) {
if (one) return 0;
one = 1;
@@ -810,7 +822,7 @@ static inline IData VL_ONEHOT0_Q(QData lhs) {
}
static inline IData VL_ONEHOT0_W(int words, WDataInP lwp) {
bool one=false;
for (int i=0; (i < words); i++) {
for (int i=0; (i < words); ++i) {
if (lwp[i]) {
if (one) return 0;
one = true;
@@ -825,21 +837,21 @@ static inline IData VL_CLOG2_I(IData lhs) {
if (VL_UNLIKELY(!lhs)) return 0;
lhs--;
int shifts=0;
for (; lhs!=0; shifts++) lhs = lhs >> 1;
for (; lhs!=0; ++shifts) lhs = lhs >> 1;
return shifts;
}
static inline IData VL_CLOG2_Q(QData lhs) {
if (VL_UNLIKELY(!lhs)) return 0;
lhs--;
int shifts=0;
for (; lhs!=0; shifts++) lhs = lhs >> VL_ULL(1);
for (; lhs!=0; ++shifts) lhs = lhs >> VL_ULL(1);
return shifts;
}
static inline IData VL_CLOG2_W(int words, WDataInP lwp) {
IData 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
for (int bit=31; bit>=0; bit--) {
for (int bit=31; bit>=0; --bit) {
if (VL_UNLIKELY(VL_BITISSET_I(lwp[i],bit))) {
return i*VL_WORDSIZE + bit + adjust;
}
@@ -852,9 +864,9 @@ static inline IData VL_CLOG2_W(int words, WDataInP lwp) {
static inline IData VL_MOSTSETBITP1_W(int words, WDataInP lwp) {
// 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
for (int bit=31; bit>=0; bit--) {
for (int bit=31; bit>=0; --bit) {
if (VL_UNLIKELY(VL_BITISSET_I(lwp[i],bit))) {
return i*VL_WORDSIZE + bit + 1;
}
@@ -870,33 +882,33 @@ static inline IData VL_MOSTSETBITP1_W(int words, WDataInP lwp) {
// EMIT_RULE: VL_AND: oclean=lclean||rclean; obits=lbits; lbits==rbits;
static inline WDataOutP VL_AND_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
for (int i=0; (i < words); i++) owp[i] = (lwp[i] & rwp[i]);
for (int i=0; (i < words); ++i) owp[i] = (lwp[i] & rwp[i]);
return(owp);
}
// EMIT_RULE: VL_OR: oclean=lclean&&rclean; obits=lbits; lbits==rbits;
static inline WDataOutP VL_OR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
for (int i=0; (i < words); i++) owp[i] = (lwp[i] | rwp[i]);
for (int i=0; (i < words); ++i) owp[i] = (lwp[i] | rwp[i]);
return(owp);
}
// EMIT_RULE: VL_CHANGEXOR: oclean=1; obits=32; lbits==rbits;
static inline IData VL_CHANGEXOR_W(int words, WDataInP lwp,WDataInP rwp){
IData od = 0;
for (int i=0; (i < words); i++) od |= (lwp[i] ^ rwp[i]);
for (int i=0; (i < words); ++i) od |= (lwp[i] ^ rwp[i]);
return(od);
}
// EMIT_RULE: VL_XOR: oclean=lclean&&rclean; obits=lbits; lbits==rbits;
static inline WDataOutP VL_XOR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
for (int i=0; (i < words); i++) owp[i] = (lwp[i] ^ rwp[i]);
for (int i=0; (i < words); ++i) owp[i] = (lwp[i] ^ rwp[i]);
return(owp);
}
// EMIT_RULE: VL_XNOR: oclean=dirty; obits=lbits; lbits==rbits;
static inline WDataOutP VL_XNOR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
for (int i=0; (i < words); i++) owp[i] = (lwp[i] ^ ~rwp[i]);
for (int i=0; (i < words); ++i) owp[i] = (lwp[i] ^ ~rwp[i]);
return(owp);
}
// EMIT_RULE: VL_NOT: oclean=dirty; obits=lbits;
static inline WDataOutP VL_NOT_W(int words, WDataOutP owp,WDataInP lwp) {
for (int i=0; i < words; i++) owp[i] = ~(lwp[i]);
for (int i=0; i < words; ++i) owp[i] = ~(lwp[i]);
return(owp);
}
@@ -918,7 +930,7 @@ static inline WDataOutP VL_NOT_W(int words, WDataOutP owp,WDataInP lwp) {
// Output clean, <lhs> AND <rhs> MUST BE CLEAN
static inline IData VL_EQ_W(int words, WDataInP lwp, WDataInP rwp) {
int 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);
}
@@ -1012,7 +1024,7 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) {
static inline WDataOutP VL_ADD_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
QData carry = 0;
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
carry = carry + (QData)(lwp[i]) + (QData)(rwp[i]);
owp[i] = (carry & VL_ULL(0xffffffff));
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
@@ -1022,7 +1034,7 @@ static inline WDataOutP VL_ADD_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
QData carry = 0;
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
carry = carry + (QData)(lwp[i]) + (QData)(IData)(~rwp[i]);
if (i==0) carry++; // Negation of temp2
owp[i] = (carry & VL_ULL(0xffffffff));
@@ -1039,7 +1051,7 @@ static inline QData VL_NEGATE_Q(QData data) { return -data; }
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
QData carry = 0;
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
carry = carry + (QData)(IData)(~lwp[i]);
if (i==0) carry++; // Negation of temp2
owp[i] = (carry & VL_ULL(0xffffffff));
@@ -1049,11 +1061,11 @@ static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
}
static inline WDataOutP VL_MUL_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
for (int i=0; i<words; i++) owp[i] = 0;
for (int lword=0; lword<words; lword++) {
for (int rword=0; rword<words; rword++) {
for (int i=0; i<words; ++i) owp[i] = 0;
for (int lword=0; lword<words; ++lword) {
for (int rword=0; rword<words; ++rword) {
QData mul = (QData)(lwp[lword]) * (QData)(rwp[rword]);
for (int qword=lword+rword; qword<words; qword++) {
for (int qword=lword+rword; qword<words; ++qword) {
mul += (QData)(owp[qword]);
owp[qword] = (mul & VL_ULL(0xffffffff));
mul = (mul >> VL_ULL(32)) & VL_ULL(0xffffffff);
@@ -1078,9 +1090,9 @@ static inline QData VL_MULS_QQQ(int,int lbits,int, QData lhs,QData rhs) {
static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lwp,WDataInP rwp){
int words = VL_WORDS_I(lbits);
// cppcheck-suppress variableScope
IData 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
IData rwstore[VL_MULS_MAX_WORDS];
WData rwstore[VL_MULS_MAX_WORDS];
WDataInP lwusp = lwp;
WDataInP rwusp = rwp;
IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
@@ -1099,7 +1111,7 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
QData carry = 0;
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
carry = carry + (QData)(IData)(~owp[i]);
if (i==0) carry++; // Negation of temp2
owp[i] = (carry & VL_ULL(0xffffffff));
@@ -1141,9 +1153,9 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
IData lsign = VL_SIGN_I(lbits,lwp[words-1]);
IData rsign = VL_SIGN_I(lbits,rwp[words-1]);
// cppcheck-suppress variableScope
IData 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
IData rwstore[VL_MULS_MAX_WORDS];
WData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp;
WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
@@ -1162,15 +1174,15 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
IData lsign = VL_SIGN_I(lbits,lwp[words-1]);
IData rsign = VL_SIGN_I(lbits,rwp[words-1]);
// cppcheck-suppress variableScope
IData 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
IData rwstore[VL_MULS_MAX_WORDS];
WData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp;
WDataInP rtup = rwp;
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 (lsign) { // Only dividend sign matters for modulus
IData qNoSign[VL_MULS_MAX_WORDS];
WData qNoSign[VL_MULS_MAX_WORDS];
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
return owp;
@@ -1186,7 +1198,7 @@ static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) {
if (VL_UNLIKELY(lhs==0)) return 0;
IData power = lhs;
IData out = 1;
for (int i=0; i<rbits; i++) {
for (int i=0; i<rbits; ++i) {
if (i>0) power = power*power;
if (rhs & (VL_ULL(1)<<i)) out *= power;
}
@@ -1197,12 +1209,13 @@ static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
if (VL_UNLIKELY(lhs==0)) return 0;
QData power = lhs;
QData out = VL_ULL(1);
for (int i=0; i<rbits; i++) {
for (int i=0; i<rbits; ++i) {
if (i>0) power = power*power;
if (rhs & (VL_ULL(1)<<i)) out *= power;
}
return out;
}
WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp);
#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
@@ -1211,28 +1224,28 @@ static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs
if (rsign && VL_SIGN_I(rbits, rhs)) {
if (lhs==0) return 0; // "X"
else if (lhs==1) return 1;
else if (lsign && lhs==VL_MASK_I(obits)) { //-1
else if (lsign && lhs==VL_MASK_I(obits)) { // -1
if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
else return 1; // -1^even=1
}
return 0;
}
return VL_POW_III(obits, obits, rbits, lhs, rhs);
return VL_POW_III(obits, rbits, rbits, lhs, rhs);
}
static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs, bool lsign, bool rsign) {
if (VL_UNLIKELY(rhs==0)) return 1;
if (rsign && VL_SIGN_I(rbits, rhs)) {
if (lhs==0) return 0; // "X"
else if (lhs==1) return 1;
else if (lsign && lhs==VL_MASK_I(obits)) { //-1
else if (lsign && lhs==VL_MASK_I(obits)) { // -1
if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
else return 1; // -1^even=1
}
return 0;
}
return VL_POW_QQQ(obits, obits, rbits, lhs, rhs);
return VL_POW_QQQ(obits, rbits, rbits, lhs, rhs);
}
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign);
//===================================================================
// Concat/replication
@@ -1287,13 +1300,13 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
int words = VL_WORDS_I(hbit-lbit+1);
if (hoffset==VL_SIZEBITS_I && loffset==0) {
// Fast and common case, word based insertion
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
owp[lword+i] = lwp[i];
}
}
else if (loffset==0) {
// Non-32bit, but nicely aligned, so stuff all but the last word
for (int i=0; i<(words-1); i++) {
for (int i=0; i<(words-1); ++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
@@ -1305,7 +1318,7 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int hword = VL_BITWORD_I(hbit);
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
{ // Lower word
int oword = lword+i;
IData d = lwp[i]<<loffset;
@@ -1338,7 +1351,7 @@ static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit, i
static inline IData VL_REPLICATE_III(int, int lbits, int, IData ld, IData rep) {
IData returndata = ld;
for (unsigned i=1; i < rep; i++){
for (unsigned i=1; i < rep; ++i){
returndata = returndata << lbits;
returndata |= ld;
}
@@ -1346,7 +1359,7 @@ static inline IData VL_REPLICATE_III(int, int lbits, int, IData ld, IData rep) {
}
static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) {
QData returndata = ld;
for (unsigned i=1; i < rep; i++){
for (unsigned i=1; i < rep; ++i){
returndata = returndata << lbits;
returndata |= (QData)ld;
}
@@ -1354,21 +1367,21 @@ static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) {
}
static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int, WDataOutP owp, IData ld, IData rep) {
owp[0] = ld;
for (unsigned i=1; i < rep; i++){
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WI(obits,owp,ld,i*lbits+lbits-1,i*lbits);
}
return(owp);
}
static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int, WDataOutP owp, QData ld, IData rep) {
VL_SET_WQ(owp,ld);
for (unsigned i=1; i < rep; i++){
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WQ(obits,owp,ld,i*lbits+lbits-1,i*lbits);
}
return(owp);
}
static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP owp, WDataInP lwp, IData rep) {
for (int i=0; i < VL_WORDS_I(lbits); i++) owp[i] = lwp[i];
for (unsigned i=1; i < rep; i++){
for (int i=0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WW(obits,owp,lwp,i*lbits+lbits-1,i*lbits);
}
return(owp);
@@ -1472,13 +1485,13 @@ static inline QData VL_STREAML_QQI(int, int lbits, int, QData ld, IData rd) {
}
static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WDataInP lwp, IData rd) {
VL_ZERO_RESET_W(lbits, owp);
VL_ZERO_W(lbits, owp);
// Slice size should never exceed the lhs width
int ssize = (rd < (IData)lbits) ? rd : ((IData)lbits);
for (int istart=0; istart<lbits; istart+=rd) {
int ostart=lbits-rd-istart;
ostart = ostart > 0 ? ostart : 0;
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
// location for owp.
WData bit= ((lwp[VL_BITWORD_I(istart+sbit)] >> VL_BITBIT_I(istart+sbit)) & 1) << VL_BITBIT_I(ostart+sbit);
@@ -1500,55 +1513,55 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData
static inline WDataOutP VL_CONCAT_WII(int obits,int lbits,int rbits,WDataOutP owp,IData ld,IData rd) {
owp[0] = rd;
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;
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WWI(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, IData rd) {
owp[0] = rd;
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;
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WIW(int obits,int lbits,int rbits,WDataOutP owp,IData ld, WDataInP rwp) {
for (int i=0; i < VL_WORDS_I(rbits); i++) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WIQ(int obits,int lbits,int rbits,WDataOutP owp,IData ld,QData rd) {
VL_SET_WQ(owp,rd);
for (int i=2; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WQI(int obits,int lbits,int rbits,WDataOutP owp,QData ld,IData rd) {
owp[0] = rd;
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;
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WQQ(int obits,int lbits,int rbits,WDataOutP owp,QData ld,QData rd) {
VL_SET_WQ(owp,rd);
for (int i=2; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WWQ(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, QData rd) {
VL_SET_WQ(owp,rd);
for (int i=2; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WQW(int obits,int lbits,int rbits,WDataOutP owp,QData ld, WDataInP rwp) {
for (int i=0; i < VL_WORDS_I(rbits); i++) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=0; i < VL_WORDS_I(rbits); i++) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
return(owp);
}
@@ -1561,7 +1574,7 @@ static inline WDataOutP VL_CONCAT_WWW(int obits,int lbits,int rbits,WDataOutP ow
static inline void _VL_SHIFTL_INPLACE_W(int obits,WDataOutP iowp,IData rd/*1 or 4*/) {
int words = VL_WORDS_I(obits);
IData linsmask = VL_MASK_I(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[0] = ((iowp[0]<<rd) & ~linsmask);
@@ -1575,16 +1588,32 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l
int word_shift = VL_BITWORD_I(rd);
int bit_shift = VL_BITBIT_I(rd);
if (rd >= (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)
for (int i=0; i < word_shift; i++) owp[i] = 0;
for (int i=word_shift; i < VL_WORDS_I(obits); i++) owp[i] = lwp[i-word_shift];
for (int i=0; i < word_shift; ++i) owp[i] = 0;
for (int i=word_shift; i < VL_WORDS_I(obits); ++i) owp[i] = lwp[i-word_shift];
} else {
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits,owp,lwp,obits-1,rd);
}
return(owp);
}
static inline WDataOutP VL_SHIFTL_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return VL_ZERO_W(obits, owp);
}
}
return VL_SHIFTL_WWI(obits,lbits,32,owp,lwp,rwp[0]);
}
static inline IData VL_SHIFTL_IIW(int obits,int,int rbits,IData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
}
return VL_CLEAN_II(obits,obits,lhs<<rwp[0]);
}
// EMIT_RULE: VL_SHIFTR: oclean=lclean; rclean==clean;
// Important: Unlike most other funcs, the shift might well be a computed
@@ -1593,27 +1622,43 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP l
int word_shift = VL_BITWORD_I(rd); // Maybe 0
int bit_shift = VL_BITBIT_I(rd);
if (rd >= (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)
int copy_words = (VL_WORDS_I(obits)-word_shift);
for (int i=0; i < copy_words; i++) owp[i] = lwp[i+word_shift];
for (int i=copy_words; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift];
for (int i=copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
} else {
int loffset = rd & VL_SIZEBITS_I;
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int words = VL_WORDS_I(obits-rd);
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
owp[i] = lwp[i+word_shift]>>loffset;
int upperword = i+word_shift+1;
if (upperword < VL_WORDS_I(obits)) {
owp[i] |= lwp[upperword]<< nbitsonright;
}
}
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;
}
return(owp);
}
static inline WDataOutP VL_SHIFTR_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return VL_ZERO_W(obits, owp);
}
}
return VL_SHIFTR_WWI(obits,lbits,32,owp,lwp,rwp[0]);
}
static inline IData VL_SHIFTR_IIW(int obits,int,int rbits,IData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
}
return VL_CLEAN_II(obits,obits,lhs>>rwp[0]);
}
// EMIT_RULE: VL_SHIFTRS: oclean=false; lclean=clean, rclean==clean;
static inline IData VL_SHIFTRS_III(int obits, int lbits, int, IData lhs, IData rhs) {
@@ -1639,20 +1684,20 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa
int lmsw = VL_WORDS_I(obits)-1;
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
if (rd >= (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);
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
int copy_words = (VL_WORDS_I(obits)-word_shift);
for (int i=0; i < copy_words; i++) owp[i] = lwp[i+word_shift];
for (int i=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift];
if (copy_words>=0) owp[copy_words-1] |= ~VL_MASK_I(obits) & sign;
for (int i=copy_words; i < VL_WORDS_I(obits); i++) owp[i] = sign;
for (int i=copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
} else {
int loffset = rd & VL_SIZEBITS_I;
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int words = VL_WORDS_I(obits-rd);
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
owp[i] = lwp[i+word_shift]>>loffset;
int upperword = i+word_shift+1;
if (upperword < VL_WORDS_I(obits)) {
@@ -1660,11 +1705,49 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa
}
}
if (words) owp[words-1] |= sign & ~VL_MASK_I(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);
}
return(owp);
}
static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
int lmsw = VL_WORDS_I(obits)-1;
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
for (int i=0; i <= lmsw; ++i) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
return owp;
}
}
return VL_SHIFTRS_WWI(obits,lbits,32,owp,lwp,rwp[0]);
}
static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
return VL_CLEAN_II(obits,obits,sign);
}
}
return VL_SHIFTRS_III(obits,lbits,32,lhs,rwp[0]);
}
static inline QData VL_SHIFTRS_QQW(int obits,int lbits,int rbits,QData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
QData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
return VL_CLEAN_QQ(obits,obits,sign);
}
}
return VL_SHIFTRS_QQI(obits,lbits,32,lhs,rwp[0]);
}
static inline IData VL_SHIFTRS_IIQ(int obits,int lbits,int rbits,IData lhs, QData rhs) {
WData rwp[2]; VL_SET_WQ(rwp,rhs);
return VL_SHIFTRS_IIW(obits,lbits,rbits,lhs,rwp);
}
static inline QData VL_SHIFTRS_QQQ(int obits,int lbits,int rbits,QData lhs, QData rhs) {
WData rwp[2]; VL_SET_WQ(rwp,rhs);
return VL_SHIFTRS_QQW(obits,lbits,rbits,lhs,rwp);
}
//===================================================================
// Bit selection
@@ -1730,25 +1813,25 @@ static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WD
int msb = lsb+width-1;
int word_shift = VL_BITWORD_I(lsb);
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);
} else if (VL_BITBIT_I(lsb)==0) {
// 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 {
// Not a _VL_INSERT because the bits come from any bit number and goto bit 0
int loffset = lsb & VL_SIZEBITS_I;
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
// Middle words
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;
int upperword = i+word_shift+1;
if (upperword <= (int)VL_BITWORD_I(msb)) {
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;
}
return owp;
}
@@ -1793,7 +1876,7 @@ static inline void VL_ASSIGNSEL_WIIW(int obits, int lsb, WDataOutP owp, WDataInP
static inline WDataOutP VL_COND_WIWW(int obits, int, int, int,
WDataOutP owp, int cond, WDataInP w1p, WDataInP w2p) {
int words = VL_WORDS_I(obits);
for (int i=0; i < words; i++) owp[i] = cond ? w1p[i] : w2p[i];
for (int i=0; i < words; ++i) owp[i] = cond ? w1p[i] : w2p[i];
return(owp);
}
@@ -1826,7 +1909,7 @@ inline IData VL_VALUEPLUSARGS_II(int rbits, const char* prefixp, char fmt, IData
// If changing the number of functions here, also change EMITCINLINES_NUM_CONSTW
#define _END(obits,wordsSet) \
for(int i=(wordsSet);i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0; \
for(int i=(wordsSet);i<VL_WORDS_I(obits);++i) o[i] = (IData)0x0; \
return o
#define VL_HAVE_CONST_W_1X
+8 -8
View File
@@ -50,7 +50,7 @@ public: // But only local to this file
// CONSTRUCTORS
// Derived classes should call zero() in their constructor
VerilatedCovImpItem() {
for (int i=0; i<MAX_KEYS; i++) {
for (int i=0; i<MAX_KEYS; ++i) {
m_keys[i]=KEY_UNDEF;
m_vals[i]=0;
}
@@ -130,7 +130,7 @@ private:
string dequote(const string& text) {
// Quote any special characters
string rtn;
for (const char* pos = text.c_str(); *pos; pos++) {
for (const char* pos = text.c_str(); *pos; ++pos) {
if (!isprint(*pos) || *pos=='%' || *pos=='"') {
char hex[10]; sprintf(hex,"%%%02X",pos[0]);
rtn += hex;
@@ -194,7 +194,7 @@ private:
return out;
}
bool itemMatchesString(VerilatedCovImpItem* itemp, const string& match) {
for (int i=0; i<MAX_KEYS; i++) {
for (int i=0; i<MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) {
// We don't compare keys, only values
string val = m_indexValues[itemp->m_vals[i]];
@@ -274,15 +274,15 @@ public:
// Keys -> strings
string keys[MAX_KEYS];
for (int i=0; i<MAX_KEYS; i++) {
for (int i=0; i<MAX_KEYS; ++i) {
if (ckeyps[i] && ckeyps[i][0]) {
keys[i] = ckeyps[i];
}
}
// Ignore empty keys
for (int i=0; i<MAX_KEYS; i++) {
for (int i=0; i<MAX_KEYS; ++i) {
if (keys[i]!="") {
for (int j=i+1; j<MAX_KEYS; j++) {
for (int j=i+1; j<MAX_KEYS; ++j) {
if (keys[i] == keys[j]) { // Duplicate key. Keep the last one
keys[i] = "";
break;
@@ -292,7 +292,7 @@ public:
}
// Insert the values
int addKeynum=0;
for (int i=0; i<MAX_KEYS; i++) {
for (int i=0; i<MAX_KEYS; ++i) {
const string key = keys[i];
if (keys[i]!="") {
const string val = valps[i];
@@ -334,7 +334,7 @@ public:
string hier;
bool per_instance = false;
for (int i=0; i<MAX_KEYS; i++) {
for (int i=0; i<MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) {
string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
string val = m_indexValues[itemp->m_vals[i]];
+2 -2
View File
@@ -60,9 +60,9 @@ using namespace std;
///
/// vluint32_t m_cases[10];
/// constructor {
/// for (int i=0; i<10; i++) { m_cases[i]=0; }
/// for (int i=0; i<10; ++i) { m_cases[i]=0; }
/// }
/// for (int i=0; i<10; i++) {
/// for (int i=0; i<10; ++i) {
/// VL_COVER_INSERT(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
/// }
+5 -5
View File
@@ -37,25 +37,25 @@
/// Return svBitVecVal from WData
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) {
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);
}
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) {
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);
}
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) {
// Note we ignore X/Z in svLogicVecVal
int words = VL_WORDS_I(obits);
for (int i=0; i<words-1; i++) owp[i]=lwp[i].aval;
for (int i=0; i<words-1; ++i) owp[i]=lwp[i].aval;
owp[words-1] = lwp[words-1].aval & VL_MASK_I(obits);
}
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) {
// Note we don't create X/Z in svLogicVecVal
int words = VL_WORDS_I(obits);
for (int i=0; i<words; i++) owp[i].bval=0;
for (int i=0; i<words-1; i++) owp[i].aval=lwp[i];
for (int i=0; i<words; ++i) owp[i].bval=0;
for (int i=0; i<words-1; ++i) owp[i].aval=lwp[i];
owp[words-1].aval = lwp[words-1] & VL_MASK_I(obits);
}
+5 -5
View File
@@ -38,14 +38,14 @@
extern string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp);
inline string VL_CVT_PACK_STR_NQ(QData lhs) {
IData lw[2]; VL_SET_WQ(lw, lhs);
WData lw[2]; VL_SET_WQ(lw, lhs);
return VL_CVT_PACK_STR_NW(2, lw);
}
inline string VL_CVT_PACK_STR_NN(const string& lhs) {
return lhs;
}
inline string VL_CVT_PACK_STR_NI(IData lhs) {
IData lw[1]; lw[0] = lhs;
WData lw[1]; lw[0] = lhs;
return VL_CVT_PACK_STR_NW(1, lw);
}
inline string VL_CONCATN_NNN(const string& lhs, const string& rhs) {
@@ -53,7 +53,7 @@ inline string VL_CONCATN_NNN(const string& lhs, const string& rhs) {
}
inline string VL_REPLICATEN_NNQ(int,int,int, const string& lhs, IData rep) {
string out; out.reserve(lhs.length() * rep);
for (unsigned times=0; times<rep; times++) out += lhs;
for (unsigned times=0; times<rep; ++times) out += lhs;
return out;
}
inline string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const string& lhs, IData rep) {
@@ -68,13 +68,13 @@ extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp,
extern string VL_SFORMATF_NX(const char* formatp, ...);
extern IData VL_VALUEPLUSARGS_INW(int rbits, const string& ld, WDataOutP rdp);
inline IData VL_VALUEPLUSARGS_INI(int rbits, const string& ld, IData& rdr) {
IData rwp[1];
WData rwp[1];
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
if (got) rdr = rwp[0];
return got;
}
inline IData VL_VALUEPLUSARGS_INQ(int rbits, const string& ld, QData& rdr) {
IData rwp[2];
WData rwp[2];
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
if (got) rdr = VL_SET_QW(rwp);
return got;
+2 -2
View File
@@ -97,7 +97,7 @@ public: // But only for verilated*.cpp
}
static void commandArgsAdd(int argc, const char** argv) {
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
for (int i=0; i<argc; i++) s_s.m_argVec.push_back(argv[i]);
for (int i=0; i<argc; ++i) s_s.m_argVec.push_back(argv[i]);
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
}
static string argPlusMatch(const char* prefixp) {
@@ -238,7 +238,7 @@ public: // But only for verilated*.cpp
// Need to create more space in m_fdps and m_fdFree
size_t start = s_s.m_fdps.size();
s_s.m_fdps.resize(start*2);
for (size_t i=start; i<start*2; i++) s_s.m_fdFree.push_back((IData)i);
for (size_t i=start; i<start*2; ++i) s_s.m_fdFree.push_back((IData)i);
}
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
s_s.m_fdps[idx] = fp;
+9
View File
@@ -428,6 +428,15 @@ public:
void dump (double timestamp) { dump((vluint64_t)timestamp); }
void dump (vluint32_t timestamp) { dump((vluint64_t)timestamp); }
void dump (int timestamp) { dump((vluint64_t)timestamp); }
/// Set time units (s/ms, defaults to ns)
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
void set_time_unit (const char* unit) { m_sptrace.set_time_unit(unit); }
void set_time_unit (const string& unit) { set_time_unit(unit.c_str()); }
/// Set time resolution (s/ms, defaults to ns)
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
void set_time_resolution (const char* unit) { m_sptrace.set_time_resolution(unit); }
void set_time_resolution (const string& unit) { set_time_resolution(unit.c_str()); }
/// Internal class access
inline VerilatedVcd* spTrace () { return &m_sptrace; };
};
+12 -12
View File
@@ -754,7 +754,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
vl_fatal(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
}
WDataInP datap = ((IData*)(vop->varDatap()));
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
out[i].aval = datap[i];
out[i].bval = 0;
}
@@ -791,7 +791,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits);
}
for (i=0; i<bits; i++) {
for (i=0; i<bits; ++i) {
char val = (datap[i>>3]>>(i&7))&1;
outStr[bits-i-1] = val?'1':'0';
}
@@ -821,7 +821,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
chars = outStrSz;
}
for (i=0; i<chars; i++) {
for (i=0; i<chars; ++i) {
div_t idx = div(i*3, 8);
int val = datap[idx.quot];
if ((idx.quot+1)<bytes) {
@@ -882,7 +882,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
chars = outStrSz;
}
for (i=0; i<chars; i++) {
for (i=0; i<chars; ++i) {
char val = (datap[i>>1]>>((i&1)<<2))&15;
static char hex[] = "0123456789abcdef";
if (i==(chars-1)) {
@@ -922,7 +922,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes);
bytes = outStrSz;
}
for (i=0; i<bytes; i++) {
for (i=0; i<bytes; ++i) {
char val = datap[bytes-i-1];
// other simulators replace [leading?] zero chars with spaces, replicate here.
outStr[i] = val?val:' ';
@@ -1007,7 +1007,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->range().elements());
WDataOutP datap = ((IData*)(vop->varDatap()));
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
datap[i] = value_p->value.vector[i].aval;
if (i==(words-1)) {
datap[i] &= vop->mask();
@@ -1037,7 +1037,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
int bits = vop->varp()->range().elements();
int len = strlen(value_p->value.str);
CData* datap = ((CData*)(vop->varDatap()));
for (int i=0; i<bits; i++) {
for (int i=0; i<bits; ++i) {
char set = (i < len)?(value_p->value.str[len-i-1]=='1'):0;
// zero bits 7:1 of byte when assigning to bit 0, else
// or in 1 if bit set
@@ -1067,7 +1067,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
CData* datap = ((CData*)(vop->varDatap()));
div_t idx;
datap[0] = 0; // reset zero'th byte
for (int i=0; i<chars; i++) {
for (int i=0; i<chars; ++i) {
union {
char byte[2];
short half;
@@ -1105,7 +1105,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
datap[idx.quot+1] &= vop->mask_byte(idx.quot+1);
}
// zero off remaining top bytes
for (int i=idx.quot+2; i<bytes; i++) {
for (int i=idx.quot+2; i<bytes; ++i) {
datap[i] = 0;
}
return object;
@@ -1155,7 +1155,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
val += 2;
}
int len = strlen(val);
for (int i=0; i<chars; i++) {
for (int i=0; i<chars; ++i) {
char hex;
// compute hex digit value
if (i < len) {
@@ -1197,7 +1197,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
int bytes = VL_BYTES_I(vop->varp()->range().elements());
int len = strlen(value_p->value.str);
CData* datap = ((CData*)(vop->varDatap()));
for (int i=0; i<bytes; i++) {
for (int i=0; i<bytes; ++i) {
datap[i] = (i < len)?value_p->value.str[len-i-1]:0; // prepend with 0 values before placing string the least signifcant bytes
}
return object;
@@ -1255,7 +1255,7 @@ void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
}
if (time_p->type == vpiSimTime) {
QData qtime = VL_TIME_Q();
IData itime[2];
WData itime[2];
VL_SET_WQ(itime, qtime);
time_p->low = itime[0];
time_p->high = itime[1];
+24
View File
@@ -509,6 +509,30 @@ public:
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPow* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPowSS* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPowSU* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPowUS* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstCCast* nodep) {
// Extending a value of the same word width is just a NOP.
if (nodep->size()>VL_WORDSIZE) {
+2 -1
View File
@@ -335,7 +335,8 @@ private:
UINFO(9," need .* PORT "<<portp<<endl);
// Create any not already connected
AstPin* newp = new AstPin(nodep->fileline(),0,portp->name(),
new AstVarRef(nodep->fileline(),portp->name(),false));
new AstParseRef(nodep->fileline(),
AstParseRefExp::PX_TEXT, portp->name(), NULL, NULL));
newp->svImplicit(true);
nodep->addPinsp(newp);
} else { // warn on the CELL that needs it, not the port
+14 -3
View File
@@ -1217,6 +1217,9 @@ V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
setZero();
for (int bit=32; bit<rhs.width(); bit++) {
if (rhs.bitIs1(bit)) return *this; // shift of over 2^32 must be zero
}
uint32_t rhsval = rhs.toUInt();
if (rhsval < (uint32_t)lhs.width()) {
for (int bit=0; bit<this->width(); bit++) {
@@ -1232,6 +1235,13 @@ V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs, uint32_
// We presume it is signed; as that's V3Width's job to convert to opShiftR
if (rhs.isFourState()) return setAllBitsX();
setZero();
for (int bit=32; bit<rhs.width(); bit++) {
for (int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIs(lbits-1)); // 0/1/X/Z
}
if (rhs.bitIs1(lbits-1)) setAllBits1(); // -1 else 0
return *this; // shift of over 2^32 must be -1/0
}
uint32_t rhsval = rhs.toUInt();
if (rhsval < (uint32_t)lhs.width()) {
for (int bit=0; bit<this->width(); bit++) {
@@ -1239,7 +1249,7 @@ V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs, uint32_
}
} else {
for (int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIs(lbits-1));
setBit(bit,lhs.bitIs(lbits-1)); // 0/1/X/Z
}
}
return *this;
@@ -1249,6 +1259,9 @@ V3Number& V3Number::opShiftL (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
setZero();
for (int bit=32; bit<rhs.width(); bit++) {
if (rhs.bitIs1(bit)) return *this; // shift of over 2^32 must be zero
}
uint32_t rhsval = rhs.toUInt();
for (int bit=0; bit<this->width(); bit++) {
if (bit >= (int)rhsval) {
@@ -1518,8 +1531,6 @@ V3Number& V3Number::opPow (const V3Number& lhs, const V3Number& rhs, bool lsign,
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setQuad(1); // Overrides lhs 0 -> return 0
// We may want to special case when the lhs is 2, so we can get larger outputs
if (lhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large >64bit ** power operator not implemented yet: "<<*this);
if (rhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large >64bit ** power operator not implemented yet: "<<*this);
if (rsign && rhs.isNegative()) {
if (lhs.isEqZero()) return setAllBitsXRemoved();
else if (lhs.isEqOne()) return setQuad(1);
+2 -1
View File
@@ -803,7 +803,6 @@ private:
nodep->dtypeFrom(expDTypep);
// rhs already finalized in iterate_shift_prelim
iterateCheck(nodep,"LHS",nodep->lhsp(),SELF,FINAL,nodep->dtypep(),EXTEND_EXP);
if (nodep->width()>64) nodep->v3error("Unsupported: Large >64bit ** power operator not implemented.");
AstNode* newp = NULL; // No change
if (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned()) {
newp = new AstPowSS (nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
@@ -2750,6 +2749,8 @@ private:
AstNodeDType* expDTypep = m_vup->dtypeOverridep(nodep->dtypep());
AstNodeDType* subDTypep = expDTypep;
nodep->dtypeFrom(expDTypep);
// We don't use LHS && RHS -- unspecified language corner, see t_math_signed5 test
//bool expSigned = (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
if (AstNodeBiop* newp=replaceWithUOrSVersion(nodep, expDTypep->isSigned())) { VL_DANGLING(nodep);
nodep = newp; // Process new node instead
}
+16 -3
View File
@@ -223,7 +223,11 @@ private:
// SELBIT(array, index) -> SEL(array, index*width-of-subindex, width-of-subindex)
AstNode* subp = rhsp;
if (fromRange.lo()!=0 || fromRange.hi()<0) {
subp = newSubNeg (subp, fromRange.lo());
if (fromRange.littleEndian()) {
subp = newSubNeg(fromRange.hi(), subp);
} else {
subp = newSubNeg(subp, fromRange.lo());
}
}
if (!fromRange.elements() || (adtypep->width() % fromRange.elements())!=0)
adtypep->v3fatalSrc("Array extraction with width miscomputed "
@@ -311,11 +315,20 @@ private:
if (!fromRange.elements() || (adtypep->width() % fromRange.elements())!=0)
adtypep->v3fatalSrc("Array extraction with width miscomputed "
<<adtypep->width()<<"/"<<fromRange.elements());
if (fromRange.littleEndian()) {
// Below code assumes big bit endian; just works out if we swap
int x = msb; msb = lsb; lsb = x;
}
if (lsb > msb) {
nodep->v3error("["<<msb<<":"<<lsb<<"] Range extract has backward bit ordering, perhaps you wanted ["<<lsb<<":"<<msb<<"]");
int x = msb; msb = lsb; lsb = x;
}
int elwidth = adtypep->width() / fromRange.elements();
AstSel* newp = new AstSel (nodep->fileline(),
fromp,
new AstConst(nodep->fileline(),AstConst::Unsized32(),lsb*elwidth),
new AstConst(nodep->fileline(),AstConst::Unsized32(),(msb-lsb+1)*elwidth));
new AstMul(nodep->fileline(), newSubLsbOf(lsbp, fromRange),
new AstConst(nodep->fileline(), AstConst::Unsized32(), elwidth)),
new AstConst(nodep->fileline(), AstConst::Unsized32(), (msb-lsb+1)*elwidth));
newp->declRange(fromRange);
newp->declElWidth(elwidth);
newp->dtypeFrom(sliceDType(adtypep, msb, lsb));
+5 -2
View File
@@ -1463,9 +1463,12 @@ sub vcd_identical {
if (!-r $fn2) { $self->error("File does not exist $fn2\n"); return 0; }
{
# vcddiff to check transitions, if installed
my $out = `vcddiff --help`;
my $cmd = qq{vcddiff --help};
print "\t$cmd\n" if $::Debug;
my $out = `$cmd`;
if ($out !~ /Usage:/) { $self->skip("No vcddiff installed\n"); return 0; }
my $cmd = qq{vcddiff "$fn1" "$fn2"};
$cmd = qq{vcddiff "$fn1" "$fn2"};
print "\t$cmd\n" if $::Debug;
$out = `$cmd`;
if ($out ne '') {
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+41
View File
@@ -0,0 +1,41 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2017 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=1;
counter_io c_data();
counter_ansi c1 (.clk, .*);
always @ (posedge clk) begin
cyc <= cyc + 1;
if (cyc==20) begin
if (c_data.value != 12345) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
interface counter_io;
integer value;
endinterface
module counter_ansi
(
input clk,
counter_io c_data
);
always_ff @ (posedge clk) begin
c_data.value <= 12345;
end
endmodule : counter_ansi
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+73
View File
@@ -0,0 +1,73 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2004 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
reg [67:0] q;
reg signed [67:0] qs;
initial begin
q = 68'he_12345678_9abcdef0 ** 68'h3;
if (q != 68'hcee3cb96ce96cf000) $stop;
//
q = 68'he_12345678_9abcdef0 ** 68'h5_6789abcd_ef012345;
if (q != 68'h0) $stop;
//
qs = 68'she_12345678_9abcdef0 ** 68'sh3;
if (qs != 68'shcee3cb96ce96cf000) $stop;
//
qs = 68'she_12345678_9abcdef0 ** 68'sh5_6789abcd_ef012345;
if (qs != 68'h0) $stop;
end
reg [67:0] left;
reg [67:0] right;
wire [67:0] outu = left ** right;
wire signed [67:0] outs = $signed(left) ** $signed(right);
integer cyc; initial cyc=1;
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
`ifdef TEST_VERBOSE
$write("%d %x %x %x %x\n", cyc, left, right, outu, outs);
`endif
if (cyc==1) begin
left <= 68'h1;
right <= '0;
end
if (cyc==2) begin
if (outu != 68'h1) $stop;
if (outs != 68'h1) $stop;
end
if (cyc==3) begin
left <= 68'he_12345678_9abcdef0;
right <= 68'h3;
end
if (cyc==4) begin
if (outu != 68'hcee3cb96ce96cf000) $stop;
if (outs != 68'hcee3cb96ce96cf000) $stop;
end
if (cyc==5) begin
left <= 68'he_12345678_9abcdef0;
right <= 68'h5_6789abcd_ef012345;
end
if (cyc==6) begin
if (outu != 68'h0) $stop;
if (outs != 68'h0) $stop;
end
if (cyc==9) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
end
endmodule
+16 -1
View File
@@ -5,17 +5,24 @@
module t (/*AUTOARG*/
// Outputs
ign,
ign, ign2, ign3,
// Inputs
clk
);
input clk;
output [31:0] ign;
output [3:0] ign2;
output [11:0] ign3;
parameter [95:0] P6 = 6;
localparam P64 = (1 << P6);
// verilator lint_off WIDTH
localparam [4:0] PBIG23 = 1'b1 << ~73'b0;
localparam [3:0] PBIG29 = 4'b1 << 33'h100000000;
// verilator lint_on WIDTH
reg [31:0] right;
reg [31:0] left;
reg [P64-1:0] qright;
@@ -23,6 +30,14 @@ module t (/*AUTOARG*/
reg [31:0] amt;
assign ign = {31'h0, clk} >>> 4'bx; // bug760
assign ign2 = {amt[1:0] >> {22{amt[5:2]}}, amt[1:0] << (0 <<< amt[5:2])}; // bug1174
assign ign3 = {amt[1:0] >> {22{amt[5:2]}},
amt[1:0] >> {11{amt[5:2]}},
$signed(amt[1:0]) >>> {22{amt[5:2]}},
$signed(amt[1:0]) >>> {11{amt[5:2]}},
amt[1:0] << {22{amt[5:2]}},
amt[1:0] << {11{amt[5:2]}}};
always @* begin
right = 32'h819b018a >> amt;
+1
View File
@@ -83,6 +83,7 @@
w4_u = ((5'b01010 == (5'sb11111 / 5'sd3))); // Exp 0 Vlt 0 // Must be signed result (-1/3) to make this result zero
`ifdef VCS // I-2014.03
`checkh(w4_u, 4'b0000); // Wrong, gets 5'b0==..., unsigned does not propagate
// Somewhat questionable, as spec says division signed depends on only LHS and RHS, however differs from others
`else
`checkh(w4_u, 4'b0001); // NC-Verilog, Modelsim, XSim, ...
`endif
+48
View File
@@ -0,0 +1,48 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2008 by Wilson Snyder.
#include <verilated.h>
#include <verilated_vcd_c.h>
#if defined(T_TRACE_TIMESCALE)
# include "Vt_trace_timescale.h"
#else
# error "Unknown test"
#endif
unsigned long long main_time = 0;
double sc_time_stamp() {
return ((double)main_time) / VL_TIME_MULTIPLIER;
}
int main(int argc, char **argv, char **env) {
VM_PREFIX* top = new VM_PREFIX("top");
Verilated::debug(0);
Verilated::traceEverOn(true);
VerilatedVcdC* tfp = new VerilatedVcdC;
tfp->set_time_resolution("1ps");
tfp->set_time_unit("1ns");
top->trace(tfp,99);
tfp->open("obj_dir/t_trace_timescale/t_trace_timescale.vcd");
top->clk = 0;
while (main_time < 190*VL_TIME_MULTIPLIER) {
top->clk = ~top->clk;
top->eval();
tfp->dump((unsigned int)(main_time));
main_time += VL_TIME_MULTIPLIER/2;
}
tfp->close();
top->final();
printf ("*-* All Finished *-*\n");
return 0;
}
+965
View File
@@ -0,0 +1,965 @@
$version Generated by VerilatedVcd $end
$date Tue Jun 20 19:31:48 2017
$end
$timescale 1ps $end
$scope module top $end
$var wire 1 $ clk $end
$scope module t $end
$var wire 1 $ clk $end
$var wire 32 # cyc [31:0] $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
b00000000000000000000000000000001 #
1$
#500
0$
#1000
b00000000000000000000000000000010 #
1$
#1500
0$
#2000
b00000000000000000000000000000011 #
1$
#2500
0$
#3000
b00000000000000000000000000000100 #
1$
#3500
0$
#4000
b00000000000000000000000000000101 #
1$
#4500
0$
#5000
b00000000000000000000000000000110 #
1$
#5500
0$
#6000
b00000000000000000000000000000111 #
1$
#6500
0$
#7000
b00000000000000000000000000001000 #
1$
#7500
0$
#8000
b00000000000000000000000000001001 #
1$
#8500
0$
#9000
b00000000000000000000000000001010 #
1$
#9500
0$
#10000
b00000000000000000000000000001011 #
1$
#10500
0$
#11000
b00000000000000000000000000001100 #
1$
#11500
0$
#12000
b00000000000000000000000000001101 #
1$
#12500
0$
#13000
b00000000000000000000000000001110 #
1$
#13500
0$
#14000
b00000000000000000000000000001111 #
1$
#14500
0$
#15000
b00000000000000000000000000010000 #
1$
#15500
0$
#16000
b00000000000000000000000000010001 #
1$
#16500
0$
#17000
b00000000000000000000000000010010 #
1$
#17500
0$
#18000
b00000000000000000000000000010011 #
1$
#18500
0$
#19000
b00000000000000000000000000010100 #
1$
#19500
0$
#20000
b00000000000000000000000000010101 #
1$
#20500
0$
#21000
b00000000000000000000000000010110 #
1$
#21500
0$
#22000
b00000000000000000000000000010111 #
1$
#22500
0$
#23000
b00000000000000000000000000011000 #
1$
#23500
0$
#24000
b00000000000000000000000000011001 #
1$
#24500
0$
#25000
b00000000000000000000000000011010 #
1$
#25500
0$
#26000
b00000000000000000000000000011011 #
1$
#26500
0$
#27000
b00000000000000000000000000011100 #
1$
#27500
0$
#28000
b00000000000000000000000000011101 #
1$
#28500
0$
#29000
b00000000000000000000000000011110 #
1$
#29500
0$
#30000
b00000000000000000000000000011111 #
1$
#30500
0$
#31000
b00000000000000000000000000100000 #
1$
#31500
0$
#32000
b00000000000000000000000000100001 #
1$
#32500
0$
#33000
b00000000000000000000000000100010 #
1$
#33500
0$
#34000
b00000000000000000000000000100011 #
1$
#34500
0$
#35000
b00000000000000000000000000100100 #
1$
#35500
0$
#36000
b00000000000000000000000000100101 #
1$
#36500
0$
#37000
b00000000000000000000000000100110 #
1$
#37500
0$
#38000
b00000000000000000000000000100111 #
1$
#38500
0$
#39000
b00000000000000000000000000101000 #
1$
#39500
0$
#40000
b00000000000000000000000000101001 #
1$
#40500
0$
#41000
b00000000000000000000000000101010 #
1$
#41500
0$
#42000
b00000000000000000000000000101011 #
1$
#42500
0$
#43000
b00000000000000000000000000101100 #
1$
#43500
0$
#44000
b00000000000000000000000000101101 #
1$
#44500
0$
#45000
b00000000000000000000000000101110 #
1$
#45500
0$
#46000
b00000000000000000000000000101111 #
1$
#46500
0$
#47000
b00000000000000000000000000110000 #
1$
#47500
0$
#48000
b00000000000000000000000000110001 #
1$
#48500
0$
#49000
b00000000000000000000000000110010 #
1$
#49500
0$
#50000
b00000000000000000000000000110011 #
1$
#50500
0$
#51000
b00000000000000000000000000110100 #
1$
#51500
0$
#52000
b00000000000000000000000000110101 #
1$
#52500
0$
#53000
b00000000000000000000000000110110 #
1$
#53500
0$
#54000
b00000000000000000000000000110111 #
1$
#54500
0$
#55000
b00000000000000000000000000111000 #
1$
#55500
0$
#56000
b00000000000000000000000000111001 #
1$
#56500
0$
#57000
b00000000000000000000000000111010 #
1$
#57500
0$
#58000
b00000000000000000000000000111011 #
1$
#58500
0$
#59000
b00000000000000000000000000111100 #
1$
#59500
0$
#60000
b00000000000000000000000000111101 #
1$
#60500
0$
#61000
b00000000000000000000000000111110 #
1$
#61500
0$
#62000
b00000000000000000000000000111111 #
1$
#62500
0$
#63000
b00000000000000000000000001000000 #
1$
#63500
0$
#64000
b00000000000000000000000001000001 #
1$
#64500
0$
#65000
b00000000000000000000000001000010 #
1$
#65500
0$
#66000
b00000000000000000000000001000011 #
1$
#66500
0$
#67000
b00000000000000000000000001000100 #
1$
#67500
0$
#68000
b00000000000000000000000001000101 #
1$
#68500
0$
#69000
b00000000000000000000000001000110 #
1$
#69500
0$
#70000
b00000000000000000000000001000111 #
1$
#70500
0$
#71000
b00000000000000000000000001001000 #
1$
#71500
0$
#72000
b00000000000000000000000001001001 #
1$
#72500
0$
#73000
b00000000000000000000000001001010 #
1$
#73500
0$
#74000
b00000000000000000000000001001011 #
1$
#74500
0$
#75000
b00000000000000000000000001001100 #
1$
#75500
0$
#76000
b00000000000000000000000001001101 #
1$
#76500
0$
#77000
b00000000000000000000000001001110 #
1$
#77500
0$
#78000
b00000000000000000000000001001111 #
1$
#78500
0$
#79000
b00000000000000000000000001010000 #
1$
#79500
0$
#80000
b00000000000000000000000001010001 #
1$
#80500
0$
#81000
b00000000000000000000000001010010 #
1$
#81500
0$
#82000
b00000000000000000000000001010011 #
1$
#82500
0$
#83000
b00000000000000000000000001010100 #
1$
#83500
0$
#84000
b00000000000000000000000001010101 #
1$
#84500
0$
#85000
b00000000000000000000000001010110 #
1$
#85500
0$
#86000
b00000000000000000000000001010111 #
1$
#86500
0$
#87000
b00000000000000000000000001011000 #
1$
#87500
0$
#88000
b00000000000000000000000001011001 #
1$
#88500
0$
#89000
b00000000000000000000000001011010 #
1$
#89500
0$
#90000
b00000000000000000000000001011011 #
1$
#90500
0$
#91000
b00000000000000000000000001011100 #
1$
#91500
0$
#92000
b00000000000000000000000001011101 #
1$
#92500
0$
#93000
b00000000000000000000000001011110 #
1$
#93500
0$
#94000
b00000000000000000000000001011111 #
1$
#94500
0$
#95000
b00000000000000000000000001100000 #
1$
#95500
0$
#96000
b00000000000000000000000001100001 #
1$
#96500
0$
#97000
b00000000000000000000000001100010 #
1$
#97500
0$
#98000
b00000000000000000000000001100011 #
1$
#98500
0$
#99000
b00000000000000000000000001100100 #
1$
#99500
0$
#100000
b00000000000000000000000001100101 #
1$
#100500
0$
#101000
b00000000000000000000000001100110 #
1$
#101500
0$
#102000
b00000000000000000000000001100111 #
1$
#102500
0$
#103000
b00000000000000000000000001101000 #
1$
#103500
0$
#104000
b00000000000000000000000001101001 #
1$
#104500
0$
#105000
b00000000000000000000000001101010 #
1$
#105500
0$
#106000
b00000000000000000000000001101011 #
1$
#106500
0$
#107000
b00000000000000000000000001101100 #
1$
#107500
0$
#108000
b00000000000000000000000001101101 #
1$
#108500
0$
#109000
b00000000000000000000000001101110 #
1$
#109500
0$
#110000
b00000000000000000000000001101111 #
1$
#110500
0$
#111000
b00000000000000000000000001110000 #
1$
#111500
0$
#112000
b00000000000000000000000001110001 #
1$
#112500
0$
#113000
b00000000000000000000000001110010 #
1$
#113500
0$
#114000
b00000000000000000000000001110011 #
1$
#114500
0$
#115000
b00000000000000000000000001110100 #
1$
#115500
0$
#116000
b00000000000000000000000001110101 #
1$
#116500
0$
#117000
b00000000000000000000000001110110 #
1$
#117500
0$
#118000
b00000000000000000000000001110111 #
1$
#118500
0$
#119000
b00000000000000000000000001111000 #
1$
#119500
0$
#120000
b00000000000000000000000001111001 #
1$
#120500
0$
#121000
b00000000000000000000000001111010 #
1$
#121500
0$
#122000
b00000000000000000000000001111011 #
1$
#122500
0$
#123000
b00000000000000000000000001111100 #
1$
#123500
0$
#124000
b00000000000000000000000001111101 #
1$
#124500
0$
#125000
b00000000000000000000000001111110 #
1$
#125500
0$
#126000
b00000000000000000000000001111111 #
1$
#126500
0$
#127000
b00000000000000000000000010000000 #
1$
#127500
0$
#128000
b00000000000000000000000010000001 #
1$
#128500
0$
#129000
b00000000000000000000000010000010 #
1$
#129500
0$
#130000
b00000000000000000000000010000011 #
1$
#130500
0$
#131000
b00000000000000000000000010000100 #
1$
#131500
0$
#132000
b00000000000000000000000010000101 #
1$
#132500
0$
#133000
b00000000000000000000000010000110 #
1$
#133500
0$
#134000
b00000000000000000000000010000111 #
1$
#134500
0$
#135000
b00000000000000000000000010001000 #
1$
#135500
0$
#136000
b00000000000000000000000010001001 #
1$
#136500
0$
#137000
b00000000000000000000000010001010 #
1$
#137500
0$
#138000
b00000000000000000000000010001011 #
1$
#138500
0$
#139000
b00000000000000000000000010001100 #
1$
#139500
0$
#140000
b00000000000000000000000010001101 #
1$
#140500
0$
#141000
b00000000000000000000000010001110 #
1$
#141500
0$
#142000
b00000000000000000000000010001111 #
1$
#142500
0$
#143000
b00000000000000000000000010010000 #
1$
#143500
0$
#144000
b00000000000000000000000010010001 #
1$
#144500
0$
#145000
b00000000000000000000000010010010 #
1$
#145500
0$
#146000
b00000000000000000000000010010011 #
1$
#146500
0$
#147000
b00000000000000000000000010010100 #
1$
#147500
0$
#148000
b00000000000000000000000010010101 #
1$
#148500
0$
#149000
b00000000000000000000000010010110 #
1$
#149500
0$
#150000
b00000000000000000000000010010111 #
1$
#150500
0$
#151000
b00000000000000000000000010011000 #
1$
#151500
0$
#152000
b00000000000000000000000010011001 #
1$
#152500
0$
#153000
b00000000000000000000000010011010 #
1$
#153500
0$
#154000
b00000000000000000000000010011011 #
1$
#154500
0$
#155000
b00000000000000000000000010011100 #
1$
#155500
0$
#156000
b00000000000000000000000010011101 #
1$
#156500
0$
#157000
b00000000000000000000000010011110 #
1$
#157500
0$
#158000
b00000000000000000000000010011111 #
1$
#158500
0$
#159000
b00000000000000000000000010100000 #
1$
#159500
0$
#160000
b00000000000000000000000010100001 #
1$
#160500
0$
#161000
b00000000000000000000000010100010 #
1$
#161500
0$
#162000
b00000000000000000000000010100011 #
1$
#162500
0$
#163000
b00000000000000000000000010100100 #
1$
#163500
0$
#164000
b00000000000000000000000010100101 #
1$
#164500
0$
#165000
b00000000000000000000000010100110 #
1$
#165500
0$
#166000
b00000000000000000000000010100111 #
1$
#166500
0$
#167000
b00000000000000000000000010101000 #
1$
#167500
0$
#168000
b00000000000000000000000010101001 #
1$
#168500
0$
#169000
b00000000000000000000000010101010 #
1$
#169500
0$
#170000
b00000000000000000000000010101011 #
1$
#170500
0$
#171000
b00000000000000000000000010101100 #
1$
#171500
0$
#172000
b00000000000000000000000010101101 #
1$
#172500
0$
#173000
b00000000000000000000000010101110 #
1$
#173500
0$
#174000
b00000000000000000000000010101111 #
1$
#174500
0$
#175000
b00000000000000000000000010110000 #
1$
#175500
0$
#176000
b00000000000000000000000010110001 #
1$
#176500
0$
#177000
b00000000000000000000000010110010 #
1$
#177500
0$
#178000
b00000000000000000000000010110011 #
1$
#178500
0$
#179000
b00000000000000000000000010110100 #
1$
#179500
0$
#180000
b00000000000000000000000010110101 #
1$
#180500
0$
#181000
b00000000000000000000000010110110 #
1$
#181500
0$
#182000
b00000000000000000000000010110111 #
1$
#182500
0$
#183000
b00000000000000000000000010111000 #
1$
#183500
0$
#184000
b00000000000000000000000010111001 #
1$
#184500
0$
#185000
b00000000000000000000000010111010 #
1$
#185500
0$
#186000
b00000000000000000000000010111011 #
1$
#186500
0$
#187000
b00000000000000000000000010111100 #
1$
#187500
0$
#188000
b00000000000000000000000010111101 #
1$
#188500
0$
#189000
b00000000000000000000000010111110 #
1$
#189500
0$
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
make_top_shell => 0,
make_main => 0,
v_flags2 => ["--trace --exe $Self->{t_dir}/t_trace_timescale.cpp"],
make_flags => 'CPPFLAGS_ADD=-DVL_TIME_MULTIPLIER=1000',
);
execute (
check_finished=>1,
);
vcd_identical ("$Self->{obj_dir}/$Self->{name}.vcd",
"t/$Self->{name}.out");
ok(1);
1;
+16
View File
@@ -0,0 +1,16 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2013 by Wilson Snyder.
module t
(
input wire clk
);
integer cyc; initial cyc = 0;
always @ (posedge clk) begin
cyc <= cyc + 1;
end
endmodule
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+26
View File
@@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2017 by James Pallister.
typedef logic logic_alias_t;
module t;
logic_alias_t [6:1] signal;
// verilator lint_off LITENDIAN
logic_alias_t [1:6] signal2;
// verilator lint_on LITENDIAN
initial begin
signal[6:1] = 'b100001;
signal[3] = 'b1;
signal2[1:6] = 'b100001;
signal2[4] = 'b1;
if (signal != 'b100101) $stop;
if (signal2 != 'b100101) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+3 -2
View File
@@ -82,8 +82,9 @@ our $Raise_Weight_Max = 50;
'VADD'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'(%1 + %2)', },
'VSUB'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'(%1 - %2)', },
'VMUL'=> {weight=>1&&15,width=>0, sc=>1, terminal=>0, v=>'(%1 * %2)', }, # High % as rarely applyable
'VDIV'=> {weight=>1&&8, width=>0, sc=>1, terminal=>0, v=>'((%2)==%xw\'h0 ? %xw\'%xsh0:(%1 / %2))', },
'VMODDIV'=> {weight=>1&&8, width=>0, sc=>1, terminal=>0, v=>'((%2)==%xw\'h0 ? %xw\'%xsh0:(%1 %% %2))', },
# Unspecified behavior with == (a-signed / b) -- see t_math_signed5.v test
'VDIV'=> {weight=>1&&8, width=>0, signed=>0, sc=>1, terminal=>0, v=>'((%2)==%xw\'h0 ? %xw\'%xsh0:(%1 / %2))', },
'VMODDIV'=> {weight=>1&&8, width=>0, signed=>0, sc=>1, terminal=>0, v=>'((%2)==%xw\'h0 ? %xw\'%xsh0:(%1 %% %2))', },
#'VPOW'=> {weight=>2&&0,width=>-64, sc=>0, terminal=>0, v=>'(%1 ** %2)', },
'VSHIFTL'=> {weight=>1&&8, width=>0, signed=>0, sc=>0, terminal=>0, v=>'(%1 << %2)', },
'VSHIFTLS'=> {weight=>1&&8, width=>0, signed=>1, sc=>0, terminal=>0, v=>'(%1 <<< %2)', },