From a901e171b2421b41e5bbd46007d557bf14162c71 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 1 Jul 2011 13:41:21 -0400 Subject: [PATCH] Support $fopen and I/O with integer instead of `verilator_file_descriptor. --- Changes | 2 ++ bin/verilator | 5 ---- include/verilated.cpp | 25 +++++++++++------ include/verilated.h | 8 +++--- include/verilated.v | 8 ++---- include/verilated_imp.h | 40 +++++++++++++++++++++++++++- src/V3AstNodes.h | 4 +-- src/V3EmitC.cpp | 10 +++---- src/V3Width.cpp | 32 +++++++++++----------- test_regress/t/t_case_write1_tasks.v | 4 --- test_regress/t/t_case_write2_tasks.v | 4 --- 11 files changed, 86 insertions(+), 56 deletions(-) diff --git a/Changes b/Changes index 39e4bfb76..7d6c128b4 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks! *** Support disable for loop escapes. +*** Support $fopen and I/O with integer instead of `verilator_file_descriptor. + **** Use 'vluint64_t' for SystemC instead of (same sized) 'uint64' for MSVC++. * Verilator 3.813 2011/06/28 diff --git a/bin/verilator b/bin/verilator index 7d6307cce..927de82bd 100755 --- a/bin/verilator +++ b/bin/verilator @@ -2313,11 +2313,6 @@ The rarely used optional parameter to $finish and $stop is ignored. File descriptors passed to the file PLI calls must be file descriptors, not MCDs, which includes the mode parameter to $fopen being mandatory. -Verilator will convert the integer used to hold the file descriptor into a -internal FILE*. To prevent core dumps due to mis-use, and because integers -are 32 bits while FILE*s may be 64 bits, the descriptor must be stored in a -reg [63:0] rather than an integer. The define `verilator_file_descriptor in -verilated.v can be used to hide this difference. =item $fscanf, $sscanf diff --git a/include/verilated.cpp b/include/verilated.cpp index 75948558b..d85b5598e 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -26,7 +26,6 @@ #define _VERILATED_CPP_ #include "verilated_imp.h" #include -#include #define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING @@ -628,6 +627,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf //=========================================================================== // File I/O +FILE* VL_CVT_I_FP(IData lhs) { + return VerilatedImp::fdToFp(lhs); +} + void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) { // See also VL_DATA_TO_STRING_NW int lsb=obits-1; @@ -655,8 +658,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) { for (; i #include +#include #include class VerilatedScope; @@ -62,9 +63,18 @@ class VerilatedImp { ExportNameMap m_exportMap; ///< Map of int m_exportNext; ///< Next export funcnum + // File I/O + vector m_fdps; ///< File descriptors + deque m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only) + public: // But only for verilated*.cpp // CONSTRUCTORS - VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {} + VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) { + m_fdps.resize(3); + m_fdps[0] = stdin; + m_fdps[1] = stdout; + m_fdps[2] = stderr; + } ~VerilatedImp() {} // METHODS - arguments @@ -184,6 +194,34 @@ public: // But only for verilated*.cpp } // We don't free up m_exportMap until the end, because we can't be sure // what other models are using the assigned funcnum's. + +public: // But only for verilated*.cpp + // METHODS - file IO + static IData fdNew(FILE* fp) { + if (VL_UNLIKELY(!fp)) return 0; + // Bit 31 indicates it's a descriptor not a MCD + if (s_s.m_fdFree.empty()) { + // Need to create more space in m_fdps and m_fdFree + size_t start = s_s.m_fdps.size(); + s_s.m_fdps.resize(start*2); + for (size_t i=start; i= s_s.m_fdps.size())) return; + if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free + s_s.m_fdps[idx] = NULL; + s_s.m_fdFree.push_back(idx); + } + static inline FILE* fdToFp(IData fdi) { + IData idx = VL_MASK_I(31) & fdi; + if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL; + return s_s.m_fdps[idx]; + } }; #endif // Guard diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 479dce113..e0ea77c94 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -2697,7 +2697,7 @@ struct AstFEof : public AstNodeUniop { ASTNODE_NODE_FUNCS(FEof, FEOF) virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } virtual string emitVerilog() { return "%f$feof(%l)"; } - virtual string emitC() { return "(%li ? feof(VL_CVT_Q_FP(%li)) : true)"; } + virtual string emitC() { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; } virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;} virtual bool sizeMattersLhs() {return false;} virtual int instrCount() const { return widthInstrs()*16; } @@ -2710,7 +2710,7 @@ struct AstFGetC : public AstNodeUniop { virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } virtual string emitVerilog() { return "%f$fgetc(%l)"; } // Non-existent filehandle returns EOF - virtual string emitC() { return "(%li ? fgetc(VL_CVT_Q_FP(%li)) : -1)"; } + virtual string emitC() { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; } virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;} virtual bool sizeMattersLhs() {return false;} virtual int instrCount() const { return widthInstrs()*64; } diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 96761b907..5d164fecf 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -344,13 +344,11 @@ public: puts(");\n"); } virtual void visit(AstFClose* nodep, AstNUser*) { - puts("if ("); + puts("VL_FCLOSE_I("); nodep->filep()->iterateAndNext(*this); - puts(") { fclose (VL_CVT_Q_FP("); - nodep->filep()->iterateAndNext(*this); - puts(")); "); + puts("); "); nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it. - puts("=0; }\n"); + puts("=0;\n"); } virtual void visit(AstFFlush* nodep, AstNUser*) { if (!nodep->filep()) { @@ -358,7 +356,7 @@ public: } else { puts("if ("); nodep->filep()->iterateAndNext(*this); - puts(") { fflush (VL_CVT_Q_FP("); + puts(") { fflush (VL_CVT_I_FP("); nodep->filep()->iterateAndNext(*this); puts(")); }\n"); } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index b0ab5a2b9..93f2a5527 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -759,55 +759,55 @@ private: } virtual void visit(AstDisplay* nodep, AstNUser*) { if (nodep->filep()) { - nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); - widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64); + nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p()); + widthCheck(nodep,"file_descriptor",nodep->filep(),32,32); } // Just let all arguments seek their natural sizes nodep->iterateChildren(*this,WidthVP(ANYSIZE,0,BOTH).p()); } virtual void visit(AstFOpen* nodep, AstNUser*) { - nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); + nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p()); nodep->filenamep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); nodep->modep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); - widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64); + widthCheck(nodep,"file_descriptor",nodep->filep(),32,32); } virtual void visit(AstFClose* nodep, AstNUser*) { - nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); - widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64); + nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p()); + widthCheck(nodep,"file_descriptor",nodep->filep(),32,32); } virtual void visit(AstFEof* nodep, AstNUser*) { - nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); + nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p()); nodep->width(1,1); - widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64); + widthCheck(nodep,"file_descriptor",nodep->filep(),32,32); } virtual void visit(AstFFlush* nodep, AstNUser*) { if (nodep->filep()) { - nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); - widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64); + nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p()); + widthCheck(nodep,"file_descriptor",nodep->filep(),32,32); } } virtual void visit(AstFGetC* nodep, AstNUser* vup) { - nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); + nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p()); if (vup->c()->prelim()) { nodep->width(32,8); } - widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64); + widthCheck(nodep,"file_descriptor",nodep->filep(),32,32); } virtual void visit(AstFGetS* nodep, AstNUser* vup) { - nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); + nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p()); nodep->strgp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); if (vup->c()->prelim()) { nodep->width(32,32); } - widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64); + widthCheck(nodep,"file_descriptor",nodep->filep(),32,32); } virtual void visit(AstFScanF* nodep, AstNUser* vup) { - nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); + nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p()); nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); if (vup->c()->prelim()) { nodep->width(32,32); } - widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64); + widthCheck(nodep,"file_descriptor",nodep->filep(),32,32); } virtual void visit(AstSScanF* nodep, AstNUser* vup) { nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); diff --git a/test_regress/t/t_case_write1_tasks.v b/test_regress/t/t_case_write1_tasks.v index 19df87e11..0c4844254 100644 --- a/test_regress/t/t_case_write1_tasks.v +++ b/test_regress/t/t_case_write1_tasks.v @@ -2497,11 +2497,7 @@ module t_case_write1_tasks (); endtask task big_case; -`ifdef verilator - input [ 63:0] fd; -`else input [ 31:0] fd; -`endif input [ 31:0] foo; reg [STRLEN*8: 1] foobar; // verilator no_inline_task diff --git a/test_regress/t/t_case_write2_tasks.v b/test_regress/t/t_case_write2_tasks.v index e0e2bf537..9790eaad3 100644 --- a/test_regress/t/t_case_write2_tasks.v +++ b/test_regress/t/t_case_write2_tasks.v @@ -10,11 +10,7 @@ module t_case_write2_tasks (); // verilator lint_off WIDTH // verilator lint_off CASEINCOMPLETE -`ifdef verilator - `define FD_BITS 63:0 -`else `define FD_BITS 31:0 -`endif parameter STRLEN = 78; task ozonerab;