diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 13308d1cc..3f5d53095 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -31,6 +31,7 @@ Harald Heckmann Howard Su Huang Rui HyungKi Jeong +Iru Cai Ivan Vnučec Iztok Jeras James Hanlon diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 595830d27..e4ea84f22 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -605,6 +605,24 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { while (bit && bitIs0(bit)) bit--; while ((bit % 3) != 2) bit++; for (; bit > 0; bit -= 3) { + const int numX = countX(bit - 2, 3); + const int numZ = countZ(bit - 2, 3); + if (numX == 3 || numX == width() - (bit - 2)) { + str += 'x'; + continue; + } + if (numZ == 3 || numZ == width() - (bit - 2)) { + str += 'z'; + continue; + } + if (numX > 0) { + str += 'X'; + continue; + } + if (numZ > 0) { + str += 'Z'; + continue; + } int v = bitsValue(bit - 2, 3); str += static_cast<char>('0' + v); } @@ -617,6 +635,24 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { while (bit && bitIs0(bit)) bit--; while ((bit % 4) != 3) bit++; for (; bit > 0; bit -= 4) { + const int numX = countX(bit - 3, 4); + const int numZ = countZ(bit - 3, 4); + if (numX == 4 || numX == width() - (bit - 3)) { + str += 'x'; + continue; + } + if (numZ == 4 || numZ == width() - (bit - 3)) { + str += 'z'; + continue; + } + if (numX > 0) { + str += 'X'; + continue; + } + if (numZ > 0) { + str += 'Z'; + continue; + } int v = bitsValue(bit - 3, 4); if (v >= 10) { str += static_cast<char>('a' + v - 10); @@ -667,17 +703,33 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { if (issigned) dchars++; // space for sign fmtsize = cvtToStr(int(dchars)); } - if (issigned) { - if (width() > 64) { - str = toDecimalS(); + bool hasXZ = false; + if (isAllX()) { + str = "x"; + hasXZ = true; + } else if (isAllZ()) { + str = "z"; + hasXZ = true; + } else if (isAnyX()) { + str = "X"; + hasXZ = true; + } else if (isAnyZ()) { + str = "Z"; + hasXZ = true; + } + if (!hasXZ) { + if (issigned) { + if (width() > 64) { + str = toDecimalS(); + } else { + str = cvtToStr(toSQuad()); + } } else { - str = cvtToStr(toSQuad()); - } - } else { - if (width() > 64) { - str = toDecimalU(); - } else { - str = cvtToStr(toUQuad()); + if (width() > 64) { + str = toDecimalU(); + } else { + str = cvtToStr(toUQuad()); + } } } const bool zeropad = fmtsize.length() > 0 && fmtsize[0] == '0'; @@ -977,6 +1029,22 @@ bool V3Number::isLtXZ(const V3Number& rhs) const { } return false; } +int V3Number::countX(int lsb, int nbits) const { + int count = 0; + for (int bitn = 0; bitn < nbits; ++bitn) { + if (lsb + bitn >= width()) return count; + if (bitIsX(lsb + bitn)) ++count; + } + return count; +} +int V3Number::countZ(int lsb, int nbits) const { + int count = 0; + for (int bitn = 0; bitn < nbits; ++bitn) { + if (lsb + bitn >= width()) return count; + if (bitIsZ(lsb + bitn)) ++count; + } + return count; +} int V3Number::widthMin() const { for (int bit = width() - 1; bit > 0; bit--) { diff --git a/src/V3Number.h b/src/V3Number.h index 09b15e67b..9a33a6b7a 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -204,6 +204,9 @@ private: return v; } + int countX(int lsb, int nbits) const; + int countZ(int lsb, int nbits) const; + int words() const { return ((width() + 31) / 32); } uint32_t hiWordMask() const { return VL_MASK_I(width()); } diff --git a/test_regress/t/t_display.out b/test_regress/t/t_display.out index 9b2b995ce..0475a1952 100644 --- a/test_regress/t/t_display.out +++ b/test_regress/t/t_display.out @@ -74,4 +74,12 @@ multiline ' beep' 'beep ' log10(2) = 2 +x +xxXa +XXX 1x5X + x + z + X + Z +ZzX *-* All Finished *-* diff --git a/test_regress/t/t_display.v b/test_regress/t/t_display.v index 073268617..3f191f9b1 100644 --- a/test_regress/t/t_display.v +++ b/test_regress/t/t_display.v @@ -179,6 +179,16 @@ multiline", $time); $display("log10(2) = %d", $log10(100)); // verilator lint_on REALCVT + // unknown and high-impedance values + $display("%d", 1'bx); + $display("%h", 14'bx01010); + $display("%h %o", 12'b001xxx101x01, 12'b001xxx101x01); + $display("%d", 32'bx); + $display("%d", 32'bz); + $display("%d", 32'b11x11z111); + $display("%d", 32'b11111z111); + $display("%h", 12'b1zz1_zzzz_1x1z); + $write("*-* All Finished *-*\n"); $finish; end