From 4ba00bd25611f4ca31a96a28771b1d6353267a58 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 14 Jun 2007 17:29:37 +0000 Subject: [PATCH] Propagate constants into displays git-svn-id: file://localhost/svn/verilator/trunk/verilator@937 77ca24e4-aefa-0310-84f0-b9a241c72d87 --- src/V3Const.cpp | 51 +++++++++++++++++++++++++++++++ src/V3Number.cpp | 20 ++++++------ test_regress/t/t_display_noopt.pl | 36 ++++++++++++++++++++++ 3 files changed, 98 insertions(+), 9 deletions(-) create mode 100755 test_regress/t/t_display_noopt.pl diff --git a/src/V3Const.cpp b/src/V3Const.cpp index cbdb07bab..4cd82c195 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -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 "<text()<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: "< "<unlinkFrBack()->deleteTree(); + } + argp=nextp; + } + break; + } // switch + dispout += fmt; + } else { + dispout += ch; + } + } + nodep->text(dispout); + //UINFO(9," Display out "<text()<iterateChildren(*this); if (nodep->condp()->isZero()) { diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 1cff44408..764f2d673 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -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; diff --git a/test_regress/t/t_display_noopt.pl b/test_regress/t/t_display_noopt.pl new file mode 100755 index 000000000..55373ae46 --- /dev/null +++ b/test_regress/t/t_display_noopt.pl @@ -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;