[#74021] simplify file IO logic

This commit is contained in:
Mateusz Gancarz 2025-03-05 08:46:08 +01:00
parent 2c677d90f7
commit 2499c71d12
2 changed files with 15 additions and 96 deletions

View File

@ -89,50 +89,26 @@ VerilatedSaifActivityBit& VerilatedSaifActivityVar::bit(const std::size_t index)
return m_bits[index];
}
//=============================================================================
//=============================================================================
//=============================================================================
// VerilatedSaifFile
bool VerilatedSaifFile::open(const std::string& name) VL_MT_UNSAFE {
m_fd = ::open(name.c_str(),
O_CREAT | O_WRONLY | O_TRUNC | O_LARGEFILE | O_NONBLOCK | O_CLOEXEC, 0666);
return m_fd >= 0;
}
void VerilatedSaifFile::close() VL_MT_UNSAFE { ::close(m_fd); }
ssize_t VerilatedSaifFile::write(const char* bufp, ssize_t len) VL_MT_UNSAFE {
return ::write(m_fd, bufp, len);
}
//=============================================================================
//=============================================================================
//=============================================================================
// Opening/Closing
VerilatedSaif::VerilatedSaif(VerilatedSaifFile* filep) {
// Not in header to avoid link issue if header is included without this .cpp file
m_fileNewed = (filep == nullptr);
m_filep = m_fileNewed ? new VerilatedSaifFile : filep;
}
VerilatedSaif::VerilatedSaif(void* filep) {}
void VerilatedSaif::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock{m_mutex};
if (isOpen()) return;
// Set member variables
m_filename = filename; // "" is ok, as someone may overload open
m_filep = ::open(m_filename.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_LARGEFILE | O_NONBLOCK | O_CLOEXEC, 0666);
m_isOpen = true;
initializeSaifFileContents();
Super::traceInit();
}
void VerilatedSaif::openNext(bool incFilename) VL_MT_SAFE_EXCLUDES(m_mutex) {
// noop, SAIF only needs one file per trace
}
void VerilatedSaif::initializeSaifFileContents() {
printStr("// Generated by verilated_saif\n");
printStr("(SAIFILE\n");
@ -145,34 +121,9 @@ void VerilatedSaif::initializeSaifFileContents() {
printStr(")\n");
}
bool VerilatedSaif::preChangeDump() { return isOpen(); }
void VerilatedSaif::emitTimeChange(uint64_t timeui) { m_time = timeui; }
VerilatedSaif::~VerilatedSaif() {
close();
if (m_filep && m_fileNewed) VL_DO_CLEAR(delete m_filep, m_filep = nullptr);
}
void VerilatedSaif::closePrev() {
// This function is on the flush() call path
if (!isOpen()) return;
Super::flushBase();
m_isOpen = false;
m_filep->close();
}
void VerilatedSaif::closeErr() {
// This function is on the flush() call path
// Close due to an error. We might abort before even getting here,
// depending on the definition of vl_fatal.
if (!isOpen()) return;
// No buffer flush, just fclose
m_isOpen = false;
m_filep->close(); // May get error, just ignore it
}
VerilatedSaif::~VerilatedSaif() { close(); }
void VerilatedSaif::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
// This function is on the flush() call path
@ -182,9 +133,9 @@ void VerilatedSaif::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
finalizeSaifFileContents();
clearCurrentlyCollectedData();
closePrev();
// closePrev() called Super::flush(), so we just
// need to shut down the tracing thread here.
::close(m_filep);
m_isOpen = false;
Super::closeBase();
}
@ -298,9 +249,9 @@ void VerilatedSaif::clearCurrentlyCollectedData() {
m_activityArena.clear();
}
void VerilatedSaif::printStr(const char* str) { m_filep->write(str, strlen(str)); }
void VerilatedSaif::printStr(const char* str) { ::write(m_filep, str, strlen(str)); }
void VerilatedSaif::printStr(const std::string& str) { m_filep->write(str.c_str(), str.size()); }
void VerilatedSaif::printStr(const std::string& str) { ::write(m_filep, str.c_str(), str.size()); }
//=============================================================================
// Definitions

View File

@ -161,8 +161,7 @@ private:
//=========================================================================
// SAIF-specific internals
VerilatedSaifFile* m_filep; // File we're writing to
bool m_fileNewed; // m_filep needs destruction
int m_filep = 0; // File we're writing to
bool m_isOpen = false; // True indicates open file
std::string m_filename; // Filename we're writing to (if open)
@ -205,8 +204,6 @@ private:
void clearCurrentlyCollectedData();
void closePrev();
void closeErr();
void declare(uint32_t code, const char* name, const char* wirep, bool array, int arraynum,
bool bussed, int msb, int lsb);
@ -222,7 +219,7 @@ protected:
// Hooks called from VerilatedTrace
bool preFullDump() override { return isOpen(); }
bool preChangeDump() override;
bool preChangeDump() override { return isOpen(); }
// Trace buffer management
Buffer* getTraceBuffer(uint32_t fidx) override;
@ -236,7 +233,7 @@ public:
// External interface to client code
// CONSTRUCTOR
explicit VerilatedSaif(VerilatedSaifFile* filep = nullptr);
explicit VerilatedSaif(void* filep = nullptr);
~VerilatedSaif();
// ACCESSORS
@ -247,8 +244,6 @@ public:
// METHODS - All must be thread safe
// Open the file; call isOpen() to see if errors
void open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex);
// Open next data-only file
void openNext(bool incFilename) VL_MT_SAFE_EXCLUDES(m_mutex);
// Close the file
void close() VL_MT_SAFE_EXCLUDES(m_mutex);
// Flush any remaining data to this file
@ -329,28 +324,6 @@ class VerilatedSaifBuffer VL_NOT_FINAL {
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
};
//=============================================================================
// VerilatedFile
/// Class representing a file to write to. These virtual methods can be
/// overrode for e.g. socket I/O.
class VerilatedSaifFile VL_NOT_FINAL {
private:
int m_fd = 0; // File descriptor we're writing to
public:
// METHODS
/// Construct a (as yet) closed file
VerilatedSaifFile() = default;
/// Close and destruct
virtual ~VerilatedSaifFile() = default;
/// Open a file with given filename
virtual bool open(const std::string& name) VL_MT_UNSAFE;
/// Close object's file
virtual void close() VL_MT_UNSAFE;
/// Write data to file (if it is open)
virtual ssize_t write(const char* bufp, ssize_t len) VL_MT_UNSAFE;
};
//=============================================================================
// VerilatedSaifC
/// Class representing a SAIF dump file in C standalone (no SystemC)
@ -363,8 +336,8 @@ class VerilatedSaifC VL_NOT_FINAL : public VerilatedTraceBaseC {
VL_UNCOPYABLE(VerilatedSaifC);
public:
/// Construct the dump. Optional argument is a preconstructed file.
explicit VerilatedSaifC(VerilatedSaifFile* filep = nullptr)
/// Construct the dump. Optional argument is ignored
explicit VerilatedSaifC(void* filep = nullptr)
: m_sptrace{filep} {}
/// Destruct, flush, and close the dump
virtual ~VerilatedSaifC() { close(); }
@ -377,13 +350,8 @@ public:
/// This includes a complete header dump each time it is called,
/// just as if this object was deleted and reconstructed.
virtual void open(const char* filename) VL_MT_SAFE { m_sptrace.open(filename); }
/// Continue a SAIF dump by rotating to a new file name
/// The header is only in the first file created, this allows
/// "cat" to be used to combine the header plus any number of data files.
void openNext(bool incFilename = true) VL_MT_SAFE { m_sptrace.openNext(incFilename); }
void rolloverSize(size_t size) VL_MT_SAFE { /* noop */
}
void rolloverSize(size_t size) VL_MT_SAFE { /* noop */ }
/// Close dump
void close() VL_MT_SAFE {