From 4443ab34fd17b01ed9013cfefeb7f0ffb53d93e9 Mon Sep 17 00:00:00 2001 From: Pieter Kapsenberg Date: Wed, 15 Jan 2020 07:32:45 -0500 Subject: [PATCH] Support left justified . Closes #2101. --- Changes | 8 +++++--- docs/CONTRIBUTORS | 1 + include/verilated.cpp | 34 ++++++++++++++++++++++------------ src/V3Const.cpp | 2 +- src/V3EmitC.cpp | 3 ++- src/V3LinkResolve.cpp | 2 +- src/V3Number.cpp | 19 ++++++++++++------- src/V3Number.h | 2 +- src/V3Width.cpp | 2 +- test_regress/t/t_display.out | 14 ++++++++++++++ test_regress/t/t_display.v | 19 +++++++++++++++++++ 11 files changed, 79 insertions(+), 27 deletions(-) diff --git a/Changes b/Changes index 6445c228c..6d0b6c432 100644 --- a/Changes +++ b/Changes @@ -5,11 +5,13 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.027 devel -** Support attributes (public, isolate_assignments, etc.) in configuration files. +** Support attributes (public, isolate_assignments, etc.) in configuration files. -** Add -match to lint_off to waive warnings. [Philipp Wagner] +** Add -match to lint_off to waive warnings. [Philipp Wagner] -*** Support $readmem/$writemem with assoc arrarys. Closes #2100. [agrobman] +*** Support $readmem/$writemem with assoc arrarys. Closes #2100. [agrobman] + +**** Support left justified $display. Closes #2101. [Pieter Kapsenberg] **** Add parameter values in XML. #2110. [Pieter Kapsenberg] diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index ab88d1a58..9ca30b58e 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -27,6 +27,7 @@ Mike Popoloski Peter Monsson Patrick Stewart Philipp Wagner +Pieter Kapsenberg Richard Myers Sebastien Van Cauwenberghe Stefan Wallentowitz diff --git a/include/verilated.cpp b/include/verilated.cpp index 8677f3154..2f04393e1 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -618,6 +618,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA const char* pctp = NULL; // Most recent %##.##g format bool inPct = false; bool widthSet = false; + bool left = false; int width = 0; for (const char* pos = formatp; *pos; ++pos) { if (!inPct && pos[0]=='%') { @@ -643,6 +644,10 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA widthSet = true; width = width*10 + (fmt - '0'); break; + case '-': + left = true; + inPct = true; // Get more digits + break; case '.': inPct = true; // Get more digits break; @@ -662,8 +667,9 @@ 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; + std::string padding; + if (width > cstrp->size()) padding.append(width - cstrp->size(), ' '); + output += left ? (*cstrp + padding) : (padding + *cstrp); break; } case 'e': @@ -721,8 +727,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff; field += (charval==0)?' ':charval; } - if (width > field.size()) output += std::string(width - field.size(), ' '); - output += field; + std::string padding; + if (width > field.size()) padding.append(width - field.size(), ' '); + output += left ? (field + padding) : (padding + field); break; } case 'd': { // Signed decimal @@ -743,14 +750,15 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA digits = append.length(); } int needmore = width-digits; + std::string padding; if (needmore>0) { if (pctp && pctp[0] && pctp[1]=='0') { // %0 - output.append(needmore, '0'); // Pre-pad zero + padding.append(needmore, '0'); // Pre-pad zero } else { - output.append(needmore, ' '); // Pre-pad spaces + padding.append(needmore, ' '); // Pre-pad spaces } } - output += append; + output += left ? (append + padding) : (padding + append); break; } case '#': { // Unsigned decimal @@ -764,14 +772,15 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA digits = append.length(); } int needmore = width-digits; + std::string padding; if (needmore>0) { if (pctp && pctp[0] && pctp[1]=='0') { // %0 - output.append(needmore, '0'); // Pre-pad zero + padding.append(needmore, '0'); // Pre-pad zero } else { - output.append(needmore, ' '); // Pre-pad spaces + padding.append(needmore, ' '); // Pre-pad spaces } } - output += append; + output += left ? (append + padding) : (padding + append); break; } case 't': { // Time @@ -786,8 +795,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA VL_FATAL_MT(__FILE__, __LINE__, "", "Unsupported VL_TIME_MULTIPLIER"); } int needmore = width-digits; - if (needmore>0) output.append(needmore, ' '); // Pre-pad spaces - output += tmp; + std::string padding; + if (needmore>0) padding.append(needmore, ' '); // Pad with spaces + output += left ? (tmp + padding) : (padding + tmp); break; } case 'b': diff --git a/src/V3Const.cpp b/src/V3Const.cpp index e5825110d..10d48e1da 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -2069,7 +2069,7 @@ private: if (!inPct && ch=='%') { inPct = true; fmt = ch; - } else if (inPct && (isdigit(ch) || ch=='.')) { + } else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) { fmt += ch; } else if (inPct) { inPct = false; diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 0f69d91f7..a5e3edd97 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -1797,7 +1797,8 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep, switch (tolower(pos[0])) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - case '.': + case '.': // FALLTHRU + case '-': // Digits, like %5d, etc. vfmt += pos[0]; inPct = true; // Get more digits diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index edf2d6dd4..8dba07d89 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -270,7 +270,7 @@ private: if (!inPct && ch=='%') { inPct = true; fmt = ch; - } else if (inPct && (isdigit(ch) || ch=='.')) { + } else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) { fmt += ch; } else if (inPct) { inPct = false; diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 65f579654..f90b80e91 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -497,10 +497,10 @@ bool V3Number::displayedFmtLegal(char format) { } } -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::displayPad(size_t fmtsize, char pad, bool left, const string& in) { + string padding; + if (in.length() < fmtsize) padding = string(fmtsize - in.length(), pad); + return left ? (in + padding) : (padding + in); } string V3Number::displayed(AstNode* nodep, const string& vformat) const { @@ -512,6 +512,11 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { UASSERT(pos != vformat.end() && pos[0]=='%', "$display-like function with non format argument "<<*this); ++pos; + bool left = false; + if (pos[0] == '-') { + left = true; + ++pos; + } string fmtsize; for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); ++pos) { fmtsize += pos[0]; @@ -574,7 +579,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { } } size_t fmtsizen = static_cast(atoi(fmtsize.c_str())); - str = displayPad(fmtsizen, ' ', str); + str = displayPad(fmtsizen, ' ', left, str); return str; } case '~': // Signed decimal @@ -604,7 +609,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { bool zeropad = fmtsize.length()>0 && fmtsize[0]=='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); + str = displayPad(fmtsizen, (zeropad ? '0' : ' '), left, str); return str; } case 'e': @@ -651,7 +656,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { } case '@': { // Packed string size_t fmtsizen = static_cast(atoi(fmtsize.c_str())); - str = displayPad(fmtsizen, ' ', toString()); + str = displayPad(fmtsizen, ' ', left, toString()); return str; } default: diff --git a/src/V3Number.h b/src/V3Number.h index 508a8db9a..73a2f4907 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -175,7 +175,7 @@ private: for (int i=0; i return [0] Embedded multiline +'23 23 23' +'23 23 23 ' +'23 23 23' +'23 23 23 ' +' 24' +'24 ' +' 0' +'0 ' +' sv-str' +'sv-str ' +' meep' +'meep ' +' beep' +'beep ' log10(2) = 2 *-* All Finished *-* diff --git a/test_regress/t/t_display.v b/test_regress/t/t_display.v index 691660ee6..90b80c6eb 100644 --- a/test_regress/t/t_display.v +++ b/test_regress/t/t_display.v @@ -13,7 +13,10 @@ module t; reg [31:0] str; initial str = "\000\277\021\n"; reg [47:0] str2; initial str2 = "\000what!"; reg [79:0] str3; initial str3 = "\000hmmm!1234"; + int n; initial n = 23; + reg [7:0] m; initial m = 24; string svs = "sv-str"; + reg [31:0] regstr = "meep"; sub sub (); sub2 sub2 (); @@ -144,6 +147,22 @@ multiline", $time); if (str !== 32'h00_bf_11_0a) $stop; `endif + // Padding + $write("'%0d %2d %8d'\n", 23, 23, 23); + $write("'%-0d %-2d %-8d'\n", 23, 23, 23); + $write("'%0d %2d %8d'\n", n, n, n); + $write("'%-0d %-2d %-8d'\n", n, n, n); + $write("'%8d'\n", m); + $write("'%-8d'\n", m); + $write("'%8t'\n", $time); + $write("'%-8t'\n", $time); + $write("'%8s'\n", svs); + $write("'%-8s'\n", svs); + $write("'%8s'\n", regstr); + $write("'%-8s'\n", regstr); + $write("'%8s'\n", "beep"); + $write("'%-8s'\n", "beep"); + // $itord conversion bug, note a %d instead of proper float $display("log10(2) = %d", $log10(100));