mirror of
https://github.com/verilator/verilator.git
synced 2025-01-08 23:57:35 +00:00
Internals: Add AstSFormatF
This commit is contained in:
parent
788f69a8c9
commit
0d1de96dbc
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
20
src/V3Ast.h
20
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;
|
||||
|
@ -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); }
|
||||
};
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 "<<nodep->text()<<endl);
|
||||
|
@ -738,7 +738,7 @@ private:
|
||||
widthCheck(nodep,"Assign RHS",nodep->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
|
||||
|
@ -2064,6 +2064,7 @@ system_f_call<nodep>: // 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); }
|
||||
|
Loading…
Reference in New Issue
Block a user