From 259201b3522ebf103b2c21ca0d436bd17c956813 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 11 Mar 2023 18:11:01 -0500 Subject: [PATCH] Support $fopen as an expression --- Changes | 2 ++ src/V3AstNodeExpr.h | 40 +++++++++++++++++++++++++ src/V3AstNodeOther.h | 40 ------------------------- src/V3EmitCFunc.h | 6 ++-- src/V3LinkLValue.cpp | 50 ++++---------------------------- src/V3LinkResolve.cpp | 8 ----- src/V3Width.cpp | 6 ++-- src/verilog.y | 4 +-- test_regress/t/t_debug_emitv.out | 6 ++-- 9 files changed, 57 insertions(+), 105 deletions(-) diff --git a/Changes b/Changes index bacce15df..4c45d300d 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,8 @@ Verilator 5.009 devel **Minor:** +* Support $fopen as an expression. + Verilator 5.008 2023-03-04 ========================== diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index 3ccc3a36f..4ec2b90c1 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -1112,6 +1112,46 @@ public: bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering bool same(const AstNode* /*samep*/) const override { return true; } }; +class AstFOpen final : public AstNodeExpr { + // @astgen op2 := filenamep : AstNodeExpr + // @astgen op3 := modep : AstNodeExpr +public: + AstFOpen(FileLine* fl, AstNodeExpr* filenamep, AstNodeExpr* modep) + : ASTGEN_SUPER_FOpen(fl) { + this->filenamep(filenamep); + this->modep(modep); + } + ASTGEN_MEMBERS_AstFOpen; + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + string verilogKwd() const override { return "$fopen"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstFOpenMcd final : public AstNodeExpr { + // @astgen op2 := filenamep : AstNodeExpr +public: + AstFOpenMcd(FileLine* fl, AstNodeExpr* filenamep) + : ASTGEN_SUPER_FOpenMcd(fl) { + this->filenamep(filenamep); + } + ASTGEN_MEMBERS_AstFOpenMcd; + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + string verilogKwd() const override { return "$fopen"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } +}; class AstFRead final : public AstNodeExpr { // @astgen op1 := memp : AstNode // VarRef for result // @astgen op2 := filep : AstNode // file (must be a VarRef) diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 87bad25ba..111b6b3a3 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -2739,46 +2739,6 @@ public: bool isUnlikely() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } }; -class AstFOpen final : public AstNodeStmt { - // Although a system function in IEEE, here a statement which sets the file pointer (MCD) - // @astgen op1 := filep : AstNodeExpr - // @astgen op2 := filenamep : AstNodeExpr - // @astgen op3 := modep : AstNodeExpr -public: - AstFOpen(FileLine* fl, AstNodeExpr* filep, AstNodeExpr* filenamep, AstNodeExpr* modep) - : ASTGEN_SUPER_FOpen(fl) { - this->filep(filep); - this->filenamep(filenamep); - this->modep(modep); - } - ASTGEN_MEMBERS_AstFOpen; - string verilogKwd() const override { return "$fopen"; } - bool isGateOptimizable() const override { return false; } - bool isPredictOptimizable() const override { return false; } - bool isPure() const override { return false; } - bool isOutputter() const override { return true; } - bool isUnlikely() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } -}; -class AstFOpenMcd final : public AstNodeStmt { - // Although a system function in IEEE, here a statement which sets the file pointer (MCD) - // @astgen op1 := filep : AstNodeExpr - // @astgen op2 := filenamep : AstNodeExpr -public: - AstFOpenMcd(FileLine* fl, AstNodeExpr* filep, AstNodeExpr* filenamep) - : ASTGEN_SUPER_FOpenMcd(fl) { - this->filep(filep); - this->filenamep(filenamep); - } - ASTGEN_MEMBERS_AstFOpenMcd; - string verilogKwd() const override { return "$fopen"; } - bool isGateOptimizable() const override { return false; } - bool isPredictOptimizable() const override { return false; } - bool isPure() const override { return false; } - bool isOutputter() const override { return true; } - bool isUnlikely() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } -}; class AstFinish final : public AstNodeStmt { public: explicit AstFinish(FileLine* fl) diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index c91112ef0..808fb7e17 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -649,8 +649,7 @@ public: } } void visit(AstFOpen* nodep) override { - iterateAndNextNull(nodep->filep()); - puts(" = VL_FOPEN_NN("); + puts("VL_FOPEN_NN("); emitCvtPackStr(nodep->filenamep()); putbs(", "); if (nodep->modep()->width() > 4 * 8) @@ -659,8 +658,7 @@ public: puts(");\n"); } void visit(AstFOpenMcd* nodep) override { - iterateAndNextNull(nodep->filep()); - puts(" = VL_FOPEN_MCD_N("); + puts("VL_FOPEN_MCD_N("); emitCvtPackStr(nodep->filenamep()); puts(");\n"); } diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 5672089fc..ca0f07574 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -116,83 +116,43 @@ private: iterateAndNextNull(nodep->top()); } } - void visit(AstFOpen* nodep) override { - VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->filep()); - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->filenamep()); - iterateAndNextNull(nodep->modep()); - } - } - void visit(AstFOpenMcd* nodep) override { - VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->filep()); - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->filenamep()); - } - } - void visit(AstFClose* nodep) override { - VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->filep()); - } - } void visit(AstFError* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->strp()); } } - void visit(AstFFlush* nodep) override { - VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->filep()); - } - } - void visit(AstFGetC* nodep) override { - VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->filep()); - } - } void visit(AstFGetS* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->strgp()); } } void visit(AstFRead* nodep) override { VL_RESTORER(m_setRefLvalue); { + iterateAndNextNull(nodep->filep()); m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->memp()); - iterateAndNextNull(nodep->filep()); } } void visit(AstFScanF* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->exprsp()); } } void visit(AstFUngetC* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->rhsp()); } } diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 6ecc90b2c..5f9bcbbef 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -318,14 +318,6 @@ private: if (filep && filep->varp()) filep->varp()->attrFileDescr(true); } - void visit(AstFOpen* nodep) override { - iterateChildren(nodep); - expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); - } - void visit(AstFOpenMcd* nodep) override { - iterateChildren(nodep); - expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); - } void visit(AstFClose* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 89ee71e5a..a50697f09 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -4861,15 +4861,13 @@ private: } void visit(AstFOpen* nodep) override { // Although a system function in IEEE, here a statement which sets the file pointer (MCD) - assertAtStatement(nodep); - iterateCheckFileDesc(nodep, nodep->filep(), BOTH); userIterateAndNext(nodep->filenamep(), WidthVP{SELF, BOTH}.p()); userIterateAndNext(nodep->modep(), WidthVP{SELF, BOTH}.p()); + nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } void visit(AstFOpenMcd* nodep) override { - assertAtStatement(nodep); - iterateCheckFileDesc(nodep, nodep->filep(), BOTH); userIterateAndNext(nodep->filenamep(), WidthVP{SELF, BOTH}.p()); + nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } void visit(AstFClose* nodep) override { assertAtStatement(nodep); diff --git a/src/verilog.y b/src/verilog.y index dc42045aa..f8408698b 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3645,8 +3645,6 @@ statementVerilatorPragmas: foperator_assignment: // IEEE: operator_assignment (for first part of expression) fexprLvalue '=' delay_or_event_controlE expr { $$ = new AstAssign{$2, $1, $4, $3}; } - | fexprLvalue '=' yD_FOPEN '(' expr ')' { $$ = new AstFOpenMcd{$3, $1, $5}; } - | fexprLvalue '=' yD_FOPEN '(' expr ',' expr ')' { $$ = new AstFOpen{$3, $1, $5, $7}; } // | fexprLvalue yP_PLUSEQ expr { $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTree(true), $3}}; } @@ -4208,6 +4206,8 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task | yD_FERROR '(' expr ',' idClassSel ')' { $$ = new AstFError{$1, $3, $5}; } | yD_FGETC '(' expr ')' { $$ = new AstFGetC{$1, $3}; } | yD_FGETS '(' expr ',' expr ')' { $$ = new AstFGetS{$1, $3, $5}; } + | yD_FOPEN '(' expr ')' { $$ = new AstFOpenMcd{$1, $3}; } + | yD_FOPEN '(' expr ',' expr ')' { $$ = new AstFOpen{$1, $3, $5}; } | yD_FREAD '(' expr ',' expr ')' { $$ = new AstFRead{$1, $3, $5, nullptr, nullptr}; } | yD_FREAD '(' expr ',' expr ',' expr ')' { $$ = new AstFRead{$1, $3, $5, $7, nullptr}; } | yD_FREAD '(' expr ',' expr ',' expr ',' expr ')' { $$ = new AstFRead{$1, $3, $5, $7, $9}; } diff --git a/test_regress/t/t_debug_emitv.out b/test_regress/t/t_debug_emitv.out index 82db5dfde..2775f2c02 100644 --- a/test_regress/t/t_debug_emitv.out +++ b/test_regress/t/t_debug_emitv.out @@ -169,9 +169,11 @@ module Vt_debug_emitv_t; : $c('sh1e))); $c(;); $display("%d", $c(0)); - $fopen(72'h2f6465762f6e756c6c); + fd = $fopen(72'h2f6465762f6e756c6c); + ; $fclose(fd); - $fopen(72'h2f6465762f6e756c6c, 8'h72); + fd = $fopen(72'h2f6465762f6e756c6c, 8'h72); + ; $fgetc(fd); $fflush(fd); $fscanf(fd, "%d", sum);