From fdcbedef8f44a18c558d472f9d155aad38e33269 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Jun 2008 08:45:05 -0400 Subject: [PATCH] Add support --- Changes | 2 +- bin/verilator | 2 +- src/V3AstNodes.h | 23 +++++++++++++++++++++++ src/V3EmitC.cpp | 7 +++++++ src/V3EmitV.cpp | 6 ++++++ src/V3LinkLValue.cpp | 8 ++++++++ src/V3LinkResolve.cpp | 4 ++++ src/V3Width.cpp | 3 +++ src/verilog.l | 1 + src/verilog.y | 4 ++++ test_regress/t/t_sys_file.v | 1 + 11 files changed, 59 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index cc43113c1..ef682d4ed 100644 --- a/Changes +++ b/Changes @@ -5,7 +5,7 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.66* -*** Support $feof. [Holger Waechtler] +*** Support $feof, $fflush. [Holger Waechtler] * Verilator 3.665 2008/06/25 diff --git a/bin/verilator b/bin/verilator index dca88108a..50e8cd037 100755 --- a/bin/verilator +++ b/bin/verilator @@ -1554,7 +1554,7 @@ them with a $write with the appropriate format specifier. The rarely used optional parameter to $finish and $stop is ignored. -=item $fopen, $fclose, $fdisplay, $feof, $fwrite +=item $fopen, $fclose, $fdisplay, $feof, $fflush, $fwrite File descriptors passed to the file PLI calls must be file descriptors, not MCDs, which includes the mode parameter to $fopen being mandatory. diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 4936b7295..ea9f4ff0e 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1323,6 +1323,29 @@ struct AstFOpen : public AstNodeStmt { AstNode* modep() const { return op3p(); } }; +struct AstFFlush : public AstNodeStmt { + // Parents: stmtlist + // Children: file which must be a varref + AstFFlush(FileLine* fileline, AstNode* filep) + : AstNodeStmt (fileline) { + setNOp2p(filep); + } + virtual ~AstFFlush() {} + virtual AstType type() const { return AstType::FFLUSH;} + virtual AstNode* clone() { return new AstFFlush(*this); } + virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); } + virtual string verilogKwd() const { return "$fflush"; }; + virtual bool isGateOptimizable() const { return false; } + virtual bool isPredictOptimizable() const { return false; } + virtual bool isSplittable() const { return false; } + virtual bool isOutputter() const { return true; } + virtual bool isUnlikely() const { return true; } + virtual V3Hash sameHash() const { return V3Hash(); } + virtual bool same(AstNode* samep) const { return true; } + AstNode* filep() const { return op2p(); } + void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } +}; + struct AstReadMem : public AstNodeStmt { private: bool m_isHex; // readmemh, not readmemb diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 1f7afcb80..f6ce6b9a5 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -299,6 +299,13 @@ public: nodep->filep()->iterateAndNext(*this); puts(")) : true)"); // Non-existant filehandle should return EOF } + virtual void visit(AstFFlush* nodep, AstNUser*) { + puts("if ("); + nodep->filep()->iterateAndNext(*this); + puts(") { fflush (VL_CVT_Q_FP("); + nodep->filep()->iterateAndNext(*this); + puts(")); "); + } virtual void visit(AstWhile* nodep, AstNUser*) { nodep->precondsp()->iterateAndNext(*this); puts("while ("); diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 6875ed8af..bb0c27c31 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -192,6 +192,12 @@ public: if (nodep->filep()) nodep->filep()->iterateChildren(*this); puts(");\n"); } + virtual void visit(AstFFlush* nodep, AstNUser*) { + putbs(nodep->verilogKwd()); + putbs(" ("); + if (nodep->filep()) nodep->filep()->iterateChildren(*this); + puts(");\n"); + } virtual void visit(AstReadMem* nodep, AstNUser*) { putbs(nodep->verilogKwd()); putbs(" ("); diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 5399b44c6..5d925f420 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -108,6 +108,14 @@ private: } m_setRefLvalue = last_setRefLvalue; } + virtual void visit(AstFFlush* nodep, AstNUser*) { + bool last_setRefLvalue = m_setRefLvalue; + { + m_setRefLvalue = true; + nodep->filep()->iterateAndNext(*this); + } + m_setRefLvalue = last_setRefLvalue; + } virtual void visit(AstReadMem* nodep, AstNUser*) { bool last_setRefLvalue = m_setRefLvalue; { diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index fe2ceebe6..5bd4abe1d 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -328,6 +328,10 @@ private: nodep->iterateChildren(*this); expectDescriptor(nodep, nodep->filep()->castNodeVarRef()); } + virtual void visit(AstFFlush* nodep, AstNUser*) { + nodep->iterateChildren(*this); + expectDescriptor(nodep, nodep->filep()->castNodeVarRef()); + } virtual void visit(AstDisplay* nodep, AstNUser*) { nodep->iterateChildren(*this); if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef()); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index a118bcf3c..7f0b527d8 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -574,6 +574,9 @@ private: nodep->lhsp()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); nodep->width(1,1); } + virtual void visit(AstFFlush* nodep, AstNUser*) { + nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); + } virtual void visit(AstReadMem* nodep, AstNUser*) { nodep->filenamep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); nodep->memp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); diff --git a/src/verilog.l b/src/verilog.l index 0fb2b2afa..c1c2d01f8 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -133,6 +133,7 @@ escid \\[^ \t\f\r\n]+ "$fclose" {yylval.fileline = CRELINE(); return yD_FCLOSE;} "$fdisplay" {yylval.fileline = CRELINE(); return yD_FDISPLAY;} "$feof" {yylval.fileline = CRELINE(); return yD_FEOF;} + "$fflush" {yylval.fileline = CRELINE(); return yD_FFLUSH;} "$finish" {yylval.fileline = CRELINE(); return yD_FINISH;} "$fopen" {yylval.fileline = CRELINE(); return yD_FOPEN;} "$fullskew" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;} diff --git a/src/verilog.y b/src/verilog.y index 267b91dfc..2789ed574 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -227,6 +227,7 @@ class AstSenTree; %token yD_FCLOSE "$fclose" %token yD_FDISPLAY "$fdisplay" %token yD_FEOF "$feof" +%token yD_FFLUSH "$fflush" %token yD_FINISH "$finish" %token yD_FOPEN "$fopen" %token yD_FWRITE "$fwrite" @@ -896,6 +897,9 @@ stmt: ';' { $$ = NULL; } | '{' concIdList '}' '=' delayE expr ';' { $$ = new AstAssign($4,$2,$6); } | yD_C '(' cStrList ')' ';' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); } | yD_FCLOSE '(' varRefDotBit ')' ';' { $$ = new AstFClose($1, $3); } + | yD_FFLUSH ';' { $1->v3error("Unsupported: $fflush of all handles does not map to C++.\n"); } + | yD_FFLUSH '(' ')' ';' { $1->v3error("Unsupported: $fflush of all handles does not map to C++.\n"); } + | yD_FFLUSH '(' varRefDotBit ')' ';' { $$ = new AstFClose($1, $3); } | yD_FINISH parenE ';' { $$ = new AstFinish($1); } | yD_FINISH '(' expr ')' ';' { $$ = new AstFinish($1); } | yD_STOP parenE ';' { $$ = new AstStop($1); } diff --git a/test_regress/t/t_sys_file.v b/test_regress/t/t_sys_file.v index 8d60ac7c7..1f4f24885 100644 --- a/test_regress/t/t_sys_file.v +++ b/test_regress/t/t_sys_file.v @@ -21,6 +21,7 @@ module t; $fdisplay(file, "[%0t] hello v=%x", $time, 32'h12345667); $fwrite(file, "[%0t] %s\n", $time, "Hello2"); + $fflush(file); $fclose(file); `ifdef verilator