2012-04-13 01:08:20 +00:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2010-01-24 23:37:01 +00:00
|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
// THIS MODULE IS PUBLICLY LICENSED
|
|
|
|
//
|
2020-03-21 15:24:24 +00:00
|
|
|
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
// Version 2.0.
|
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2010-01-24 23:37:01 +00:00
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
///
|
|
|
|
/// \file
|
|
|
|
/// \brief C++ Tracing in VCD Format
|
|
|
|
///
|
|
|
|
//=============================================================================
|
|
|
|
// SPDIFF_OFF
|
|
|
|
|
|
|
|
#ifndef _VERILATED_VCD_C_H_
|
|
|
|
#define _VERILATED_VCD_C_H_ 1
|
|
|
|
|
2017-10-21 21:53:23 +00:00
|
|
|
#include "verilated.h"
|
2020-04-19 22:57:36 +00:00
|
|
|
#include "verilated_trace.h"
|
2010-01-24 23:37:01 +00:00
|
|
|
|
2018-10-14 17:43:24 +00:00
|
|
|
#include <map>
|
2010-01-24 23:37:01 +00:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
class VerilatedVcd;
|
|
|
|
|
|
|
|
// SPDIFF_ON
|
2015-03-05 13:54:57 +00:00
|
|
|
//=============================================================================
|
|
|
|
// VerilatedFile
|
|
|
|
/// File handling routines, which can be overrode for e.g. socket I/O
|
|
|
|
|
|
|
|
class VerilatedVcdFile {
|
|
|
|
private:
|
2018-11-29 00:59:10 +00:00
|
|
|
int m_fd; ///< File descriptor we're writing to
|
2015-03-05 13:54:57 +00:00
|
|
|
public:
|
|
|
|
// METHODS
|
2019-12-22 23:09:46 +00:00
|
|
|
VerilatedVcdFile()
|
|
|
|
: m_fd(0) {}
|
2015-03-05 13:54:57 +00:00
|
|
|
virtual ~VerilatedVcdFile() {}
|
2017-10-27 01:51:51 +00:00
|
|
|
virtual bool open(const std::string& name) VL_MT_UNSAFE;
|
|
|
|
virtual void close() VL_MT_UNSAFE;
|
|
|
|
virtual ssize_t write(const char* bufp, ssize_t len) VL_MT_UNSAFE;
|
2015-03-05 13:54:57 +00:00
|
|
|
};
|
|
|
|
|
2010-01-24 23:37:01 +00:00
|
|
|
//=============================================================================
|
|
|
|
// VerilatedVcd
|
2013-02-24 02:10:25 +00:00
|
|
|
/// Base class to create a Verilator VCD dump
|
|
|
|
/// This is an internally used class - see VerilatedVcdC for what to call from applications
|
2010-01-24 23:37:01 +00:00
|
|
|
|
2020-04-19 22:57:36 +00:00
|
|
|
class VerilatedVcd : public VerilatedTrace<VerilatedVcd> {
|
2010-01-24 23:37:01 +00:00
|
|
|
private:
|
2020-04-19 22:57:36 +00:00
|
|
|
// Give the superclass access to private bits (to avoid virtual functions)
|
|
|
|
friend class VerilatedTrace<VerilatedVcd>;
|
|
|
|
|
|
|
|
//=========================================================================
|
|
|
|
// VCD specific internals
|
|
|
|
|
2020-04-04 17:45:24 +00:00
|
|
|
VerilatedVcdFile* m_filep; ///< File we're writing to
|
|
|
|
bool m_fileNewed; ///< m_filep needs destruction
|
|
|
|
bool m_isOpen; ///< True indicates open file
|
|
|
|
bool m_evcd; ///< True for evcd format
|
|
|
|
std::string m_filename; ///< Filename we're writing to (if open)
|
|
|
|
vluint64_t m_rolloverMB; ///< MB of file size to rollover at
|
|
|
|
int m_modDepth; ///< Depth of module hierarchy
|
|
|
|
|
|
|
|
char* m_wrBufp; ///< Output buffer
|
|
|
|
char* m_wrFlushp; ///< Output buffer flush trigger location
|
|
|
|
char* m_writep; ///< Write pointer into output buffer
|
|
|
|
vluint64_t m_wrChunkSize; ///< Output buffer size
|
|
|
|
vluint64_t m_wroteBytes; ///< Number of bytes written to this file
|
|
|
|
|
2020-04-13 23:13:10 +00:00
|
|
|
std::vector<char> m_suffixes; ///< VCD line end string codes + metadata
|
|
|
|
const char* m_suffixesp; ///< Pointer to first element of above
|
|
|
|
|
2020-04-04 17:45:24 +00:00
|
|
|
typedef std::map<std::string, std::string> NameMap;
|
2020-03-02 02:39:23 +00:00
|
|
|
NameMap* m_namemapp; ///< List of names for the header
|
2017-09-23 11:44:52 +00:00
|
|
|
|
2014-11-06 03:22:27 +00:00
|
|
|
void bufferResize(vluint64_t minsize);
|
2017-10-27 01:51:51 +00:00
|
|
|
void bufferFlush() VL_MT_UNSAFE_ONE;
|
2014-11-06 03:22:27 +00:00
|
|
|
inline void bufferCheck() {
|
2018-08-22 23:14:06 +00:00
|
|
|
// Flush the write buffer if there's not enough space left for new information
|
|
|
|
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
2019-11-10 01:35:12 +00:00
|
|
|
if (VL_UNLIKELY(m_writep > m_wrFlushp)) { bufferFlush(); }
|
2010-01-24 23:37:01 +00:00
|
|
|
}
|
|
|
|
void closePrev();
|
|
|
|
void closeErr();
|
|
|
|
void openNext();
|
2010-03-22 22:38:24 +00:00
|
|
|
void makeNameMap();
|
2013-02-24 02:10:25 +00:00
|
|
|
void deleteNameMap();
|
2018-10-14 22:39:33 +00:00
|
|
|
void printIndent(int level_change);
|
2018-08-22 23:14:06 +00:00
|
|
|
void printStr(const char* str);
|
|
|
|
void printQuad(vluint64_t n);
|
|
|
|
void printTime(vluint64_t timeui);
|
2020-01-08 12:32:31 +00:00
|
|
|
void declare(vluint32_t code, const char* name, const char* wirep, bool array, int arraynum,
|
|
|
|
bool tri, bool bussed, int msb, int lsb);
|
2010-01-24 23:37:01 +00:00
|
|
|
|
|
|
|
void dumpHeader();
|
2020-04-19 22:57:36 +00:00
|
|
|
|
2020-04-13 23:13:10 +00:00
|
|
|
char* writeCode(char* writep, vluint32_t code);
|
|
|
|
|
2020-04-19 22:57:36 +00:00
|
|
|
void finishLine(vluint32_t code, char* writep);
|
|
|
|
|
2017-11-01 22:51:41 +00:00
|
|
|
// CONSTRUCTORS
|
|
|
|
VL_UNCOPYABLE(VerilatedVcd);
|
2020-04-04 17:45:24 +00:00
|
|
|
|
2020-04-19 22:57:36 +00:00
|
|
|
protected:
|
|
|
|
//=========================================================================
|
|
|
|
// Implementation of VerilatedTrace interface
|
|
|
|
|
|
|
|
// Implementations of protected virtual methods for VerilatedTrace
|
2020-08-15 14:03:34 +00:00
|
|
|
void emitTimeChange(vluint64_t timeui) override;
|
2020-04-19 22:57:36 +00:00
|
|
|
|
|
|
|
// Hooks called from VerilatedTrace
|
2020-08-15 14:03:34 +00:00
|
|
|
bool preFullDump() override { return isOpen(); }
|
|
|
|
bool preChangeDump() override;
|
2020-04-19 22:57:36 +00:00
|
|
|
|
2020-04-25 18:37:59 +00:00
|
|
|
// Implementations of duck-typed methods for VerilatedTrace. These are
|
|
|
|
// called from only one place (namely full*) so always inline them.
|
2020-04-29 23:09:09 +00:00
|
|
|
inline void emitBit(vluint32_t code, CData newval);
|
|
|
|
inline void emitCData(vluint32_t code, CData newval, int bits);
|
|
|
|
inline void emitSData(vluint32_t code, SData newval, int bits);
|
|
|
|
inline void emitIData(vluint32_t code, IData newval, int bits);
|
|
|
|
inline void emitQData(vluint32_t code, QData newval, int bits);
|
|
|
|
inline void emitWData(vluint32_t code, const WData* newvalp, int bits);
|
2020-04-25 18:37:59 +00:00
|
|
|
inline void emitDouble(vluint32_t code, double newval);
|
2020-04-19 22:57:36 +00:00
|
|
|
|
2010-01-24 23:37:01 +00:00
|
|
|
public:
|
2020-04-19 22:57:36 +00:00
|
|
|
//=========================================================================
|
|
|
|
// External interface to client code
|
|
|
|
|
2019-11-10 01:35:12 +00:00
|
|
|
explicit VerilatedVcd(VerilatedVcdFile* filep = NULL);
|
2010-01-24 23:37:01 +00:00
|
|
|
~VerilatedVcd();
|
|
|
|
|
|
|
|
// ACCESSORS
|
|
|
|
/// Set size in megabytes after which new file should be created
|
2019-11-10 01:35:12 +00:00
|
|
|
void rolloverMB(vluint64_t rolloverMB) { m_rolloverMB = rolloverMB; }
|
2010-01-24 23:37:01 +00:00
|
|
|
|
|
|
|
// METHODS
|
2020-04-04 17:45:24 +00:00
|
|
|
/// Open the file; call isOpen() to see if errors
|
|
|
|
void open(const char* filename) VL_MT_UNSAFE_ONE;
|
2020-04-19 22:57:36 +00:00
|
|
|
/// Open next data-only file
|
|
|
|
void openNext(bool incFilename) VL_MT_UNSAFE_ONE;
|
|
|
|
/// Close the file
|
|
|
|
void close() VL_MT_UNSAFE_ONE;
|
2017-10-21 21:53:23 +00:00
|
|
|
/// Flush any remaining data to this file
|
2020-04-25 17:29:27 +00:00
|
|
|
void flush() VL_MT_UNSAFE_ONE;
|
2020-04-19 22:57:36 +00:00
|
|
|
/// Is file open?
|
|
|
|
bool isOpen() const { return m_isOpen; }
|
2010-01-24 23:37:01 +00:00
|
|
|
|
2020-04-19 22:57:36 +00:00
|
|
|
//=========================================================================
|
|
|
|
// Internal interface to Verilator generated code
|
2010-01-24 23:37:01 +00:00
|
|
|
|
2020-04-04 17:45:24 +00:00
|
|
|
void declBit(vluint32_t code, const char* name, bool array, int arraynum);
|
|
|
|
void declBus(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
|
|
|
|
void declQuad(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
|
|
|
|
void declArray(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
|
2020-04-13 23:13:10 +00:00
|
|
|
void declDouble(vluint32_t code, const char* name, bool array, int arraynum);
|
2020-04-19 22:57:36 +00:00
|
|
|
|
|
|
|
#ifdef VL_TRACE_VCD_OLD_API
|
|
|
|
//=========================================================================
|
|
|
|
// Note: These are only for testing for backward compatibility with foreign
|
|
|
|
// code and is not used by Verilator. Do not use these as there is no
|
|
|
|
// guarantee of functionality.
|
|
|
|
|
2020-04-04 17:45:24 +00:00
|
|
|
void declTriBit(vluint32_t code, const char* name, bool array, int arraynum);
|
|
|
|
void declTriBus(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
|
|
|
|
void declTriQuad(vluint32_t code, const char* name, bool array, int arraynum, int msb,
|
|
|
|
int lsb);
|
|
|
|
void declTriArray(vluint32_t code, const char* name, bool array, int arraynum, int msb,
|
|
|
|
int lsb);
|
2020-04-13 23:13:10 +00:00
|
|
|
|
2020-04-29 23:09:09 +00:00
|
|
|
void fullBit(vluint32_t* oldp, CData newval) { fullBit(oldp - this->oldp(0), newval); }
|
|
|
|
void fullCData(vluint32_t* oldp, CData newval, int bits) {
|
|
|
|
fullBus(oldp - this->oldp(0), newval, bits);
|
|
|
|
}
|
|
|
|
void fullSData(vluint32_t* oldp, SData newval, int bits) {
|
2020-04-25 18:37:59 +00:00
|
|
|
fullBus(oldp - this->oldp(0), newval, bits);
|
2020-04-13 23:13:10 +00:00
|
|
|
}
|
2020-04-29 23:09:09 +00:00
|
|
|
void fullIData(vluint32_t* oldp, IData newval, int bits) {
|
|
|
|
fullBus(oldp - this->oldp(0), newval, bits);
|
|
|
|
}
|
|
|
|
void fullQData(vluint32_t* oldp, QData newval, int bits) {
|
2020-04-19 22:57:36 +00:00
|
|
|
fullQuad(oldp - this->oldp(0), newval, bits);
|
2020-04-13 23:13:10 +00:00
|
|
|
}
|
2020-04-29 23:09:09 +00:00
|
|
|
void fullWData(vluint32_t* oldp, const WData* newvalp, int bits) {
|
2020-04-19 22:57:36 +00:00
|
|
|
fullArray(oldp - this->oldp(0), newvalp, bits);
|
2020-04-13 23:13:10 +00:00
|
|
|
}
|
2020-04-19 22:57:36 +00:00
|
|
|
void fullDouble(vluint32_t* oldp, double newval) { fullDouble(oldp - this->oldp(0), newval); }
|
2020-04-13 23:13:10 +00:00
|
|
|
|
2020-04-29 23:09:09 +00:00
|
|
|
inline void chgBit(vluint32_t* oldp, CData newval) { chgBit(oldp - this->oldp(0), newval); }
|
|
|
|
inline void chgCData(vluint32_t* oldp, CData newval, int bits) {
|
2020-04-25 18:37:59 +00:00
|
|
|
chgBus(oldp - this->oldp(0), newval, bits);
|
2020-04-13 23:13:10 +00:00
|
|
|
}
|
2020-04-29 23:09:09 +00:00
|
|
|
inline void chgSData(vluint32_t* oldp, SData newval, int bits) {
|
|
|
|
chgBus(oldp - this->oldp(0), newval, bits);
|
|
|
|
}
|
|
|
|
inline void chgIData(vluint32_t* oldp, IData newval, int bits) {
|
|
|
|
chgBus(oldp - this->oldp(0), newval, bits);
|
|
|
|
}
|
|
|
|
inline void chgQData(vluint32_t* oldp, QData newval, int bits) {
|
2020-04-19 22:57:36 +00:00
|
|
|
chgQuad(oldp - this->oldp(0), newval, bits);
|
2020-04-13 23:13:10 +00:00
|
|
|
}
|
2020-04-29 23:09:09 +00:00
|
|
|
inline void chgWData(vluint32_t* oldp, const WData* newvalp, int bits) {
|
2020-04-19 22:57:36 +00:00
|
|
|
chgArray(oldp - this->oldp(0), newvalp, bits);
|
2020-04-13 23:13:10 +00:00
|
|
|
}
|
2020-04-29 23:09:09 +00:00
|
|
|
inline void chgDouble(vluint32_t* oldp, double newval) {
|
|
|
|
chgDouble(oldp - this->oldp(0), newval);
|
|
|
|
}
|
2020-04-13 23:13:10 +00:00
|
|
|
|
2020-04-09 12:19:26 +00:00
|
|
|
/// Inside dumping routines, dump one signal, faster when not inlined
|
|
|
|
/// due to code size reduction.
|
|
|
|
void fullBit(vluint32_t code, const vluint32_t newval);
|
|
|
|
void fullBus(vluint32_t code, const vluint32_t newval, int bits);
|
|
|
|
void fullQuad(vluint32_t code, const vluint64_t newval, int bits);
|
2020-04-13 23:13:10 +00:00
|
|
|
void fullArray(vluint32_t code, const vluint32_t* newvalp, int bits);
|
|
|
|
void fullArray(vluint32_t code, const vluint64_t* newvalp, int bits);
|
2020-04-09 12:19:26 +00:00
|
|
|
void fullTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri);
|
|
|
|
void fullTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits);
|
2020-05-17 13:52:03 +00:00
|
|
|
void fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint64_t newtri, int bits);
|
2020-04-13 23:13:10 +00:00
|
|
|
void fullTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip,
|
|
|
|
int bits);
|
2018-08-22 23:14:06 +00:00
|
|
|
void fullDouble(vluint32_t code, const double newval);
|
2010-01-24 23:37:01 +00:00
|
|
|
|
2020-04-09 12:19:26 +00:00
|
|
|
/// Inside dumping routines, dump one signal if it has changed.
|
|
|
|
/// We do want to inline these to avoid calls when the value did not change.
|
2018-08-22 23:14:06 +00:00
|
|
|
inline void chgBit(vluint32_t code, const vluint32_t newval) {
|
2020-04-19 22:57:36 +00:00
|
|
|
vluint32_t diff = oldp(code)[0] ^ newval;
|
2020-04-13 23:13:10 +00:00
|
|
|
if (VL_UNLIKELY(diff)) fullBit(code, newval);
|
2010-01-24 23:37:01 +00:00
|
|
|
}
|
2018-08-22 23:14:06 +00:00
|
|
|
inline void chgBus(vluint32_t code, const vluint32_t newval, int bits) {
|
2020-04-19 22:57:36 +00:00
|
|
|
vluint32_t diff = oldp(code)[0] ^ newval;
|
2018-08-22 23:14:06 +00:00
|
|
|
if (VL_UNLIKELY(diff)) {
|
2019-11-10 01:35:12 +00:00
|
|
|
if (VL_UNLIKELY(bits == 32 || (diff & ((1U << bits) - 1)))) {
|
2018-08-22 23:14:06 +00:00
|
|
|
fullBus(code, newval, bits);
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 23:37:01 +00:00
|
|
|
}
|
2018-08-22 23:14:06 +00:00
|
|
|
inline void chgQuad(vluint32_t code, const vluint64_t newval, int bits) {
|
2020-04-19 22:57:36 +00:00
|
|
|
vluint64_t diff = (*(reinterpret_cast<vluint64_t*>(oldp(code)))) ^ newval;
|
2018-08-22 23:14:06 +00:00
|
|
|
if (VL_UNLIKELY(diff)) {
|
2020-05-29 00:32:07 +00:00
|
|
|
if (VL_UNLIKELY(bits == 64 || (diff & ((1ULL << bits) - 1)))) {
|
2018-08-22 23:14:06 +00:00
|
|
|
fullQuad(code, newval, bits);
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 23:37:01 +00:00
|
|
|
}
|
2020-04-13 23:13:10 +00:00
|
|
|
inline void chgArray(vluint32_t code, const vluint32_t* newvalp, int bits) {
|
2019-11-10 01:35:12 +00:00
|
|
|
for (int word = 0; word < (((bits - 1) / 32) + 1); ++word) {
|
2020-04-19 22:57:36 +00:00
|
|
|
if (VL_UNLIKELY(oldp(code)[word] ^ newvalp[word])) {
|
2020-04-13 23:13:10 +00:00
|
|
|
fullArray(code, newvalp, bits);
|
2018-08-22 23:14:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 23:37:01 +00:00
|
|
|
}
|
2020-04-13 23:13:10 +00:00
|
|
|
inline void chgArray(vluint32_t code, const vluint64_t* newvalp, int bits) {
|
2019-12-06 03:25:30 +00:00
|
|
|
for (int word = 0; word < (((bits - 1) / 64) + 1); ++word) {
|
2020-04-19 22:57:36 +00:00
|
|
|
if (VL_UNLIKELY(*(reinterpret_cast<vluint64_t*>(oldp(code + 2 * word)))
|
|
|
|
^ newvalp[word])) {
|
2020-04-13 23:13:10 +00:00
|
|
|
fullArray(code, newvalp, bits);
|
2019-12-06 03:25:30 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-04-04 17:45:24 +00:00
|
|
|
inline void chgTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri) {
|
2020-04-19 22:57:36 +00:00
|
|
|
vluint32_t diff = ((oldp(code)[0] ^ newval) | (oldp(code)[1] ^ newtri));
|
2018-08-22 23:14:06 +00:00
|
|
|
if (VL_UNLIKELY(diff)) {
|
2019-05-15 02:49:21 +00:00
|
|
|
// Verilator 3.510 and newer provide clean input, so the below
|
|
|
|
// is only for back compatibility
|
2018-08-22 23:14:06 +00:00
|
|
|
if (VL_UNLIKELY(diff & 1)) { // Change after clean?
|
|
|
|
fullTriBit(code, newval, newtri);
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 23:37:01 +00:00
|
|
|
}
|
2020-04-04 17:45:24 +00:00
|
|
|
inline void chgTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri,
|
|
|
|
int bits) {
|
2020-04-19 22:57:36 +00:00
|
|
|
vluint32_t diff = ((oldp(code)[0] ^ newval) | (oldp(code)[1] ^ newtri));
|
2018-08-22 23:14:06 +00:00
|
|
|
if (VL_UNLIKELY(diff)) {
|
2020-04-04 17:45:24 +00:00
|
|
|
if (VL_UNLIKELY(bits == 32 || (diff & ((1U << bits) - 1)))) {
|
2018-08-22 23:14:06 +00:00
|
|
|
fullTriBus(code, newval, newtri, bits);
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 23:37:01 +00:00
|
|
|
}
|
2020-05-17 13:52:03 +00:00
|
|
|
inline void chgTriQuad(vluint32_t code, const vluint64_t newval, const vluint64_t newtri,
|
2020-04-04 17:45:24 +00:00
|
|
|
int bits) {
|
2020-04-19 22:57:36 +00:00
|
|
|
vluint64_t diff = (((*(reinterpret_cast<vluint64_t*>(oldp(code)))) ^ newval)
|
|
|
|
| ((*(reinterpret_cast<vluint64_t*>(oldp(code + 1)))) ^ newtri));
|
2018-08-22 23:14:06 +00:00
|
|
|
if (VL_UNLIKELY(diff)) {
|
2020-05-29 00:32:07 +00:00
|
|
|
if (VL_UNLIKELY(bits == 64 || (diff & ((1ULL << bits) - 1)))) {
|
2018-08-22 23:14:06 +00:00
|
|
|
fullTriQuad(code, newval, newtri, bits);
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 23:37:01 +00:00
|
|
|
}
|
2020-04-04 17:45:24 +00:00
|
|
|
inline void chgTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip,
|
|
|
|
int bits) {
|
|
|
|
for (int word = 0; word < (((bits - 1) / 32) + 1); ++word) {
|
2020-04-19 22:57:36 +00:00
|
|
|
if (VL_UNLIKELY((oldp(code)[word * 2] ^ newvalp[word])
|
|
|
|
| (oldp(code)[word * 2 + 1] ^ newtrip[word]))) {
|
2020-04-04 17:45:24 +00:00
|
|
|
fullTriArray(code, newvalp, newtrip, bits);
|
2018-08-22 23:14:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 23:37:01 +00:00
|
|
|
}
|
2018-08-22 23:14:06 +00:00
|
|
|
inline void chgDouble(vluint32_t code, const double newval) {
|
|
|
|
// cppcheck-suppress invalidPointerCast
|
2020-04-19 22:57:36 +00:00
|
|
|
if (VL_UNLIKELY((*(reinterpret_cast<double*>(oldp(code)))) != newval)) {
|
2018-08-22 23:14:06 +00:00
|
|
|
fullDouble(code, newval);
|
|
|
|
}
|
2010-01-24 23:37:01 +00:00
|
|
|
}
|
2017-11-01 22:51:41 +00:00
|
|
|
|
|
|
|
// METHODS
|
2020-05-16 11:43:22 +00:00
|
|
|
// Old/standalone API only
|
2017-11-01 22:51:41 +00:00
|
|
|
void evcd(bool flag) { m_evcd = flag; }
|
2020-04-19 22:57:36 +00:00
|
|
|
#endif // VL_TRACE_VCD_OLD_API
|
2010-01-24 23:37:01 +00:00
|
|
|
};
|
|
|
|
|
2020-04-19 22:57:36 +00:00
|
|
|
// Declare specializations here they are used in VerilatedVcdC just below
|
|
|
|
template <> void VerilatedTrace<VerilatedVcd>::dump(vluint64_t timeui);
|
|
|
|
template <> void VerilatedTrace<VerilatedVcd>::set_time_unit(const char* unitp);
|
|
|
|
template <> void VerilatedTrace<VerilatedVcd>::set_time_unit(const std::string& unit);
|
|
|
|
template <> void VerilatedTrace<VerilatedVcd>::set_time_resolution(const char* unitp);
|
|
|
|
template <> void VerilatedTrace<VerilatedVcd>::set_time_resolution(const std::string& unit);
|
|
|
|
|
2010-01-24 23:37:01 +00:00
|
|
|
//=============================================================================
|
|
|
|
// VerilatedVcdC
|
|
|
|
/// Create a VCD dump file in C standalone (no SystemC) simulations.
|
2017-10-27 01:51:51 +00:00
|
|
|
/// Also derived for use in SystemC simulations.
|
|
|
|
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
|
2010-01-24 23:37:01 +00:00
|
|
|
|
|
|
|
class VerilatedVcdC {
|
2018-08-22 23:14:06 +00:00
|
|
|
VerilatedVcd m_sptrace; ///< Trace file being created
|
2017-11-01 22:51:41 +00:00
|
|
|
|
2010-01-24 23:37:01 +00:00
|
|
|
// CONSTRUCTORS
|
2017-11-01 22:51:41 +00:00
|
|
|
VL_UNCOPYABLE(VerilatedVcdC);
|
2020-04-04 17:45:24 +00:00
|
|
|
|
2017-11-01 22:51:41 +00:00
|
|
|
public:
|
2019-11-10 01:35:12 +00:00
|
|
|
explicit VerilatedVcdC(VerilatedVcdFile* filep = NULL)
|
|
|
|
: m_sptrace(filep) {}
|
2020-03-02 02:39:23 +00:00
|
|
|
~VerilatedVcdC() { close(); }
|
2020-03-02 12:43:10 +00:00
|
|
|
/// Routines can only be called from one thread; allow next call from different thread
|
|
|
|
void changeThread() { spTrace()->changeThread(); }
|
2020-04-04 17:45:24 +00:00
|
|
|
|
2017-11-01 22:51:41 +00:00
|
|
|
public:
|
2010-01-24 23:37:01 +00:00
|
|
|
// ACCESSORS
|
|
|
|
/// Is file open?
|
|
|
|
bool isOpen() const { return m_sptrace.isOpen(); }
|
|
|
|
// METHODS
|
|
|
|
/// Open a new VCD file
|
2013-02-24 02:10:25 +00:00
|
|
|
/// This includes a complete header dump each time it is called,
|
|
|
|
/// just as if this object was deleted and reconstructed.
|
2017-10-27 01:51:51 +00:00
|
|
|
void open(const char* filename) VL_MT_UNSAFE_ONE { m_sptrace.open(filename); }
|
2010-01-24 23:37:01 +00:00
|
|
|
/// Continue a VCD dump by rotating to a new file name
|
2013-02-24 02:10:25 +00:00
|
|
|
/// 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.
|
2019-11-10 01:35:12 +00:00
|
|
|
void openNext(bool incFilename = true) VL_MT_UNSAFE_ONE { m_sptrace.openNext(incFilename); }
|
2010-01-24 23:37:01 +00:00
|
|
|
/// Set size in megabytes after which new file should be created
|
2019-06-11 22:31:06 +00:00
|
|
|
void rolloverMB(size_t rolloverMB) { m_sptrace.rolloverMB(rolloverMB); }
|
2010-01-24 23:37:01 +00:00
|
|
|
/// Close dump
|
2017-10-27 01:51:51 +00:00
|
|
|
void close() VL_MT_UNSAFE_ONE { m_sptrace.close(); }
|
2010-01-24 23:37:01 +00:00
|
|
|
/// Flush dump
|
2017-10-27 01:51:51 +00:00
|
|
|
void flush() VL_MT_UNSAFE_ONE { m_sptrace.flush(); }
|
2010-01-24 23:37:01 +00:00
|
|
|
/// Write one cycle of dump data
|
2018-08-22 23:14:06 +00:00
|
|
|
void dump(vluint64_t timeui) { m_sptrace.dump(timeui); }
|
2010-01-24 23:37:01 +00:00
|
|
|
/// Write one cycle of dump data - backward compatible and to reduce
|
|
|
|
/// conversion warnings. It's better to use a vluint64_t time instead.
|
2018-08-22 23:14:06 +00:00
|
|
|
void dump(double timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
|
|
|
|
void dump(vluint32_t timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
|
|
|
|
void dump(int timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
|
2017-06-20 23:33:58 +00:00
|
|
|
/// Set time units (s/ms, defaults to ns)
|
2020-04-15 23:39:03 +00:00
|
|
|
/// For Verilated models, these propage from the Verilated default --timeunit
|
2018-08-22 23:14:06 +00:00
|
|
|
void set_time_unit(const char* unit) { m_sptrace.set_time_unit(unit); }
|
2020-04-19 22:57:36 +00:00
|
|
|
void set_time_unit(const std::string& unit) { m_sptrace.set_time_unit(unit); }
|
2017-06-20 23:33:58 +00:00
|
|
|
/// Set time resolution (s/ms, defaults to ns)
|
2020-04-15 23:39:03 +00:00
|
|
|
/// For Verilated models, these propage from the Verilated default --timeunit
|
2018-08-22 23:14:06 +00:00
|
|
|
void set_time_resolution(const char* unit) { m_sptrace.set_time_resolution(unit); }
|
2020-04-19 22:57:36 +00:00
|
|
|
void set_time_resolution(const std::string& unit) { m_sptrace.set_time_resolution(unit); }
|
2017-06-20 23:33:58 +00:00
|
|
|
|
2010-01-24 23:37:01 +00:00
|
|
|
/// Internal class access
|
2019-06-11 22:31:06 +00:00
|
|
|
inline VerilatedVcd* spTrace() { return &m_sptrace; }
|
2020-05-16 11:43:22 +00:00
|
|
|
|
|
|
|
#ifdef VL_TRACE_VCD_OLD_API
|
|
|
|
//=========================================================================
|
|
|
|
// Note: These are only for testing for backward compatibility with foreign
|
|
|
|
// code and is not used by Verilator. Do not use these as there is no
|
|
|
|
// guarantee of functionality.
|
|
|
|
/// Use evcd format
|
|
|
|
void evcd(bool flag) VL_MT_UNSAFE_ONE { m_sptrace.evcd(flag); }
|
|
|
|
#endif
|
2010-01-24 23:37:01 +00:00
|
|
|
};
|
|
|
|
|
2018-08-22 23:14:06 +00:00
|
|
|
#endif // guard
|