From c4aab57c622bcb222be5ca72dcbec90764501384 Mon Sep 17 00:00:00 2001 From: Stephen Henry <stephenry@gmail.com> Date: Thu, 28 May 2020 22:59:18 +0100 Subject: [PATCH] Internals: Refactor to introduce VerilatedFdList. (#2363) --- include/verilated.cpp | 14 ++------ include/verilated_imp.h | 77 +++++++++++++++++++++++++++++------------ 2 files changed, 57 insertions(+), 34 deletions(-) diff --git a/include/verilated.cpp b/include/verilated.cpp index 5204b3665..d99918312 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -1190,11 +1190,8 @@ done: // File I/O FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE { - // Expected non-MCD case; returns ONLY the first file descriptor seen in lhs (which - // in the MCD case can result in descriptors being ignored). - FILE* fp[1] = {NULL}; - VerilatedImp::fdToFp(lhs, fp, 1); - return fp[0]; + // Expected non-MCD case; returns null on MCD descriptors. + return VerilatedImp::fdToFp(lhs); } void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE { @@ -1378,12 +1375,7 @@ void VL_FWRITEF(IData fpi, const char* formatp, ...) VL_MT_SAFE { _vl_vsformat(output, formatp, ap); va_end(ap); - FILE* fp[30]; - const std::size_t n = VerilatedImp::fdToFp(fpi, fp, 30); - for (std::size_t i = 0; i < n; ++i) { - if (VL_UNLIKELY(!fp[i])) continue; - fwrite(output.c_str(), 1, output.size(), fp[i]); - } + VerilatedImp::fdWrite(fpi, output); } IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE { diff --git a/include/verilated_imp.h b/include/verilated_imp.h index b337aee1c..724d10433 100644 --- a/include/verilated_imp.h +++ b/include/verilated_imp.h @@ -169,6 +169,24 @@ public: }; #endif // VL_THREADED +// FILE* list constructed from a file-descriptor +class VerilatedFpList { + FILE* m_fp[31]; + std::size_t m_sz; + +public: + typedef FILE* const* const_iterator; + explicit VerilatedFpList() + : m_sz(0) {} + const_iterator begin() const { return m_fp; } + const_iterator end() const { return m_fp + m_sz; } + std::size_t size() const { return m_sz; } + std::size_t capacity() const { return 31; } + void push_back(FILE* fd) { + if (VL_LIKELY(size() < capacity())) m_fp[m_sz++] = fd; + } +}; + //====================================================================== // VerilatedImp @@ -484,24 +502,32 @@ public: // But only for verilated*.cpp return (idx | (1UL << 31)); // bit 31 indicates not MCD } static void fdFlush(IData fdi) VL_MT_SAFE { - FILE* fp[30]; - const int n = fdToFp(fdi, fp, 30); VerilatedLockGuard lock(s_s.m_fdMutex); - for (int i = 0; i < n; i++) fflush(fp[i]); + const VerilatedFpList fdlist = fdToFpList(fdi); + for (VerilatedFpList::const_iterator it = fdlist.begin(); it != fdlist.end(); ++it) { + fflush(*it); + } } static IData fdSeek(IData fdi, IData offset, IData origin) VL_MT_SAFE { - FILE* fp; - const int n = fdToFp(fdi, &fp); VerilatedLockGuard lock(s_s.m_fdMutex); - if (VL_UNLIKELY(!fp || (n != 1))) return 0; - return static_cast<IData>(fseek(fp, static_cast<long>(offset), static_cast<int>(origin))); + const VerilatedFpList fdlist = fdToFpList(fdi); + if (VL_UNLIKELY(fdlist.size() != 1)) return 0; + return static_cast<IData>( + fseek(*fdlist.begin(), static_cast<long>(offset), static_cast<int>(origin))); } static IData fdTell(IData fdi) VL_MT_SAFE { - FILE* fp; - const int n = fdToFp(fdi, &fp); VerilatedLockGuard lock(s_s.m_fdMutex); - if (VL_UNLIKELY(!fp || (n != 1))) return 0; - return static_cast<IData>(ftell(fp)); + const VerilatedFpList fdlist = fdToFpList(fdi); + if (VL_UNLIKELY(fdlist.size() != 1)) return 0; + return static_cast<IData>(ftell(*fdlist.begin())); + } + static void fdWrite(IData fdi, const std::string& output) VL_MT_SAFE { + VerilatedLockGuard lock(s_s.m_fdMutex); + const VerilatedFpList fdlist = fdToFpList(fdi); + for (VerilatedFpList::const_iterator it = fdlist.begin(); it != fdlist.end(); ++it) { + if (VL_UNLIKELY(!*it)) continue; + fwrite(output.c_str(), 1, output.size(), *it); + } } static void fdClose(IData fdi) VL_MT_SAFE { VerilatedLockGuard lock(s_s.m_fdMutex); @@ -524,29 +550,34 @@ public: // But only for verilated*.cpp } } } - static inline int fdToFp(IData fdi, FILE** fp, std::size_t max = 1) VL_MT_SAFE { - if (VL_UNLIKELY(!fp || (max == 0))) return 0; + static inline FILE* fdToFp(IData fdi) VL_MT_SAFE { VerilatedLockGuard lock(s_s.m_fdMutex); - int out = 0; + const VerilatedFpList fdlist = fdToFpList(fdi); + if (VL_UNLIKELY(fdlist.size() != 1)) return NULL; + return *fdlist.begin(); + } + +private: + static inline VerilatedFpList fdToFpList(IData fdi) VL_REQUIRES(s_s.m_fdMutex) { + VerilatedFpList fp; if ((fdi & (1 << 31)) != 0) { // Non-MCD case - IData idx = fdi & VL_MASK_I(31); + const IData idx = fdi & VL_MASK_I(31); switch (idx) { - case 0: fp[out++] = stdin; break; - case 1: fp[out++] = stdout; break; - case 2: fp[out++] = stderr; break; + case 0: fp.push_back(stdin); break; + case 1: fp.push_back(stdout); break; + case 2: fp.push_back(stderr); break; default: - if (VL_LIKELY(idx < s_s.m_fdps.size())) fp[out++] = s_s.m_fdps[idx]; + if (VL_LIKELY(idx < s_s.m_fdps.size())) fp.push_back(s_s.m_fdps[idx]); break; } } else { // MCD Case - for (int i = 0; (fdi != 0) && (out < static_cast<int>(max)) && (i < 31); - ++i, fdi >>= 1) { - if (fdi & VL_MASK_I(1)) fp[out++] = s_s.m_fdps[i]; + for (int i = 0; (fdi != 0) && (i < fp.capacity()); ++i, fdi >>= 1) { + if (fdi & VL_MASK_I(1)) fp.push_back(s_s.m_fdps[i]); } } - return out; + return fp; } };