Internals: Refactor to introduce VerilatedFdList. (#2363)
This commit is contained in:
parent
e8f27be200
commit
c4aab57c62
|
|
@ -1190,11 +1190,8 @@ done:
|
||||||
// File I/O
|
// File I/O
|
||||||
|
|
||||||
FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE {
|
FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE {
|
||||||
// Expected non-MCD case; returns ONLY the first file descriptor seen in lhs (which
|
// Expected non-MCD case; returns null on MCD descriptors.
|
||||||
// in the MCD case can result in descriptors being ignored).
|
return VerilatedImp::fdToFp(lhs);
|
||||||
FILE* fp[1] = {NULL};
|
|
||||||
VerilatedImp::fdToFp(lhs, fp, 1);
|
|
||||||
return fp[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE {
|
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);
|
_vl_vsformat(output, formatp, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
FILE* fp[30];
|
VerilatedImp::fdWrite(fpi, output);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE {
|
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE {
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,24 @@ public:
|
||||||
};
|
};
|
||||||
#endif // VL_THREADED
|
#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
|
// VerilatedImp
|
||||||
|
|
||||||
|
|
@ -484,24 +502,32 @@ public: // But only for verilated*.cpp
|
||||||
return (idx | (1UL << 31)); // bit 31 indicates not MCD
|
return (idx | (1UL << 31)); // bit 31 indicates not MCD
|
||||||
}
|
}
|
||||||
static void fdFlush(IData fdi) VL_MT_SAFE {
|
static void fdFlush(IData fdi) VL_MT_SAFE {
|
||||||
FILE* fp[30];
|
|
||||||
const int n = fdToFp(fdi, fp, 30);
|
|
||||||
VerilatedLockGuard lock(s_s.m_fdMutex);
|
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 {
|
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);
|
VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||||
if (VL_UNLIKELY(!fp || (n != 1))) return 0;
|
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||||
return static_cast<IData>(fseek(fp, static_cast<long>(offset), static_cast<int>(origin)));
|
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 {
|
static IData fdTell(IData fdi) VL_MT_SAFE {
|
||||||
FILE* fp;
|
|
||||||
const int n = fdToFp(fdi, &fp);
|
|
||||||
VerilatedLockGuard lock(s_s.m_fdMutex);
|
VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||||
if (VL_UNLIKELY(!fp || (n != 1))) return 0;
|
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||||
return static_cast<IData>(ftell(fp));
|
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 {
|
static void fdClose(IData fdi) VL_MT_SAFE {
|
||||||
VerilatedLockGuard lock(s_s.m_fdMutex);
|
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 {
|
static inline FILE* fdToFp(IData fdi) VL_MT_SAFE {
|
||||||
if (VL_UNLIKELY(!fp || (max == 0))) return 0;
|
|
||||||
VerilatedLockGuard lock(s_s.m_fdMutex);
|
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) {
|
if ((fdi & (1 << 31)) != 0) {
|
||||||
// Non-MCD case
|
// Non-MCD case
|
||||||
IData idx = fdi & VL_MASK_I(31);
|
const IData idx = fdi & VL_MASK_I(31);
|
||||||
switch (idx) {
|
switch (idx) {
|
||||||
case 0: fp[out++] = stdin; break;
|
case 0: fp.push_back(stdin); break;
|
||||||
case 1: fp[out++] = stdout; break;
|
case 1: fp.push_back(stdout); break;
|
||||||
case 2: fp[out++] = stderr; break;
|
case 2: fp.push_back(stderr); break;
|
||||||
default:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// MCD Case
|
// MCD Case
|
||||||
for (int i = 0; (fdi != 0) && (out < static_cast<int>(max)) && (i < 31);
|
for (int i = 0; (fdi != 0) && (i < fp.capacity()); ++i, fdi >>= 1) {
|
||||||
++i, fdi >>= 1) {
|
if (fdi & VL_MASK_I(1)) fp.push_back(s_s.m_fdps[i]);
|
||||||
if (fdi & VL_MASK_I(1)) fp[out++] = s_s.m_fdps[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return fp;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue