From 27e4503dc6aec4a662773b7ba9c03eede06807e8 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 17 Jan 2010 20:06:08 -0500 Subject: [PATCH] DPI: Constify new $sformatf --- src/V3AstNodes.h | 39 +++++++++++++++++++++++++++++++---- src/V3Const.cpp | 18 ++++++++++++++++ src/V3EmitC.cpp | 3 +++ src/V3EmitV.cpp | 4 ++++ src/V3Width.cpp | 5 ++++- src/verilog.y | 2 +- test_regress/t/t_dpi_import.v | 7 +++++++ 7 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 333414236..aff226034 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -83,6 +83,34 @@ public: virtual int instrCount() const { return widthInstrs(); } }; +struct AstConstString : public AstNodeMath { + // A constant string +private: + string m_name; +public: + AstConstString(FileLine* fl, const string& name) + : AstNodeMath(fl), m_name(name) { + rewidth(); + } + void rewidth() { + if (m_name.length()==0) { + width(1,1); // 0 width isn't allowed due to historic special cases + } else { + width(m_name.length()*8, m_name.length()*8); + } + } + ASTNODE_NODE_FUNCS(ConstString, CONSTSTRING) + virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially + virtual string emitC() { V3ERROR_NA; return ""; } + virtual bool cleanOut() { return true; } + virtual V3Hash sameHash() const { return V3Hash(name()); } + virtual bool same(AstNode* samep) const { + return name()==samep->castConstString()->name(); } + virtual int instrCount() const { return 2; } // C just loads a pointer + virtual string name() const { return m_name; } + void name(const string& flag) { m_name = flag; rewidth(); } +}; + struct AstRange : public AstNode { // Range specification, for use under variables and cells private: @@ -1511,10 +1539,12 @@ public: class AstSFormatF : public AstNode { // Convert format to string, generally under a AstDisplay or AstSFormat + // Also used as "real" function for /*verilator sformat*/ functions string m_text; + bool m_hidden; // Under display, etc public: - AstSFormatF(FileLine* fl, const string& text, AstNode* exprsp) - : AstNode(fl), m_text(text) { + AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNode* exprsp) + : AstNode(fl), m_text(text), m_hidden(hidden) { addNOp1p(exprsp); addNOp2p(NULL); } ASTNODE_NODE_FUNCS(SFormatF, SFORMATF) virtual string name() const { return m_text; } @@ -1530,6 +1560,7 @@ public: void scopeNamep(AstNode* nodep) { setNOp2p(nodep); } bool formatScopeTracking() const { // Track scopeNamep(); Ok if false positive return (name().find("%m") != string::npos || name().find("%M") != string::npos); } + bool hidden() const { return m_hidden; } }; struct AstDisplay : public AstNode { @@ -1541,7 +1572,7 @@ private: public: AstDisplay(FileLine* fileline, AstDisplayType dispType, const string& text, AstNode* filep, AstNode* exprsp) : AstNode (fileline) { - setNOp1p(new AstSFormatF(fileline,text,exprsp)); + setOp1p(new AstSFormatF(fileline,text,true,exprsp)); setNOp3p(filep); m_displayType = dispType; } @@ -1573,7 +1604,7 @@ struct AstSFormat : public AstNode { // Children: SFORMATF to generate print string AstSFormat(FileLine* fileline, AstNode* lhsp, const string& text, AstNode* exprsp) : AstNode (fileline) { - setOp1p(new AstSFormatF(fileline,text,exprsp)); + setOp1p(new AstSFormatF(fileline,text,true,exprsp)); setOp3p(lhsp); } ASTNODE_NODE_FUNCS(SFormat, SFORMAT) diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 005b4549b..8eb7feca9 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -432,6 +432,15 @@ private: replaceNum(nodep, num); nodep=NULL; } + void replaceConstString (AstNode* oldp, const string& num) { + // Replace oldp node with a constant set to specified value + UASSERT (oldp, "Null old\n"); + AstNode* newp = new AstConstString(oldp->fileline(), num); + if (debug()>5) oldp->dumpTree(cout," const_old: "); + if (debug()>5) newp->dumpTree(cout," _new: "); + oldp->replaceWith(newp); + oldp->deleteTree(); oldp=NULL; + } //---------------------------------------- // Replacement functions. // These all take a node and replace it with something else @@ -1459,6 +1468,12 @@ private: nodep->text(dispout); //UINFO(9," Display out "<text()<exprsp() + && nodep->name().find("%") == string::npos + && !nodep->hidden()) { + // Just a simple constant string - the formatting is pointless + replaceConstString(nodep, nodep->name()); nodep=NULL; + } } virtual void visit(AstFuncRef* nodep, AstNUser*) { @@ -1712,6 +1727,9 @@ private: TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}"); TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}"); + // Strings + TREEOP ("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())"); + // Possible futures: // (a?(b?y:x):y) -> (a&&!b)?x:y diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index b282f1ae3..f70608083 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -563,6 +563,9 @@ public: emitConstant(nodep, NULL, ""); } } + virtual void visit(AstConstString* nodep, AstNUser*) { + putsQuoted(nodep->name()); + } // Just iterate virtual void visit(AstNetlist* nodep, AstNUser*) { diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index b617b2292..208965cd0 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -456,6 +456,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { virtual void visit(AstConst* nodep, AstNUser*) { putfs(nodep,nodep->num().ascii(true,true)); } + virtual void visit(AstConstString* nodep, AstNUser*) { + putfs(nodep,""); + putsQuoted(nodep->name()); + } // Just iterate virtual void visit(AstTopScope* nodep, AstNUser*) { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index cd075210f..8a1872d62 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -448,6 +448,9 @@ private: // We don't size the constant until we commit the widths, as need parameters // to remain unsized, and numbers to remain unsized to avoid backp() warnings } + virtual void visit(AstConstString* nodep, AstNUser* vup) { + nodep->rewidth(); + } virtual void visit(AstRand* nodep, AstNUser* vup) { if (vup->c()->prelim()) { nodep->width(32,32); // Says the spec @@ -962,7 +965,7 @@ private: string format; if (pinp->castConst()) format = pinp->castConst()->num().toString(); else pinp->v3error("Format to $display-like function must have constant format string"); - AstSFormatF* newp = new AstSFormatF(nodep->fileline(), format, argsp); + AstSFormatF* newp = new AstSFormatF(nodep->fileline(), format, false, argsp); if (!newp->scopeNamep() && newp->formatScopeTracking()) { newp->scopeNamep(new AstScopeName(newp->fileline())); } diff --git a/src/verilog.y b/src/verilog.y index 2f486f109..86d78fecd 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2066,7 +2066,7 @@ system_f_call: // IEEE: system_tf_call (as func) | yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); } | yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); } | yD_RANDOM parenE { $$ = new AstRand($1); } - //| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,$4); } // Have AST, just need testing and debug + //| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug | yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); } | yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); } | yD_TIME parenE { $$ = new AstTime($1); } diff --git a/test_regress/t/t_dpi_import.v b/test_regress/t/t_dpi_import.v index 85ffa091c..582479c67 100644 --- a/test_regress/t/t_dpi_import.v +++ b/test_regress/t/t_dpi_import.v @@ -98,6 +98,8 @@ module t (); bit [127:0] wide; + bit [6*8:1] string6; + initial begin wide = 128'h36f3e51d15caff7a73c48afee4ffcb57; @@ -165,6 +167,11 @@ module t (); if (dpii_f_strlen ("stri")!=4) $stop; if (dpii_f_strlen ("string_l")!=8) $stop; if (dpii_f_strlen ("string_len")!=10) $stop; + string6 = "hello6"; +`ifdef VERILATOR + string6 = $c48(string6); // Don't optimize away - want to see the constant conversion function +`endif + if (dpii_f_strlen (string6) != 6) $stop; dpii_f_void(); dpii_t_void();