Propagate constants into displays

git-svn-id: file://localhost/svn/verilator/trunk/verilator@937 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2007-06-14 17:29:37 +00:00
parent c18f9da400
commit 4ba00bd256
3 changed files with 98 additions and 9 deletions

View File

@ -938,6 +938,57 @@ private:
}
}
virtual void visit(AstDisplay* nodep, AstNUser*) {
// Substitute constants into displays. The main point of this is to
// simplify assertion methodologies which call functions with display's.
// This eliminates a pile of wide temps, and makes the C a whole lot more readable.
nodep->iterateChildren(*this);
bool anyconst = false;
for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) {
if (argp->castConst()) { anyconst=true; break; }
}
if (anyconst) {
//UINFO(9," Display in "<<nodep->text()<<endl);
string dispout = "";
string fmt = "";
bool inPct = false;
AstNode* argp = nodep->exprsp();
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
char ch = *inp; // Breaks with iterators...
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;
} else if (inPct && isdigit(ch)) {
fmt += ch;
} else if (inPct) {
inPct = false;
fmt += ch;
switch (tolower(ch)) {
case '%': break; // %% - just output a %
case 'm': break; // %m - auto insert "name"
default: // Most operators, just move to next argument
if (argp) {
AstNode* nextp=argp->nextp();
if (argp && argp->castConst()) { // Convert it
string out = argp->castConst()->num().displayed(fmt);
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
fmt = out;
argp->unlinkFrBack()->deleteTree();
}
argp=nextp;
}
break;
} // switch
dispout += fmt;
} else {
dispout += ch;
}
}
nodep->text(dispout);
//UINFO(9," Display out "<<nodep->text()<<endl);
}
}
virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->condp()->isZero()) {

View File

@ -357,8 +357,8 @@ string V3Number::displayed(const string& vformat) const {
switch (code) {
case 'b': {
int bit = width()-1;
if (fmtsize != "0") while (bit && bitIs0(bit)) bit--;
for (; bit>0; bit--) {
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
for (; bit>=0; bit--) {
if (bitIs0(bit)) str+='0';
else if (bitIs1(bit)) str+='1';
else if (bitIsZ(bit)) str+='z';
@ -368,8 +368,8 @@ string V3Number::displayed(const string& vformat) const {
}
case 'o': {
int bit = width()-1;
if (fmtsize != "0") while (bit && bitIs0(bit)) bit--;
while ((bit&2)!=2) bit++;
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
while ((bit%3)!=2) bit++;
for (; bit>0; bit -= 3) {
int v = bitsValue(bit-2, 3);
str += (char)('0'+v);
@ -379,8 +379,8 @@ string V3Number::displayed(const string& vformat) const {
case 'h':
case 'x': {
int bit = width()-1;
if (fmtsize != "0") while (bit && bitIs0(bit)) bit--;
while ((bit&3)!=3) bit++;
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
while ((bit%4)!=3) bit++;
for (; bit>0; bit -= 4) {
int v = bitsValue(bit-3, 4);
if (v>=10) str += (char)('a'+v-10);
@ -395,15 +395,17 @@ string V3Number::displayed(const string& vformat) const {
return str;
}
case 's': {
// Spec says always drop leading zeros
// Spec says always drop leading zeros, this isn't quite right, we space pad.
int bit=this->width()-1;
bool start=true;
while ((bit&7)!=7) bit++;
while ((bit%8)!=7) bit++;
for (; bit>=0; bit -= 8) {
int v = bitsValue(bit-7, 8);
if (!start || v) {
str = (char)((v==0)?' ':v);
str += (char)((v==0)?' ':v);
start = false; // Drop leading 0s
} else {
if (fmtsize != "0") str += ' ';
}
}
return str;

View File

@ -0,0 +1,36 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
top_filename("t/t_display.v");
compile (
v_flags2 => [$Last_Self->{v3}?"-O0":""],
);
execute (
check_finished=>1,
expect=>quotemeta(
'[0] In TOP.v: Hi
[0] In TOP.v.sub
[0] In TOP.v.sub.subblock
[0] In TOP.v.sub2
[0] In TOP.v.sub2.subblock2
[0] %X=0c %D=12 %0X=c %0O=14 %B=001100
[0] %x=0c %d=12 %0x=c %0o=14 %b=001100
[0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. This gets substituted in.
*-* All Finished *-*
'),
);
ok(1);
1;