diff --git a/Changes b/Changes index 0bc7b655f..755695398 100644 --- a/Changes +++ b/Changes @@ -36,6 +36,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix expand optimization slowing --lint-only. Closes #2091. [Thomas Watts] +**** Fix %{number}s with strings. #2093. [agrobman] + * Verilator 4.024 2019-12-08 diff --git a/include/verilated.cpp b/include/verilated.cpp index 4bfae8d4c..07a880837 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -662,6 +662,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA case '@': { // Verilog/C++ string va_arg(ap, int); // # bits is ignored const std::string* cstrp = va_arg(ap, const std::string*); + if (width > cstrp->size()) output += std::string(width - cstrp->size(), ' '); output += *cstrp; break; } @@ -713,13 +714,17 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA output += charval; break; } - case 's': + case 's': { + std::string field; for (; lsb>=0; --lsb) { lsb = (lsb / 8) * 8; // Next digit IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff; - output += (charval==0)?' ':charval; + field += (charval==0)?' ':charval; } + if (width > field.size()) output += std::string(width - field.size(), ' '); + output += field; break; + } case 'd': { // Signed decimal int digits; std::string append; diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 1f060cecf..65f579654 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -496,11 +496,18 @@ bool V3Number::displayedFmtLegal(char format) { default: return false; } } + +string V3Number::displayPad(size_t fmtsize, char pad, const string& in) { + string prefix; + if (in.length() < fmtsize) prefix = string(fmtsize - in.length(), pad); + return prefix + in; +} + string V3Number::displayed(AstNode* nodep, const string& vformat) const { return displayed(nodep->fileline(), vformat); } -string V3Number::displayed(FileLine*fl, const string& vformat) const { +string V3Number::displayed(FileLine* fl, const string& vformat) const { string::const_iterator pos = vformat.begin(); UASSERT(pos != vformat.end() && pos[0]=='%', "$display-like function with non format argument "<<*this); @@ -566,6 +573,8 @@ string V3Number::displayed(FileLine*fl, const string& vformat) const { if (fmtsize != "0") str += ' '; } } + size_t fmtsizen = static_cast(atoi(fmtsize.c_str())); + str = displayPad(fmtsizen, ' ', str); return str; } case '~': // Signed decimal @@ -592,12 +601,10 @@ string V3Number::displayed(FileLine*fl, const string& vformat) const { str = cvtToStr(toUQuad()); } } - int intfmtsize = atoi(fmtsize.c_str()); bool zeropad = fmtsize.length()>0 && fmtsize[0]=='0'; - while (static_cast(str.length()) < intfmtsize) { - if (zeropad) str.insert(0, "0"); - else str.insert(0, " "); - } + // fmtsize might have changed since we parsed the %fmtsize + size_t fmtsizen = static_cast(atoi(fmtsize.c_str())); + str = displayPad(fmtsizen, (zeropad ? '0' : ' '), str); return str; } case 'e': @@ -643,7 +650,9 @@ string V3Number::displayed(FileLine*fl, const string& vformat) const { return str; } case '@': { // Packed string - return toString(); + size_t fmtsizen = static_cast(atoi(fmtsize.c_str())); + str = displayPad(fmtsizen, ' ', toString()); + return str; } default: fl->v3fatalSrc("Unknown $display-like format code for number: %"<