forked from github/verilator
Internals: Refactor to introduce VerilatedFdList. (#2363)
This commit is contained in:
parent
e8f27be200
commit
c4aab57c62
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user