Commentary

This commit is contained in:
Wilson Snyder 2021-03-28 11:50:05 -04:00
parent f39318bde5
commit 8992e2ec02
14 changed files with 152 additions and 129 deletions

View File

@ -95,7 +95,7 @@ VL_THREAD_LOCAL Verilated::ThreadLocal Verilated::t_s;
// Note a TODO is a future version of the API will pass a structure so that
// the calling arguments allow for extension
#ifndef VL_USER_FINISH ///< Define this to override this function
#ifndef VL_USER_FINISH ///< Define this to override the vl_finish function
void vl_finish(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
if (false && hier) {}
VL_PRINTF( // Not VL_PRINTF_MT, already on main thread
@ -111,7 +111,7 @@ void vl_finish(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE
}
#endif
#ifndef VL_USER_STOP ///< Define this to override this function
#ifndef VL_USER_STOP ///< Define this to override the vl_stop function
void vl_stop(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
const char* const msg = "Verilog $stop";
Verilated::threadContextp()->gotError(true);
@ -130,7 +130,7 @@ void vl_stop(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
}
#endif
#ifndef VL_USER_FATAL ///< Define this to override this function
#ifndef VL_USER_FATAL ///< Define this to override the vl_fatal function
void vl_fatal(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_UNSAFE {
if (false && hier) {}
Verilated::threadContextp()->gotError(true);
@ -154,7 +154,7 @@ void vl_fatal(const char* filename, int linenum, const char* hier, const char* m
}
#endif
#ifndef VL_USER_STOP_MAYBE ///< Define this to override this function
#ifndef VL_USER_STOP_MAYBE ///< Define this to override the vl_stop_maybe function
void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool maybe) VL_MT_UNSAFE {
Verilated::threadContextp()->errorCountInc();
if (maybe
@ -204,7 +204,7 @@ void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char
//===========================================================================
// Debug prints
/// sprintf but return as string (this isn't fast, for print messages only)
// sprintf but return as string (this isn't fast, for print messages only)
std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
va_list aq;
va_copy(aq, ap);
@ -598,7 +598,7 @@ double VL_ISTOR_D_W(int lbits, WDataInP lwp) VL_PURE {
//===========================================================================
// Formatting
/// Output a string representation of a wide number
// Output a string representation of a wide number
std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE {
int maxdecwidth = (width + 3) * 4 / 3;
// Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word

View File

@ -75,37 +75,38 @@
#endif
// clang-format on
//=========================================================================
// Basic types
// clang-format off
// P // Packed data of bit type (C/S/I/Q/W)
typedef vluint8_t CData; ///< Verilated pack data, 1-8 bits
typedef vluint16_t SData; ///< Verilated pack data, 9-16 bits
typedef vluint32_t IData; ///< Verilated pack data, 17-32 bits
typedef vluint64_t QData; ///< Verilated pack data, 33-64 bits
typedef vluint32_t EData; ///< Verilated pack element of WData array
typedef EData WData; ///< Verilated pack data, >64 bits, as an array
// float F // No typedef needed; Verilator uses float
// double D // No typedef needed; Verilator uses double
// string N // No typedef needed; Verilator uses string
// clang-format on
typedef const WData* WDataInP; ///< Array input to a function
typedef WData* WDataOutP; ///< Array output from a function
class VerilatedContextImp;
class VerilatedContextImpData;
class VerilatedCovContext;
class VerilatedEvalMsgQueue;
class VerilatedFst;
class VerilatedFstC;
class VerilatedScope;
class VerilatedScopeNameMap;
class VerilatedVar;
class VerilatedVarNameMap;
class VerilatedVcd;
class VerilatedVcdC;
class VerilatedVcdSc;
class VerilatedFst;
class VerilatedFstC;
//=========================================================================
// Basic types
// clang-format off
// P // Packed data of bit type (C/S/I/Q/W)
typedef vluint8_t CData; ///< Data representing 'bit' of 1-8 packed bits
typedef vluint16_t SData; ///< Data representing 'bit' of 9-16 packed bits
typedef vluint32_t IData; ///< Data representing 'bit' of 17-32 packed bits
typedef vluint64_t QData; ///< Data representing 'bit' of 33-64 packed bits
typedef vluint32_t EData; ///< Data representing one element of WData array
typedef EData WData; ///< Data representing >64 packed bits (used as pointer)
// float F // No typedef needed; Verilator uses float
// double D // No typedef needed; Verilator uses double
// string N // No typedef needed; Verilator uses string
// clang-format on
typedef const WData* WDataInP; ///< 'bit' of >64 packed bits as array input to a function
typedef WData* WDataOutP; ///< 'bit' of >64 packed bits as array output from a function
enum VerilatedVarType : vluint8_t {
VLVT_UNKNOWN = 0,
@ -218,7 +219,7 @@ public:
class VerilatedAssertOneThread final {
// MEMBERS
#if defined(VL_THREADED) && defined(VL_DEBUG)
vluint32_t m_threadid; /// Thread that is legal
vluint32_t m_threadid; // Thread that is legal
public:
// CONSTRUCTORS
// The constructor establishes the thread id for all later calls.
@ -245,9 +246,7 @@ public:
};
//=========================================================================
/// Base class for all Verilated module classes
class VerilatedScope;
/// Base class for all Verilated module classes.
class VerilatedModule VL_NOT_FINAL {
VL_UNCOPYABLE(VerilatedModule);
@ -255,7 +254,7 @@ class VerilatedModule VL_NOT_FINAL {
private:
const char* m_namep; // Module name
public:
explicit VerilatedModule(const char* namep); ///< Create module with given hierarchy name
explicit VerilatedModule(const char* namep); // Create module with given hierarchy name
~VerilatedModule();
const char* name() const { return m_namep; } ///< Return name of module
};
@ -286,7 +285,7 @@ public:
#define VL_CELL(instname, type) ///< Declare a cell, ala SP_CELL
/// Declare a module, ala SC_MODULE
///< Declare a module, ala SC_MODULE
#define VL_MODULE(modname) class modname VL_NOT_FINAL : public VerilatedModule
// Not class final in VL_MODULE, as users might be abstracting our models (--hierarchical)
@ -470,6 +469,8 @@ public:
int randSeed() const VL_MT_SAFE { return m_s.m_randSeed; }
// Time handling
/// Returns current simulation time.
///
/// How Verilator runtime gets the current simulation time:
///
/// * If using SystemC, time comes from the SystemC kernel-defined
@ -553,8 +554,8 @@ public: // But for internal use only
};
//===========================================================================
/// Verilator symbol table base class
/// Used for internal VPI implementation, and introspection into scopes
// Verilator symbol table base class
// Used for internal VPI implementation, and introspection into scopes
class VerilatedSyms VL_NOT_FINAL {
public: // But for internal use only
@ -569,8 +570,8 @@ public: // But for internal use only
};
//===========================================================================
/// Verilator scope information class
/// Used for internal VPI implementation, and introspection into scopes
// Verilator scope information class
// Used for internal VPI implementation, and introspection into scopes
class VerilatedScope final {
public:
@ -1008,18 +1009,18 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
//=========================================================================
// Base macros
/// Return true if data[bit] set; not 0/1 return, but 0/non-zero return.
// Return true if data[bit] set; not 0/1 return, but 0/non-zero return.
#define VL_BITISSET_I(data, bit) ((data) & (VL_UL(1) << VL_BITBIT_I(bit)))
#define VL_BITISSET_Q(data, bit) ((data) & (1ULL << VL_BITBIT_Q(bit)))
#define VL_BITISSET_E(data, bit) ((data) & (VL_EUL(1) << VL_BITBIT_E(bit)))
#define VL_BITISSET_W(data, bit) ((data)[VL_BITWORD_E(bit)] & (VL_EUL(1) << VL_BITBIT_E(bit)))
#define VL_BITISSETLIMIT_W(data, width, bit) (((bit) < (width)) && VL_BITISSET_W(data, bit))
/// Shift appropriate word by bit. Does not account for wrapping between two words
// Shift appropriate word by bit. Does not account for wrapping between two words
#define VL_BITRSHIFT_W(data, bit) ((data)[VL_BITWORD_E(bit)] >> VL_BITBIT_E(bit))
/// Create two 32-bit words from quadword
/// WData is always at least 2 words; does not clean upper bits
// Create two 32-bit words from quadword
// WData is always at least 2 words; does not clean upper bits
#define VL_SET_WQ(owp, data) \
do { \
(owp)[0] = static_cast<IData>(data); \
@ -1138,8 +1139,8 @@ extern int VL_TIME_STR_CONVERT(const char* strp) VL_PURE;
# endif
#endif
/// Return current simulation time
#if defined(SYSTEMC_VERSION)
/// Return current simulation time
// Already defined: extern sc_time sc_time_stamp();
inline vluint64_t vl_time_stamp64() { return sc_time_stamp().value(); }
#else // Non-SystemC
@ -1187,8 +1188,8 @@ inline vluint64_t VerilatedContext::time() const VL_MT_SAFE {
// Return time precision as multiplier of time units
double vl_time_multiplier(int scale) VL_PURE;
/// Evaluate statement if debug enabled
#ifdef VL_DEBUG
/// Evaluate statement if Verilated::debug() enabled
# define VL_DEBUG_IF(stmt) \
do { \
if (VL_UNLIKELY(Verilated::debug())) {stmt} \
@ -2768,7 +2769,7 @@ static inline WDataOutP VL_SEL_WWII(int obits, int lbits, int, int, WDataOutP ow
//======================================================================
// Math needing insert/select
/// Return QData from double (numeric)
// Return QData from double (numeric)
// EMIT_RULE: VL_RTOIROUND_Q_D: oclean=dirty; lclean==clean/real
static inline QData VL_RTOIROUND_Q_D(int, double lhs) VL_PURE {
// IEEE format: [63]=sign [62:52]=exp+1023 [51:0]=mantissa

View File

@ -444,6 +444,7 @@ void VerilatedCovContext::_insertf(const char* filename, int lineno) VL_MT_SAFE
impp()->insertf(filename, lineno);
}
#ifndef DOXYGEN
#define K(n) const char* key##n
#define A(n) const char *key##n, const char *valp##n // Argument list
#define C(n) key##n, valp##n // Calling argument list
@ -493,6 +494,8 @@ void VerilatedCovContext::_insertp(A(0), A(1), K(2), int val2, K(3), int val3, K
#undef N
#undef K
#endif // DOXYGEN
//=============================================================================
// VerilatedCov

View File

@ -86,7 +86,7 @@ class VerilatedCovImp;
covcontextp->_insertp("hier", name(), __VA_ARGS__))
//=============================================================================
/// Convert VL_COVER_INSERT value arguments to strings, is \internal
// Convert VL_COVER_INSERT value arguments to strings, is \internal
template <class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
std::ostringstream os;
@ -96,7 +96,7 @@ template <class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
//=============================================================================
// VerilatedCov
/// Verilator coverage per-context structure.
/// Per-VerilatedContext coverage data class.
/// All public methods in this class are thread safe.
///
/// This structure is accessed and constructed on first access via
@ -134,6 +134,7 @@ public: // But Internal use only
// We could have just the maximum argument version, but this compiles
// much slower (nearly 2x) than having smaller versions also. However
// there's not much more gain in having a version for each number of args.
#ifndef DOXYGEN
#define K(n) const char* key##n
#define A(n) const char *key##n, const char *valp##n // Argument list
#define D(n) const char *key##n = nullptr, const char *valp##n = nullptr // Argument list
@ -150,6 +151,7 @@ public: // But Internal use only
#undef K
#undef A
#undef D
#endif // DOXYGEN
protected:
friend class VerilatedCovImp;
@ -165,7 +167,7 @@ protected:
//=============================================================================
// VerilatedCov
/// Verilator coverage global class
/// Coverage global class.
///
/// Global class that accesses via current thread's context's
/// VerilatedCovContext. This class is provided only for
@ -196,6 +198,6 @@ private:
// Current thread's coverage structure
static VerilatedCovContext* threadCovp() VL_MT_SAFE;
};
#endif
#endif // VL_NO_LEGACY
#endif // Guard

View File

@ -17,7 +17,6 @@
/// User wrapper code should use this header when creating FST traces.
///
//=============================================================================
// SPDIFF_OFF
#ifndef VERILATOR_VERILATED_FST_C_H_
#define VERILATOR_VERILATED_FST_C_H_
@ -115,12 +114,14 @@ public:
fstVarType vartype, bool array, int arraynum);
};
#ifndef DOXYGEN
// Declare specialization here as it's used in VerilatedFstC just below
template <> void VerilatedTrace<VerilatedFst>::dump(vluint64_t timeui);
template <> void VerilatedTrace<VerilatedFst>::set_time_unit(const char* unitp);
template <> void VerilatedTrace<VerilatedFst>::set_time_unit(const std::string& unit);
template <> void VerilatedTrace<VerilatedFst>::set_time_resolution(const char* unitp);
template <> void VerilatedTrace<VerilatedFst>::set_time_resolution(const std::string& unit);
#endif
//=============================================================================
// VerilatedFstC

View File

@ -88,12 +88,14 @@ public:
};
//===================================================================
// Verilog wide-number-in-array container
// Similar to std::array<WData, N>, but lighter weight, only methods needed
// by Verilator, to help compile time.
//
// This is only used when we need an upper-level container and so can't
// simply use a C style array (which is just a pointer).
/// Verilog wide unpacked bit container.
/// Similar to std::array<WData, N>, but lighter weight, only methods needed
/// by Verilator, to help compile time.
///
/// For example a Verilog "bit [94:0]" will become a VlWide<3> because 3*32
/// bits are needed to hold the 95 bits. The MSB (bit 96) must always be
/// zero in memory, but during intermediate operations in the Verilated
/// internals is unpredictable.
template <std::size_t T_Words> class VlWide final {
EData m_storage[T_Words];
@ -795,9 +797,12 @@ void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename,
}
//===================================================================
// Verilog packed array container
// For when a standard C++[] array is not sufficient, e.g. an
// array under a queue, or methods operating on the array
/// Verilog packed array container
/// For when a standard C++[] array is not sufficient, e.g. an
/// array under a queue, or methods operating on the array.
///
/// This class may get exposed to a Verilated Model's top I/O, if the top
/// IO has an unpacked array.
template <class T_Value, std::size_t T_Depth> class VlUnpacked final {
private:
@ -849,7 +854,6 @@ std::string VL_TO_STRING(const VlUnpacked<T_Value, T_Depth>& obj) {
// Verilog class reference container
// There are no multithreaded locks on this; the base variable must
// be protected by other means
//
#define VlClassRef std::shared_ptr

View File

@ -49,7 +49,7 @@ class VerilatedScope;
// Threaded message passing
#ifdef VL_THREADED
/// Message, enqueued on an mtask, and consumed on the main eval thread
// Message, enqueued on an mtask, and consumed on the main eval thread
class VerilatedMsg final {
public:
// TYPES
@ -75,13 +75,13 @@ public:
VerilatedMsg& operator=(VerilatedMsg&&) = default;
// METHODS
vluint32_t mtaskId() const { return m_mtaskId; }
/// Execute the lambda function
// Execute the lambda function
void run() const { m_cb(); }
};
/// Each thread has a queue it pushes to
/// This assumes no thread starts pushing the next tick until the previous has drained.
/// If more aggressiveness is needed, a double-buffered scheme might work well.
// Each thread has a queue it pushes to
// This assumes no thread starts pushing the next tick until the previous has drained.
// If more aggressiveness is needed, a double-buffered scheme might work well.
class VerilatedEvalMsgQueue final {
using VerilatedThreadQueue = std::multiset<VerilatedMsg, VerilatedMsg::Cmp>;
@ -102,13 +102,13 @@ private:
public:
// METHODS
//// Add message to queue (called by producer)
// Add message to queue (called by producer)
void post(const VerilatedMsg& msg) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
m_queue.insert(msg); // Pass by value to copy the message into queue
++m_depth;
}
/// Service queue until completion (called by consumer)
// Service queue until completion (called by consumer)
void process() VL_MT_SAFE_EXCLUDES(m_mutex) {
// Tracking m_depth is redundant to e.g. getting the mutex and looking at queue size,
// but on the reader side it's 4x faster to test an atomic then getting a mutex
@ -133,7 +133,7 @@ public:
}
};
/// Each thread has a local queue to build up messages until the end of the eval() call
// Each thread has a local queue to build up messages until the end of the eval() call
class VerilatedThreadMsgQueue final {
std::queue<VerilatedMsg> m_queue;
@ -154,7 +154,7 @@ private:
}
public:
/// Add message to queue, called by producer
// Add message to queue, called by producer
static void post(const VerilatedMsg& msg) VL_MT_SAFE {
// Handle calls to threaded routines outside
// of any mtask -- if an initial block calls $finish, say.
@ -166,7 +166,7 @@ public:
threadton().m_queue.push(msg); // Pass by value to copy the message into queue
}
}
/// Push all messages to the eval's queue
// Push all messages to the eval's queue
static void flush(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
while (!threadton().m_queue.empty()) {
evalMsgQp->post(threadton().m_queue.front());
@ -204,7 +204,7 @@ class VerilatedContextImpData final {
friend class VerilatedContextImp;
protected:
/// Map of <scope_name, scope pointer>
// Map of <scope_name, scope pointer>
// Used by scopeInsert, scopeFind, scopeErase, scopeNameMap
mutable VerilatedMutex m_nameMutex; // Protect m_nameMap
VerilatedScopeNameMap m_nameMap VL_GUARDED_BY(m_nameMutex);
@ -474,7 +474,7 @@ public:
}
public: // But only for verilated.cpp
/// Symbol table destruction cleans up the entries for each scope.
// Symbol table destruction cleans up the entries for each scope.
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope on destruction, so we simply iterate.
const VerilatedLockGuard lock(s().m_userMapMutex);

View File

@ -50,9 +50,9 @@
// clang-format on
// CONSTANTS
/// Value of first bytes of each file (must be multiple of 8 bytes)
// Value of first bytes of each file (must be multiple of 8 bytes)
static const char* const VLTSAVE_HEADER_STR = "verilatorsave02\n";
/// Value of last bytes of each file (must be multiple of 8 bytes)
// Value of last bytes of each file (must be multiple of 8 bytes)
static const char* const VLTSAVE_TRAILER_STR = "vltsaved";
//=============================================================================

View File

@ -29,7 +29,7 @@
//=============================================================================
// VerilatedSerialize
/// Convert structures to a stream representation.
/// Class for writing serialization of structures to a stream representation.
///
/// User wrapper code will more typically use VerilatedSave which uses this
/// as a subclass to write a file.
@ -100,7 +100,7 @@ private:
//=============================================================================
// VerilatedDeserialize
/// Load structures from a stream representation
/// Class for loading structures from a stream representation.
///
/// User wrapper code will more typically use VerilatedRestore which uses
/// this as a subclass to a read from a file.

View File

@ -1,5 +1,5 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// -*- mode: C++; c-file-style: "cc-mode"
//-*- *************************************************************************
//
// Code available from: https://verilator.org
//
@ -18,6 +18,9 @@
/// the symbol table. It is not included in verilated.h (instead see
/// verilated_sym_props.h) as it requires some heavyweight C++ classes.
///
/// These classes are rarely used by user code; typical user code will
/// instead use the VPI to access this information.
///
/// These classes are thread safe and read only. It is constructed only
/// when a model is built (from the main thread).
///
@ -35,14 +38,14 @@
#include <vector>
//======================================================================
/// Types
// Types
/// Class to sort maps keyed by const char*'s
// Class to sort maps keyed by const char*'s
struct VerilatedCStrCmp {
bool operator()(const char* a, const char* b) const { return std::strcmp(a, b) < 0; }
};
/// Map of sorted scope names to find associated scope class
// Map of sorted scope names to find associated scope class
// This is a class instead of typedef/using to allow forward declaration in verilated.h
class VerilatedScopeNameMap final
: public std::map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
@ -51,7 +54,7 @@ public:
~VerilatedScopeNameMap() = default;
};
/// Map of sorted variable names to find associated variable class
// Map of sorted variable names to find associated variable class
// This is a class instead of typedef/using to allow forward declaration in verilated.h
class VerilatedVarNameMap final : public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
public:
@ -59,7 +62,7 @@ public:
~VerilatedVarNameMap() = default;
};
/// Map of parent scope to vector of children scopes
// Map of parent scope to vector of children scopes
// This is a class instead of typedef/using to allow forward declaration in verilated.h
class VerilatedHierarchyMap final
: public std::unordered_map<const VerilatedScope*, std::vector<const VerilatedScope*>> {

View File

@ -17,7 +17,6 @@
/// User wrapper code should use this header when creating VCD traces.
///
//=============================================================================
// SPDIFF_OFF
#ifndef VERILATOR_VERILATED_VCD_C_H_
#define VERILATOR_VERILATED_VCD_C_H_
@ -31,20 +30,25 @@
class VerilatedVcd;
// SPDIFF_ON
//=============================================================================
// VerilatedFile
/// File handling routines, which can be overrode for e.g. socket I/O
/// Class representing a file to write to. These virtual methods can be
/// overrode for e.g. socket I/O.
class VerilatedVcdFile VL_NOT_FINAL {
private:
int m_fd = 0; // File descriptor we're writing to
public:
// METHODS
/// Construct a (as yet) closed file
VerilatedVcdFile() = default;
/// Close and destruct
virtual ~VerilatedVcdFile() = 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;
};
@ -318,17 +322,19 @@ public:
#endif // VL_TRACE_VCD_OLD_API
};
#ifndef DOXYGEN
// 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);
#endif // DOXYGEN
//=============================================================================
// VerilatedVcdC
/// Create a VCD dump file in C standalone (no SystemC) simulations.
/// Also derived for use in SystemC simulations.
/// Class representing a VCD dump file in C standalone (no SystemC)
/// simulations. Also derived for use in SystemC simulations.
class VerilatedVcdC VL_NOT_FINAL {
VerilatedVcd m_sptrace; // Trace file being created

View File

@ -29,8 +29,9 @@
//=============================================================================
// VerilatedVcdSc
///
/// This class creates a Verilator-friendly VCD trace format with the
/// SystemC simulation kernel, just like a SystemC-documented trace format.
/// Class representing a Verilator-friendly VCD trace format registered
/// with the SystemC simulation kernel, just like a SystemC-documented
/// trace format.
class VerilatedVcdSc final : sc_trace_file, public VerilatedVcdC {
// CONSTRUCTORS

View File

@ -35,6 +35,8 @@
//======================================================================
/// Class for namespace-like groupng of Verilator VPI functions.
class VerilatedVpi final {
public:
/// Call timed callbacks.

View File

@ -71,31 +71,31 @@
// Defaults for unsupported compiler features
#ifndef VL_ATTR_ALIGNED
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
# define VL_ATTR_ALIGNED(alignment) ///< Attribute to align structure to byte alignment
#endif
#ifndef VL_ATTR_ALWINLINE
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
# define VL_ATTR_ALWINLINE ///< Attribute to inline, even when not optimizing
#endif
#ifndef VL_ATTR_COLD
# define VL_ATTR_COLD ///< Function is rarely executed
# define VL_ATTR_COLD ///< Attribute that function is rarely executed
#endif
#ifndef VL_ATTR_HOT
# define VL_ATTR_HOT ///< Function is highly executed
# define VL_ATTR_HOT ///< Attribute that function is highly executed
#endif
#ifndef VL_ATTR_NORETURN
# define VL_ATTR_NORETURN ///< Function does not ever return
# define VL_ATTR_NORETURN ///< Attribute that function does not ever return
#endif
#ifndef VL_ATTR_PRINTF
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
# define VL_ATTR_PRINTF(fmtArgNum) ///< Attribute for function with printf format checking
#endif
#ifndef VL_ATTR_PURE
# define VL_ATTR_PURE ///< Function is pure (and thus also VL_MT_SAFE)
# define VL_ATTR_PURE ///< Attribute that function is pure (and thus also VL_MT_SAFE)
#endif
#ifndef VL_ATTR_UNUSED
# define VL_ATTR_UNUSED ///< Function that may be never used
# define VL_ATTR_UNUSED ///< Attribute that function that may be never used
#endif
#ifndef VL_ATTR_WEAK
# define VL_ATTR_WEAK ///< Function external that is optionally defined
# define VL_ATTR_WEAK ///< Attribute that function external that is optionally defined
#endif
#ifndef VL_CAPABILITY
# define VL_ACQUIRE(...) ///< Function requires a capability/lock (-fthread-safety)
@ -111,19 +111,19 @@
# define VL_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
#endif
#ifndef VL_LIKELY
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
# define VL_LIKELY(x) (!!(x)) ///< Return boolean expression that is more often true
# define VL_UNLIKELY(x) (!!(x)) ///< Return boolean expression that is more often false
#endif
/// Boolean expression never hit by users (branch coverage disabled)
# define VL_UNCOVERABLE(x) VL_UNLIKELY(x)
#ifndef VL_UNREACHABLE
# define VL_UNREACHABLE ///< Point that may never be reached
# define VL_UNREACHABLE ///< Statement that may never be reached (for coverage etc)
#endif
#ifndef VL_PREFETCH_RD
# define VL_PREFETCH_RD(p) ///< Prefetch pointed-to-data with read intent
# define VL_PREFETCH_RD(p) ///< Prefetch pointer argument with read intent
#endif
#ifndef VL_PREFETCH_RW
# define VL_PREFETCH_RW(p) ///< Prefetch pointed-to-data with read/write intent
# define VL_PREFETCH_RW(p) ///< Prefetch pointer argument with read/write intent
#endif
#if defined(VL_THREADED) && !defined(VL_CPPCHECK)
@ -136,9 +136,9 @@
# else
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
# endif
# define VL_THREAD_LOCAL thread_local ///< "thread_local" when supported
# define VL_THREAD_LOCAL thread_local // "thread_local" when supported
#else
# define VL_THREAD_LOCAL ///< "thread_local" when supported
# define VL_THREAD_LOCAL // "thread_local" when supported
#endif
#ifndef VL_NO_LEGACY
@ -147,27 +147,27 @@
# define VL_STATIC_OR_THREAD static // Deprecated
#endif
/// Comment tag that Function is pure (and thus also VL_MT_SAFE)
// Comment tag that Function is pure (and thus also VL_MT_SAFE)
#define VL_PURE
/// Comment tag that function is threadsafe when VL_THREADED
// Comment tag that function is threadsafe when VL_THREADED
#define VL_MT_SAFE
/// Comment tag that function is threadsafe when VL_THREADED, only
/// during normal operation (post-init)
// Comment tag that function is threadsafe when VL_THREADED, only
// during normal operation (post-init)
#define VL_MT_SAFE_POSTINIT
/// Clang threadsafe and uses given mutex
// Attribute that function is clang threadsafe and uses given mutex
#define VL_MT_SAFE_EXCLUDES(mutex) VL_EXCLUDES(mutex)
/// Comment tag that function is not threadsafe when VL_THREADED
// Comment tag that function is not threadsafe when VL_THREADED
#define VL_MT_UNSAFE
/// Comment tag that function is not threadsafe when VL_THREADED,
/// protected to make sure single-caller
// Comment tag that function is not threadsafe when VL_THREADED,
// protected to make sure single-caller
#define VL_MT_UNSAFE_ONE
#ifndef VL_NO_LEGACY
# define VL_ULL(c) (c##ULL) // Add appropriate suffix to 64-bit constant (deprecated)
#endif
/// Convert argument to IData
/// This is not necessarily the same as #UL, depending on what the IData typedef is.
// Convert argument to IData
// This is not necessarily the same as "#UL", depending on what the IData typedef is.
#define VL_UL(c) (static_cast<IData>(c##UL))
#if defined(VL_CPPCHECK) || defined(__clang_analyzer__) || __cplusplus < 201103L
@ -235,7 +235,7 @@
extern "C" {
void __gcov_flush(); // gcc sources gcc/gcov-io.h has the prototype
}
/// Flush internal code coverage data before e.g. std::abort()
// Flush internal code coverage data before e.g. std::abort()
# define VL_GCOV_FLUSH() \
__gcov_flush()
#else
@ -390,20 +390,20 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# define VL_WORDSIZE VL_IDATASIZE // Legacy define
#endif
/// Bytes this number of bits needs (1 bit=1 byte)
/// Return number of bytes argument-number of bits needs (1 bit=1 byte)
#define VL_BYTES_I(nbits) (((nbits) + (VL_BYTESIZE - 1)) / VL_BYTESIZE)
/// Words/EDatas this number of bits needs (1 bit=1 word)
/// Return Words/EDatas in argument-number of bits needs (1 bit=1 word)
#define VL_WORDS_I(nbits) (((nbits) + (VL_EDATASIZE - 1)) / VL_EDATASIZE)
/// Words/EDatas a quad requires
// Number of Words/EDatas a quad requires
#define VL_WQ_WORDS_E VL_WORDS_I(VL_QUADSIZE)
//=========================================================================
// Class definition helpers
/// Comment tag to indicate a base class, e.g. cannot label "class final"
// Comment tag to indicate a base class, e.g. cannot label "class final"
#define VL_NOT_FINAL
/// Declare a class as uncopyable; put after a private:
// Declare a class as uncopyable; put after a private:
#define VL_UNCOPYABLE(Type) \
Type(const Type& other) = delete; \
Type& operator=(const Type&) = delete
@ -421,14 +421,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#define VL_SIZEBITS_Q (VL_QUADSIZE - 1) ///< Bit mask for bits in a quad
#define VL_SIZEBITS_E (VL_EDATASIZE - 1) ///< Bit mask for bits in a quad
/// Mask for words with 1's where relevant bits are (0=all bits)
/// Return mask for words with 1's where relevant bits are (0=all bits)
#define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) ? ((1U << ((nbits) & VL_SIZEBITS_I)) - 1) : ~0)
/// Mask for quads with 1's where relevant bits are (0=all bits)
/// Return mask for quads with 1's where relevant bits are (0=all bits)
#define VL_MASK_Q(nbits) \
(((nbits) & VL_SIZEBITS_Q) ? ((1ULL << ((nbits) & VL_SIZEBITS_Q)) - 1ULL) : ~0ULL)
/// Mask for EData with 1's where relevant bits are (0=all bits)
/// Return mask for EData with 1's where relevant bits are (0=all bits)
#define VL_MASK_E(nbits) VL_MASK_I(nbits)
#define VL_EUL(n) VL_UL(n) ///< Make constant number EData sized
#define VL_EUL(n) VL_UL(n) // Make constant number EData sized
#define VL_BITWORD_I(bit) ((bit) / VL_IDATASIZE) ///< Word number for sv DPI vectors
#define VL_BITWORD_E(bit) ((bit) >> VL_EDATASIZE_LOG2) ///< Word number for a wide quantity
@ -451,9 +451,9 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
//=========================================================================
// Performance counters
/// The vluint64_t argument is loaded with a high-performance counter for profiling
/// or 0x0 if not implemented on this platform
#if defined(__i386__) || defined(__x86_64__)
// The vluint64_t argument is loaded with a high-performance counter for profiling
// or 0x0 if not implemented on this platform
#define VL_RDTSC(val) \
{ \
vluint32_t hi, lo; \
@ -477,8 +477,8 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# include "Windows.h"
# define VL_CPU_RELAX() YieldProcessor()
# elif defined(__i386__) || defined(__x86_64__) || defined(VL_CPPCHECK)
/// For more efficient busy waiting on SMT CPUs, let the processor know
/// we're just waiting so it can let another thread run
// For more efficient busy waiting on SMT CPUs, let the processor know
// we're just waiting so it can let another thread run
# define VL_CPU_RELAX() asm volatile("rep; nop" ::: "memory")
# elif defined(__ia64__)
# define VL_CPU_RELAX() asm volatile("hint @pause" ::: "memory")