Support left justified . Closes #2101.

This commit is contained in:
Pieter Kapsenberg 2020-01-15 07:32:45 -05:00 committed by Wilson Snyder
parent e9a309ea8d
commit 4443ab34fd
11 changed files with 79 additions and 27 deletions

View File

@ -5,11 +5,13 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.027 devel * 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] **** Add parameter values in XML. #2110. [Pieter Kapsenberg]

View File

@ -27,6 +27,7 @@ Mike Popoloski
Peter Monsson Peter Monsson
Patrick Stewart Patrick Stewart
Philipp Wagner Philipp Wagner
Pieter Kapsenberg
Richard Myers Richard Myers
Sebastien Van Cauwenberghe Sebastien Van Cauwenberghe
Stefan Wallentowitz Stefan Wallentowitz

View File

@ -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 const char* pctp = NULL; // Most recent %##.##g format
bool inPct = false; bool inPct = false;
bool widthSet = false; bool widthSet = false;
bool left = false;
int width = 0; int width = 0;
for (const char* pos = formatp; *pos; ++pos) { for (const char* pos = formatp; *pos; ++pos) {
if (!inPct && pos[0]=='%') { 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; widthSet = true;
width = width*10 + (fmt - '0'); width = width*10 + (fmt - '0');
break; break;
case '-':
left = true;
inPct = true; // Get more digits
break;
case '.': case '.':
inPct = true; // Get more digits inPct = true; // Get more digits
break; break;
@ -662,8 +667,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
case '@': { // Verilog/C++ string case '@': { // Verilog/C++ string
va_arg(ap, int); // # bits is ignored va_arg(ap, int); // # bits is ignored
const std::string* cstrp = va_arg(ap, const std::string*); const std::string* cstrp = va_arg(ap, const std::string*);
if (width > cstrp->size()) output += std::string(width - cstrp->size(), ' '); std::string padding;
output += *cstrp; if (width > cstrp->size()) padding.append(width - cstrp->size(), ' ');
output += left ? (*cstrp + padding) : (padding + *cstrp);
break; break;
} }
case 'e': 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; IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
field += (charval==0)?' ':charval; field += (charval==0)?' ':charval;
} }
if (width > field.size()) output += std::string(width - field.size(), ' '); std::string padding;
output += field; if (width > field.size()) padding.append(width - field.size(), ' ');
output += left ? (field + padding) : (padding + field);
break; break;
} }
case 'd': { // Signed decimal 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(); digits = append.length();
} }
int needmore = width-digits; int needmore = width-digits;
std::string padding;
if (needmore>0) { if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { // %0 if (pctp && pctp[0] && pctp[1]=='0') { // %0
output.append(needmore, '0'); // Pre-pad zero padding.append(needmore, '0'); // Pre-pad zero
} else { } else {
output.append(needmore, ' '); // Pre-pad spaces padding.append(needmore, ' '); // Pre-pad spaces
} }
} }
output += append; output += left ? (append + padding) : (padding + append);
break; break;
} }
case '#': { // Unsigned decimal 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(); digits = append.length();
} }
int needmore = width-digits; int needmore = width-digits;
std::string padding;
if (needmore>0) { if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { // %0 if (pctp && pctp[0] && pctp[1]=='0') { // %0
output.append(needmore, '0'); // Pre-pad zero padding.append(needmore, '0'); // Pre-pad zero
} else { } else {
output.append(needmore, ' '); // Pre-pad spaces padding.append(needmore, ' '); // Pre-pad spaces
} }
} }
output += append; output += left ? (append + padding) : (padding + append);
break; break;
} }
case 't': { // Time 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"); VL_FATAL_MT(__FILE__, __LINE__, "", "Unsupported VL_TIME_MULTIPLIER");
} }
int needmore = width-digits; int needmore = width-digits;
if (needmore>0) output.append(needmore, ' '); // Pre-pad spaces std::string padding;
output += tmp; if (needmore>0) padding.append(needmore, ' '); // Pad with spaces
output += left ? (tmp + padding) : (padding + tmp);
break; break;
} }
case 'b': case 'b':

View File

@ -2069,7 +2069,7 @@ private:
if (!inPct && ch=='%') { if (!inPct && ch=='%') {
inPct = true; inPct = true;
fmt = ch; fmt = ch;
} else if (inPct && (isdigit(ch) || ch=='.')) { } else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) {
fmt += ch; fmt += ch;
} else if (inPct) { } else if (inPct) {
inPct = false; inPct = false;

View File

@ -1797,7 +1797,8 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
switch (tolower(pos[0])) { switch (tolower(pos[0])) {
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
case '.': case '.': // FALLTHRU
case '-':
// Digits, like %5d, etc. // Digits, like %5d, etc.
vfmt += pos[0]; vfmt += pos[0];
inPct = true; // Get more digits inPct = true; // Get more digits

View File

@ -270,7 +270,7 @@ private:
if (!inPct && ch=='%') { if (!inPct && ch=='%') {
inPct = true; inPct = true;
fmt = ch; fmt = ch;
} else if (inPct && (isdigit(ch) || ch=='.')) { } else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) {
fmt += ch; fmt += ch;
} else if (inPct) { } else if (inPct) {
inPct = false; inPct = false;

View File

@ -497,10 +497,10 @@ bool V3Number::displayedFmtLegal(char format) {
} }
} }
string V3Number::displayPad(size_t fmtsize, char pad, const string& in) { string V3Number::displayPad(size_t fmtsize, char pad, bool left, const string& in) {
string prefix; string padding;
if (in.length() < fmtsize) prefix = string(fmtsize - in.length(), pad); if (in.length() < fmtsize) padding = string(fmtsize - in.length(), pad);
return prefix + in; return left ? (in + padding) : (padding + in);
} }
string V3Number::displayed(AstNode* nodep, const string& vformat) const { 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]=='%', UASSERT(pos != vformat.end() && pos[0]=='%',
"$display-like function with non format argument "<<*this); "$display-like function with non format argument "<<*this);
++pos; ++pos;
bool left = false;
if (pos[0] == '-') {
left = true;
++pos;
}
string fmtsize; string fmtsize;
for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); ++pos) { for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); ++pos) {
fmtsize += pos[0]; fmtsize += pos[0];
@ -574,7 +579,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
} }
} }
size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str())); size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, ' ', str); str = displayPad(fmtsizen, ' ', left, str);
return str; return str;
} }
case '~': // Signed decimal case '~': // Signed decimal
@ -604,7 +609,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
bool zeropad = fmtsize.length()>0 && fmtsize[0]=='0'; bool zeropad = fmtsize.length()>0 && fmtsize[0]=='0';
// fmtsize might have changed since we parsed the %fmtsize // fmtsize might have changed since we parsed the %fmtsize
size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str())); size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, (zeropad ? '0' : ' '), str); str = displayPad(fmtsizen, (zeropad ? '0' : ' '), left, str);
return str; return str;
} }
case 'e': case 'e':
@ -651,7 +656,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
} }
case '@': { // Packed string case '@': { // Packed string
size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str())); size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, ' ', toString()); str = displayPad(fmtsizen, ' ', left, toString());
return str; return str;
} }
default: default:

View File

@ -175,7 +175,7 @@ private:
for (int i=0; i<words(); i++) m_value[i] = m_valueX[i] = 0; for (int i=0; i<words(); i++) m_value[i] = m_valueX[i] = 0;
} }
void setNames(AstNode* nodep); void setNames(AstNode* nodep);
static string displayPad(size_t fmtsize, char pad, const string& in); static string displayPad(size_t fmtsize, char pad, bool left, const string& in);
string displayed(FileLine* fl, const string& vformat) const; string displayed(FileLine* fl, const string& vformat) const;
string displayed(const string& vformat) const { string displayed(const string& vformat) const {
return displayed(m_fileline, vformat); return displayed(m_fileline, vformat);

View File

@ -2706,7 +2706,7 @@ private:
if (!inPct && ch=='%') { if (!inPct && ch=='%') {
inPct = true; inPct = true;
fmt = ch; fmt = ch;
} else if (inPct && (isdigit(ch) || ch=='.')) { } else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) {
fmt += ch; fmt += ch;
} else if (tolower(inPct)) { } else if (tolower(inPct)) {
inPct = false; inPct = false;

View File

@ -51,5 +51,19 @@ extra argument: 0000000000000000
[0] Embedded <#013> return [0] Embedded <#013> return
[0] Embedded [0] Embedded
multiline 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 log10(2) = 2
*-* All Finished *-* *-* All Finished *-*

View File

@ -13,7 +13,10 @@ module t;
reg [31:0] str; initial str = "\000\277\021\n"; reg [31:0] str; initial str = "\000\277\021\n";
reg [47:0] str2; initial str2 = "\000what!"; reg [47:0] str2; initial str2 = "\000what!";
reg [79:0] str3; initial str3 = "\000hmmm!1234"; reg [79:0] str3; initial str3 = "\000hmmm!1234";
int n; initial n = 23;
reg [7:0] m; initial m = 24;
string svs = "sv-str"; string svs = "sv-str";
reg [31:0] regstr = "meep";
sub sub (); sub sub ();
sub2 sub2 (); sub2 sub2 ();
@ -144,6 +147,22 @@ multiline", $time);
if (str !== 32'h00_bf_11_0a) $stop; if (str !== 32'h00_bf_11_0a) $stop;
`endif `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 // $itord conversion bug, note a %d instead of proper float
$display("log10(2) = %d", $log10(100)); $display("log10(2) = %d", $log10(100));