From 0d1de96dbc54b59bfc5c809689d89ce648ec63b6 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 17 Jan 2010 15:53:12 -0500 Subject: [PATCH] Internals: Add AstSFormatF --- src/V3Assert.cpp | 10 ++++---- src/V3Ast.h | 20 ---------------- src/V3AstNodes.h | 56 +++++++++++++++++++++++++++++++------------ src/V3Clean.cpp | 2 +- src/V3Const.cpp | 2 +- src/V3EmitC.cpp | 18 +++++++------- src/V3EmitV.cpp | 4 ++-- src/V3LinkLValue.cpp | 2 +- src/V3LinkResolve.cpp | 12 +++------- src/V3Signed.cpp | 2 +- src/V3Width.cpp | 2 +- src/verilog.y | 1 + 12 files changed, 66 insertions(+), 65 deletions(-) diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index c9392783e..cda004d17 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -61,12 +61,12 @@ private: } void replaceDisplay(AstDisplay* nodep, const string& prefix) { nodep->displayType(AstDisplayType::WRITE); - nodep->text(assertDisplayMessage(nodep, prefix, nodep->text())); - AstNode* timesp = nodep->exprsp(); if (timesp) timesp->unlinkFrBack(); + nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text())); + AstNode* timesp = nodep->fmtp()->exprsp(); if (timesp) timesp->unlinkFrBack(); timesp = timesp->addNext(new AstTime(nodep->fileline())); - nodep->exprsp(timesp); - if (!nodep->scopeNamep() && nodep->formatScopeTracking()) { - nodep->scopeNamep(new AstScopeName(nodep->fileline())); + nodep->fmtp()->exprsp(timesp); + if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) { + nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline())); } } diff --git a/src/V3Ast.h b/src/V3Ast.h index 71879186b..4aea8df67 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1194,26 +1194,6 @@ public: void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } }; -class AstNodeDisplay : public AstNodeStmt { - // AstDisplay, AstSFormat or anything else with a format that might have %m - string m_text; -public: - AstNodeDisplay(FileLine* fl, const string& text, AstNode* exprsp) - : AstNodeStmt(fl), m_text(text) { - addNOp1p(exprsp); addNOp2p(NULL); } - ASTNODE_BASE_FUNCS(NodeDisplay) - virtual string name() const { return m_text; } - virtual int instrCount() const { return instrCountPli(); } - void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output - AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output - string text() const { return m_text; } // * = Text to display - void text(const string& text) { m_text=text; } - AstScopeName* scopeNamep() const { return op2p()->castScopeName(); } - void scopeNamep(AstNode* nodep) { setNOp2p(nodep); } - bool formatScopeTracking() const { // Track scopeNamep(); Ok if over-eager - return (name().find("%m") != string::npos || name().find("%M") != string::npos); } -}; - struct AstNodeText : public AstNode { private: string m_text; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index d6fae4744..0af2d0568 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1506,14 +1506,38 @@ public: void ignoreOverlap(bool flag) { m_ignoreOverlap = flag; } }; -struct AstDisplay : public AstNodeDisplay { +class AstSFormatF : public AstNode { + // Convert format to string, generally under a AstDisplay or AstSFormat + string m_text; +public: + AstSFormatF(FileLine* fl, const string& text, AstNode* exprsp) + : AstNode(fl), m_text(text) { + addNOp1p(exprsp); addNOp2p(NULL); } + ASTNODE_NODE_FUNCS(SFormatF, SFORMATF) + virtual string name() const { return m_text; } + virtual int instrCount() const { return instrCountPli(); } + virtual V3Hash sameHash() const { return V3Hash(text()); } + virtual bool same(AstNode* samep) const { return text()==samep->castSFormatF()->text(); } + void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output + AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output + string text() const { return m_text; } // * = Text to display + void text(const string& text) { m_text=text; } + AstScopeName* scopeNamep() const { return op2p()->castScopeName(); } + 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); } +}; + +struct AstDisplay : public AstNode { // Parents: stmtlist - // Children: file which must be a varref, MATH to print + // Children: file which must be a varref + // Children: SFORMATF to generate print string private: AstDisplayType m_displayType; public: AstDisplay(FileLine* fileline, AstDisplayType dispType, const string& text, AstNode* filep, AstNode* exprsp) - : AstNodeDisplay (fileline, text, exprsp) { + : AstNode (fileline) { + setNOp1p(new AstSFormatF(fileline,text,exprsp)); setNOp3p(filep); m_displayType = dispType; } @@ -1526,24 +1550,25 @@ public: virtual bool isSplittable() const { return false; } // SPECIAL: $display has 'visual' ordering virtual bool isOutputter() const { return true; } // SPECIAL: $display makes output virtual bool isUnlikely() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(text()); } - virtual bool same(AstNode* samep) const { - return displayType()==samep->castDisplay()->displayType() - && text()==samep->castDisplay()->text(); } - // op1,op2 used by AstNodeDisplay + virtual V3Hash sameHash() const { return V3Hash(displayType()); } + virtual bool same(AstNode* samep) const { return displayType()==samep->castDisplay()->displayType(); } + virtual int instrCount() const { return instrCountPli(); } AstDisplayType displayType() const { return m_displayType; } void displayType(AstDisplayType type) { m_displayType = type; } bool addNewline() const { return displayType().addNewline(); } // * = Add a newline for $display + void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter + AstSFormatF* fmtp() const { return op1p()->castSFormatF(); } AstNode* filep() const { return op3p(); } void filep(AstNodeVarRef* nodep) { setNOp3p(nodep); } }; -struct AstSFormat : public AstNodeDisplay { +struct AstSFormat : public AstNode { // Parents: statement container // Children: string to load - // Children: varrefs to print + // Children: SFORMATF to generate print string AstSFormat(FileLine* fileline, AstNode* lhsp, const string& text, AstNode* exprsp) - : AstNodeDisplay (fileline, text, exprsp) { + : AstNode (fileline) { + setOp1p(new AstSFormatF(fileline,text,exprsp)); setOp3p(lhsp); } ASTNODE_NODE_FUNCS(SFormat, SFORMAT) @@ -1555,10 +1580,11 @@ struct AstSFormat : public AstNodeDisplay { virtual bool isSplittable() const { return true; } virtual bool isOutputter() const { return false; } virtual bool cleanOut() { return false; } - virtual V3Hash sameHash() const { return V3Hash(text()); } - virtual bool same(AstNode* samep) const { - return text()==samep->castSFormat()->text(); } - // op1,op2 used by AstNodeDisplay + virtual int instrCount() const { return instrCountPli(); } + virtual V3Hash sameHash() const { return V3Hash(); } + virtual bool same(AstNode* samep) const { return true; } + void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter + AstSFormatF* fmtp() const { return op1p()->castSFormatF(); } AstNode* lhsp() const { return op3p(); } void lhsp(AstNode* nodep) { setOp3p(nodep); } }; diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index af1d9aefc..908f38d78 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -240,7 +240,7 @@ private: nodep->iterateChildren(*this); insureClean(nodep->condp()); } - virtual void visit(AstNodeDisplay* nodep, AstNUser*) { + virtual void visit(AstSFormatF* nodep, AstNUser*) { nodep->iterateChildren(*this); insureCleanAndNext (nodep->exprsp()); } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 2a8afeea6..005b4549b 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1404,7 +1404,7 @@ private: } } - virtual void visit(AstNodeDisplay* nodep, AstNUser*) { + virtual void visit(AstSFormatF* 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. diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index a453c29d9..3b8fb3988 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -63,7 +63,8 @@ public: && v3Global.opt.outputSplit() < splitSize()); } // METHODS - void displayNode(AstNode* nodep, const string& vformat, AstNode* exprsp, bool isScan); + void displayNode(AstNode* nodep, AstScopeName* scopenamep, + const string& vformat, AstNode* exprsp, bool isScan); void displayEmit(AstNode* nodep, bool isScan); void displayArg(AstNode* dispp, AstNode** elistp, bool isScan, string vfmt, char fmtLetter); @@ -203,9 +204,9 @@ public: puts(");\n"); } virtual void visit(AstDisplay* nodep, AstNUser*) { - string text = nodep->text(); + string text = nodep->fmtp()->text(); if (nodep->addNewline()) text += "\n"; - displayNode(nodep, text, nodep->exprsp(), false); + displayNode(nodep, nodep->fmtp()->scopeNamep(), text, nodep->fmtp()->exprsp(), false); } virtual void visit(AstScopeName* nodep, AstNUser*) { // For use under AstCCalls for dpiImports. ScopeNames under displays are handled in AstDisplay @@ -214,13 +215,13 @@ public: } } virtual void visit(AstSFormat* nodep, AstNUser*) { - displayNode(nodep, nodep->text(), nodep->exprsp(), false); + displayNode(nodep, nodep->fmtp()->scopeNamep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp(), false); } virtual void visit(AstFScanF* nodep, AstNUser*) { - displayNode(nodep, nodep->text(), nodep->exprsp(), true); + displayNode(nodep, NULL, nodep->text(), nodep->exprsp(), true); } virtual void visit(AstSScanF* nodep, AstNUser*) { - displayNode(nodep, nodep->text(), nodep->exprsp(), true); + displayNode(nodep, NULL, nodep->text(), nodep->exprsp(), true); } virtual void visit(AstValuePlusArgs* nodep, AstNUser*) { string prefix; @@ -1150,7 +1151,8 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, *elistp = (*elistp)->nextp(); } -void EmitCStmts::displayNode(AstNode* nodep, const string& vformat, AstNode* exprsp, +void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep, + const string& vformat, AstNode* exprsp, bool isScan) { AstNode* elistp = exprsp; @@ -1193,8 +1195,6 @@ void EmitCStmts::displayNode(AstNode* nodep, const string& vformat, AstNode* exp case 'm': { emitDispState.pushFormat("%S"); emitDispState.pushArg(NULL, "vlSymsp->name()"); - if (!nodep->castNodeDisplay()) nodep->v3fatalSrc("Non-Display with %m"); - AstScopeName* scopenamep = nodep->castNodeDisplay()->scopeNamep(); if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName"); emitDispState.pushFormat(scopenamep->scopePrettyName()); break; diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 2d700dba3..6fa5b3628 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -196,7 +196,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { puts(");\n"); } virtual void visit(AstDisplay* nodep, AstNUser*) { - visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp()); + visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); } virtual void visit(AstFScanF* nodep, AstNUser*) { visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp()); @@ -205,7 +205,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp()); } virtual void visit(AstSFormat* nodep, AstNUser*) { - visitNodeDisplay(nodep, nodep->lhsp(), nodep->text(), nodep->exprsp()); + visitNodeDisplay(nodep, nodep->lhsp(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); } virtual void visit(AstValuePlusArgs* nodep, AstNUser*) { visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp()); diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index e81a71ee5..2f6a43df0 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -180,7 +180,7 @@ private: m_setRefLvalue = true; nodep->lhsp()->iterateAndNext(*this); m_setRefLvalue = false; - nodep->exprsp()->iterateAndNext(*this); + nodep->fmtp()->iterateAndNext(*this); } m_setRefLvalue = last_setRefLvalue; } diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 17e46d291..7c40355eb 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -311,22 +311,16 @@ private: nodep->iterateChildren(*this); expectFormat(nodep, nodep->text(), nodep->exprsp(), true); } - - void expectNodeDisplay(AstNodeDisplay* nodep) { - // AstSFormat also handled here + virtual void visit(AstSFormatF* nodep, AstNUser*) { + nodep->iterateChildren(*this); expectFormat(nodep, nodep->text(), nodep->exprsp(), false); - if ((nodep->castDisplay() && nodep->castDisplay()->displayType().needScopeTracking()) + if ((nodep->backp()->castDisplay() && nodep->backp()->castDisplay()->displayType().needScopeTracking()) || nodep->formatScopeTracking()) { nodep->scopeNamep(new AstScopeName(nodep->fileline())); } } - virtual void visit(AstNodeDisplay* nodep, AstNUser*) { - nodep->iterateChildren(*this); - expectNodeDisplay(nodep); - } virtual void visit(AstDisplay* nodep, AstNUser* vup) { nodep->iterateChildren(*this); - expectNodeDisplay(nodep); if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef()); if (!m_assertp && (nodep->displayType() == AstDisplayType::INFO diff --git a/src/V3Signed.cpp b/src/V3Signed.cpp index 7984fdc7c..61300961f 100644 --- a/src/V3Signed.cpp +++ b/src/V3Signed.cpp @@ -195,7 +195,7 @@ private: } // VISITORS - Special - virtual void visit(AstNodeDisplay* nodep, AstNUser*) { + virtual void visit(AstSFormatF* nodep, AstNUser*) { nodep->iterateChildren(*this); // UINFO(9," Display in "<text()<rhsp(),awidth,awidth); //if (debug()) nodep->dumpTree(cout," AssignOut: "); } - virtual void visit(AstNodeDisplay* nodep, AstNUser*) { + virtual void visit(AstSFormatF* nodep, AstNUser*) { // Excludes NodeDisplay, see below // TOP LEVEL NODE // Just let all arguments seek their natural sizes diff --git a/src/verilog.y b/src/verilog.y index 85e336989..0ef58858d 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2064,6 +2064,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_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); } | yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); } | yD_TIME parenE { $$ = new AstTime($1); }