forked from github/verilator
Support with non-format arguments, bug467.
Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
parent
4475060268
commit
49108c23f0
2
Changes
2
Changes
@ -13,6 +13,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
*** Support elaboration assertions, bug973. [Johan Bjork]
|
||||
|
||||
*** Support $display with non-format arguments, bug467. [Jamey Hicks]
|
||||
|
||||
**** Add VerilatedScopeNameMap for introspection, bug966. [Todd Strader]
|
||||
|
||||
**** Ignore %l in $display, bug983. [Todd Strader]
|
||||
|
@ -254,7 +254,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void expectFormat(AstNode* nodep, const string& format, AstNode* argp, bool isScan) {
|
||||
string expectFormat(AstNode* nodep, const string& format, AstNode* argp, bool isScan) {
|
||||
// Check display arguments
|
||||
bool inPct = false;
|
||||
for (string::const_iterator it = format.begin(); it != format.end(); ++it) {
|
||||
@ -290,8 +290,57 @@ private:
|
||||
} // switch
|
||||
}
|
||||
}
|
||||
if (argp) {
|
||||
argp->v3error("Extra arguments for $display-like format");
|
||||
if (argp && !isScan) {
|
||||
int skipCount = 0; // number of args consume by any additional format strings
|
||||
string newFormat(format);
|
||||
while (argp) {
|
||||
if (skipCount) {
|
||||
argp = argp->nextp();
|
||||
skipCount--;
|
||||
continue;
|
||||
}
|
||||
AstConst *constp = argp->castConst();
|
||||
bool isFromString = (constp) ? constp->num().isFromString() : false;
|
||||
if (isFromString) {
|
||||
int numchars = argp->dtypep()->width()/8;
|
||||
string str(numchars, ' ');
|
||||
// now scan for % operators
|
||||
bool inpercent = false;
|
||||
for (int i = 0; i < numchars; i++) {
|
||||
int ii = numchars - i - 1;
|
||||
char c = constp->num().dataByte(ii);
|
||||
str[i] = c;
|
||||
if (!inpercent && c == '%') {
|
||||
inpercent = true;
|
||||
} else if (inpercent) {
|
||||
inpercent = 0;
|
||||
switch (c) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '.':
|
||||
inpercent = true;
|
||||
break;
|
||||
case '%':
|
||||
break;
|
||||
default:
|
||||
if (V3Number::displayedFmtLegal(c)) {
|
||||
skipCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newFormat.append(str);
|
||||
AstNode *nextp = argp->nextp();
|
||||
argp->unlinkFrBack(); pushDeletep(argp); VL_DANGLING(argp);
|
||||
argp = nextp;
|
||||
} else {
|
||||
newFormat.append("%h");
|
||||
argp = argp->nextp();
|
||||
}
|
||||
}
|
||||
return newFormat;
|
||||
} else {
|
||||
return string();
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,7 +371,9 @@ private:
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectFormat(nodep, nodep->text(), nodep->exprsp(), false);
|
||||
string newFormat = expectFormat(nodep, nodep->text(), nodep->exprsp(), false);
|
||||
if (newFormat.size())
|
||||
nodep->text(newFormat);
|
||||
if ((nodep->backp()->castDisplay() && nodep->backp()->castDisplay()->displayType().needScopeTracking())
|
||||
|| nodep->formatScopeTracking()) {
|
||||
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||
|
@ -205,6 +205,7 @@ public:
|
||||
double toDouble() const;
|
||||
uint32_t toHash() const;
|
||||
uint32_t dataWord(int word) const;
|
||||
uint8_t dataByte(int byte) const { return (dataWord(byte/4) >> (8*(byte&3))) & 0xff; }
|
||||
uint32_t countOnes() const;
|
||||
uint32_t mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0.
|
||||
|
||||
|
@ -28,6 +28,9 @@ execute (
|
||||
|
||||
[0] %s=! %s= what! %s= hmmm!1234
|
||||
[0] hello, from a very long string. Percent %s are literally substituted in.
|
||||
hello, from a concatenated string.
|
||||
hello, from a concatenated format string [0].
|
||||
extra argument: 0000000000000000
|
||||
[0] Embedded <#013> return
|
||||
[0] Embedded
|
||||
multiline
|
||||
|
@ -43,6 +43,9 @@ module t;
|
||||
|
||||
$display("[%0t] %s%s%s", $time,
|
||||
"hel", "lo, fr", "om a very long string. Percent %s are literally substituted in.");
|
||||
$display("hel", "lo, fr", "om a concatenated string.");
|
||||
$write("hel", "lo, fr", "om a concatenated format string [%0t].\n", $time);
|
||||
$display("extra argument: ", $time);
|
||||
$write("[%0t] Embedded \r return\n", $time);
|
||||
$display("[%0t] Embedded\
|
||||
multiline", $time);
|
||||
|
@ -12,7 +12,6 @@ compile (
|
||||
fails=>1,
|
||||
expect=>
|
||||
'%Error: t/t_display_bad.v:\d+: Missing arguments for \$display-like format
|
||||
%Error: t/t_display_bad.v:\d+: Extra arguments for \$display-like format
|
||||
%Error: t/t_display_bad.v:\d+: Unknown \$display-like format code: %q
|
||||
%Error: Exiting due to.*',
|
||||
);
|
||||
|
@ -31,6 +31,9 @@ execute (
|
||||
|
||||
[0] %s=! %s= what! %s= hmmm!1234
|
||||
[0] hello, from a very long string. Percent %s are literally substituted in.
|
||||
hello, from a concatenated string.
|
||||
hello, from a concatenated format string [0].
|
||||
extra argument: 0000000000000000
|
||||
[0] Embedded <#013> return
|
||||
[0] Embedded
|
||||
multiline
|
||||
|
Loading…
Reference in New Issue
Block a user