mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 12:17:35 +00:00
1060 lines
45 KiB
C++
1060 lines
45 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
//*************************************************************************
|
|
//
|
|
// Code available from: https://verilator.org
|
|
//
|
|
// Copyright 2003-2024 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
|
|
//
|
|
//*************************************************************************
|
|
///
|
|
/// \file
|
|
/// \brief Verilated common header, include for all Verilated C files
|
|
///
|
|
/// This file is included automatically by Verilator at the top of all C++
|
|
/// files it generates. It contains standard macros and classes required
|
|
/// by the Verilated code.
|
|
///
|
|
/// User wrapper code may need to include this to get appropriate
|
|
/// structures, however they would generally just include the
|
|
/// Verilated-model's header instead (which then includes this).
|
|
///
|
|
/// Those macro/function/variable starting or ending in _ are internal,
|
|
/// however many of the other function/macros here are also internal.
|
|
///
|
|
//*************************************************************************
|
|
|
|
#ifndef VERILATOR_VERILATED_H_
|
|
#define VERILATOR_VERILATED_H_
|
|
#define VERILATOR_VERILATED_H_INTERNAL_
|
|
#ifdef VERILATOR_INTERNAL_
|
|
// This file contains definition of VerilationMutex that should
|
|
// only be used by verilated code. Verilator itself should use
|
|
// mutex from V3Mutex.h. Make sure this file isn't included in
|
|
// verilator code.
|
|
#error "verilated.h should only be included in verilated code"
|
|
#endif
|
|
|
|
// clang-format off
|
|
#include "verilatedos.h"
|
|
#include "verilated_config.h"
|
|
#if VM_SC
|
|
# include "verilated_sc.h" // Get SYSTEMC_VERSION and time declarations
|
|
#endif
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <cassert>
|
|
#include <cmath>
|
|
#include <cstdarg>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <deque>
|
|
#include <functional>
|
|
#include <limits>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <set>
|
|
#include <string>
|
|
#include <unordered_set>
|
|
#include <vector>
|
|
// <iostream> avoided to reduce compile time
|
|
#include <atomic>
|
|
#include <mutex>
|
|
#include <thread>
|
|
|
|
// Allow user to specify their own include file
|
|
#ifdef VL_VERILATED_INCLUDE
|
|
// cppcheck-suppress preprocessorErrorDirective
|
|
# include VL_VERILATED_INCLUDE
|
|
#endif
|
|
// clang-format on
|
|
|
|
using namespace std::literals; // "<std::string literal>"s; see SF.7 core guideline
|
|
|
|
//=============================================================================
|
|
// Switches
|
|
|
|
// clang-format off
|
|
#if VM_TRACE // Verilator tracing requested
|
|
# define WAVES 1 // Set backward compatibility flag
|
|
#endif
|
|
|
|
// Version check
|
|
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION < 20111121)
|
|
# warning "Verilator requires SystemC 2.3.* or newer."
|
|
#endif
|
|
// clang-format on
|
|
|
|
class VerilatedContext;
|
|
class VerilatedContextImp;
|
|
class VerilatedContextImpData;
|
|
class VerilatedCovContext;
|
|
class VerilatedEvalMsgQueue;
|
|
class VerilatedFst;
|
|
class VerilatedFstC;
|
|
class VerilatedFstSc;
|
|
class VerilatedScope;
|
|
class VerilatedScopeNameMap;
|
|
template <class, class>
|
|
class VerilatedTrace;
|
|
class VerilatedTraceBaseC;
|
|
class VerilatedTraceConfig;
|
|
class VerilatedVar;
|
|
class VerilatedVarNameMap;
|
|
class VerilatedVcd;
|
|
class VerilatedVcdC;
|
|
class VerilatedVcdSc;
|
|
|
|
//=========================================================================
|
|
// Basic types
|
|
|
|
// clang-format off
|
|
// P // Packed data of bit type (C/S/I/Q/W)
|
|
using CData = uint8_t; ///< Data representing 'bit' of 1-8 packed bits
|
|
using SData = uint16_t; ///< Data representing 'bit' of 9-16 packed bits
|
|
using IData = uint32_t; ///< Data representing 'bit' of 17-32 packed bits
|
|
using QData = uint64_t; ///< Data representing 'bit' of 33-64 packed bits
|
|
using EData = uint32_t; ///< Data representing one element of WData array
|
|
using WData = EData; ///< Data representing >64 packed bits (used as pointer)
|
|
// F = float; // No typedef needed; Verilator uses float
|
|
// D = double; // No typedef needed; Verilator uses double
|
|
// N = std::string; // No typedef needed; Verilator uses string
|
|
// clang-format on
|
|
|
|
using WDataInP = const WData*; ///< 'bit' of >64 packed bits as array input to a function
|
|
using WDataOutP = WData*; ///< 'bit' of >64 packed bits as array output from a function
|
|
|
|
enum VerilatedVarType : uint8_t {
|
|
VLVT_UNKNOWN = 0,
|
|
VLVT_PTR, // Pointer to something
|
|
VLVT_UINT8, // AKA CData
|
|
VLVT_UINT16, // AKA SData
|
|
VLVT_UINT32, // AKA IData
|
|
VLVT_UINT64, // AKA QData
|
|
VLVT_WDATA, // AKA WData
|
|
VLVT_STRING, // C++ string
|
|
VLVT_REAL // AKA double
|
|
};
|
|
|
|
enum VerilatedVarFlags {
|
|
VLVD_0 = 0, // None
|
|
VLVD_IN = 1, // == vpiInput
|
|
VLVD_OUT = 2, // == vpiOutput
|
|
VLVD_INOUT = 3, // == vpiInOut
|
|
VLVD_NODIR = 5, // == vpiNoDirection
|
|
VLVF_MASK_DIR = 7, // Bit mask for above directions
|
|
// Flags
|
|
VLVF_PUB_RD = (1 << 8), // Public readable
|
|
VLVF_PUB_RW = (1 << 9), // Public writable
|
|
VLVF_DPI_CLAY = (1 << 10) // DPI compatible C standard layout
|
|
};
|
|
|
|
// IEEE 1800-2023 Table 20-6
|
|
enum class VerilatedAssertType : uint8_t {
|
|
ASSERT_TYPE_CONCURRENT = (1 << 0),
|
|
ASSERT_TYPE_SIMPLE_IMMEDIATE = (1 << 1),
|
|
ASSERT_TYPE_OBSERVED_DEFERRED_IMMEDIATE = (1 << 2),
|
|
ASSERT_TYPE_FINAL_DEFERRED_IMMEDIATE = (1 << 3),
|
|
ASSERT_TYPE_EXPECT = (1 << 4),
|
|
ASSERT_TYPE_UNIQUE = (1 << 5),
|
|
ASSERT_TYPE_UNIQUE0 = (1 << 6),
|
|
ASSERT_TYPE_PRIORITY = (1 << 7),
|
|
};
|
|
|
|
// IEEE 1800-2023 Table 20-7
|
|
enum class VerilatedAssertDirectiveType : uint8_t {
|
|
DIRECTIVE_TYPE_ASSERT = (1 << 0),
|
|
DIRECTIVE_TYPE_COVER = (1 << 1),
|
|
DIRECTIVE_TYPE_ASSUME = (1 << 2),
|
|
};
|
|
using VerilatedAssertType_t = std::underlying_type<VerilatedAssertType>::type;
|
|
using VerilatedAssertDirectiveType_t = std::underlying_type<VerilatedAssertDirectiveType>::type;
|
|
|
|
//=============================================================================
|
|
// Utility functions
|
|
|
|
template <size_t N>
|
|
inline constexpr size_t roundUpToMultipleOf(size_t value) {
|
|
static_assert((N & (N - 1)) == 0, "'N' must be a power of 2");
|
|
return (value + N - 1) & ~(N - 1);
|
|
}
|
|
|
|
//=========================================================================
|
|
// Mutex and threading support
|
|
|
|
// Return current thread ID (or 0), not super fast, cache if needed
|
|
extern uint32_t VL_THREAD_ID() VL_MT_SAFE;
|
|
|
|
#ifndef VL_LOCK_SPINS
|
|
#define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before yielding
|
|
#endif
|
|
|
|
/// Mutex, wrapped to allow -fthread_safety checks
|
|
class VL_CAPABILITY("mutex") VerilatedMutex final {
|
|
private:
|
|
std::mutex m_mutex; // Mutex
|
|
|
|
public:
|
|
/// Construct mutex (without locking it)
|
|
VerilatedMutex() = default;
|
|
~VerilatedMutex() = default;
|
|
VL_UNCOPYABLE(VerilatedMutex);
|
|
const VerilatedMutex& operator!() const { return *this; } // For -fthread_safety
|
|
/// Acquire/lock mutex
|
|
void lock() VL_ACQUIRE() VL_MT_SAFE {
|
|
// Try to acquire the lock by spinning. If the wait is short,
|
|
// avoids a trap to the OS plus OS scheduler overhead.
|
|
if (VL_LIKELY(try_lock())) return; // Short circuit loop
|
|
for (int i = 0; i < VL_LOCK_SPINS; ++i) {
|
|
if (VL_LIKELY(try_lock())) return;
|
|
VL_CPU_RELAX();
|
|
}
|
|
// Spinning hasn't worked, pay the cost of blocking.
|
|
m_mutex.lock();
|
|
}
|
|
/// Release/unlock mutex
|
|
void unlock() VL_RELEASE() VL_MT_SAFE { m_mutex.unlock(); }
|
|
/// Try to acquire mutex. Returns true on success, and false on failure.
|
|
bool try_lock() VL_TRY_ACQUIRE(true) VL_MT_SAFE { return m_mutex.try_lock(); }
|
|
};
|
|
|
|
/// Lock guard for mutex (ala std::unique_lock), wrapped to allow -fthread_safety checks
|
|
class VL_SCOPED_CAPABILITY VerilatedLockGuard final {
|
|
VL_UNCOPYABLE(VerilatedLockGuard);
|
|
|
|
private:
|
|
VerilatedMutex& m_mutexr;
|
|
|
|
public:
|
|
/// Construct and hold given mutex lock until destruction or unlock()
|
|
explicit VerilatedLockGuard(VerilatedMutex& mutexr) VL_ACQUIRE(mutexr) VL_MT_SAFE
|
|
: m_mutexr(mutexr) { // Need () or GCC 4.8 false warning
|
|
mutexr.lock();
|
|
}
|
|
/// Destruct and unlock the mutex
|
|
~VerilatedLockGuard() VL_RELEASE() { m_mutexr.unlock(); }
|
|
};
|
|
|
|
// Internals: Remember the calling thread at construction time, and make
|
|
// sure later calls use same thread
|
|
|
|
class VerilatedAssertOneThread final {
|
|
// MEMBERS
|
|
#ifdef VL_DEBUG
|
|
uint32_t m_threadid; // Thread that is legal
|
|
public:
|
|
// CONSTRUCTORS
|
|
// The constructor establishes the thread id for all later calls.
|
|
// If necessary, a different class could be made that inits it otherwise.
|
|
VerilatedAssertOneThread()
|
|
: m_threadid{VL_THREAD_ID()} {}
|
|
~VerilatedAssertOneThread() { check(); }
|
|
// METHODS
|
|
// Check that the current thread ID is the same as the construction thread ID
|
|
void check() VL_MT_UNSAFE_ONE {
|
|
if (VL_UNCOVERABLE(m_threadid != VL_THREAD_ID())) {
|
|
if (m_threadid == 0) {
|
|
m_threadid = VL_THREAD_ID();
|
|
} else {
|
|
fatal_different(); // LCOV_EXCL_LINE
|
|
}
|
|
}
|
|
}
|
|
static void fatal_different() VL_MT_SAFE;
|
|
#else // !VL_DEBUG
|
|
public:
|
|
void check() {}
|
|
#endif
|
|
};
|
|
|
|
//=========================================================================
|
|
/// Base class of a Verilator generated (Verilated) model.
|
|
///
|
|
/// VerilatedModel is a base class of the user facing primary class generated
|
|
/// by Verilator.
|
|
|
|
class VerilatedModel VL_NOT_FINAL {
|
|
VL_UNCOPYABLE(VerilatedModel);
|
|
|
|
VerilatedContext& m_context; // The VerilatedContext this model is instantiated under
|
|
|
|
protected:
|
|
explicit VerilatedModel(VerilatedContext& context);
|
|
virtual ~VerilatedModel() = default;
|
|
|
|
public:
|
|
/// Returns the VerilatedContext this model is instantiated under
|
|
/// Used to get to e.g. simulation time via contextp()->time()
|
|
VerilatedContext* contextp() const VL_MT_SAFE { return &m_context; }
|
|
/// Returns the hierarchical name of this module instance.
|
|
virtual const char* hierName() const = 0;
|
|
/// Returns the name of this model (the name of the generated model class).
|
|
virtual const char* modelName() const = 0;
|
|
/// Returns the thread level parallelism, this model was Verilated with. Always 1 or higher.
|
|
virtual unsigned threads() const = 0;
|
|
|
|
private:
|
|
// The following are for use by Verilator internals only
|
|
template <class, class>
|
|
friend class VerilatedTrace;
|
|
// Run-time trace configuration requested by this model
|
|
virtual std::unique_ptr<VerilatedTraceConfig> traceConfig() const;
|
|
};
|
|
|
|
//=========================================================================
|
|
/// Base class for all Verilated module classes.
|
|
|
|
class VerilatedModule VL_NOT_FINAL {
|
|
VL_UNCOPYABLE(VerilatedModule);
|
|
|
|
private:
|
|
const char* m_namep; // Module name
|
|
public:
|
|
explicit VerilatedModule(const char* namep); // Create module with given hierarchy name
|
|
~VerilatedModule();
|
|
const char* name() const VL_MT_SAFE_POSTINIT { return m_namep; } ///< Return name of module
|
|
};
|
|
|
|
//=========================================================================
|
|
// Functions overridable by user defines
|
|
// (Internals however must use VL_PRINTF_MT, which calls these.)
|
|
|
|
// clang-format off
|
|
#ifndef VL_PRINTF
|
|
# define VL_PRINTF printf ///< Print ala printf, called from main thread; redefine if desired
|
|
#endif
|
|
#ifndef VL_VPRINTF
|
|
# define VL_VPRINTF vprintf ///< Print ala vprintf, called from main thread; redefine if desired
|
|
#endif
|
|
// clang-format on
|
|
|
|
//===========================================================================
|
|
// Internal: Base class to allow virtual destruction
|
|
|
|
class VerilatedVirtualBase VL_NOT_FINAL {
|
|
public:
|
|
VerilatedVirtualBase() = default;
|
|
virtual ~VerilatedVirtualBase() = default;
|
|
};
|
|
|
|
//===========================================================================
|
|
/// Verilator simulation context
|
|
///
|
|
/// The VerilatedContext contains the information common across all models
|
|
/// that are interconnected, for example this contains the simulation time
|
|
/// and if $finish was executed.
|
|
///
|
|
/// VerilatedContexts maybe created by the user wrapper code and passed
|
|
/// when a model is created. If this is not done, then Verilator will use
|
|
/// the Verilated::defaultContextp()'s global context.
|
|
|
|
class VerilatedContext VL_NOT_FINAL {
|
|
friend class VerilatedContextImp;
|
|
|
|
private:
|
|
// MEMBERS
|
|
// Numer of assertion directive type members. Then each of them will represented as 1-bit in a
|
|
// mask.
|
|
static constexpr size_t ASSERT_DIRECTIVE_TYPE_MASK_WIDTH = 3;
|
|
// Specifies how many groups of directive type bit groups there are based on a number of
|
|
// assertion types.
|
|
// Note: we add one bit to store information whether Verilator's internal
|
|
// directive types are enabled, for example `violation if`s.
|
|
static constexpr size_t ASSERT_ON_WIDTH
|
|
= ASSERT_DIRECTIVE_TYPE_MASK_WIDTH * std::numeric_limits<VerilatedAssertType_t>::digits
|
|
+ 1;
|
|
|
|
protected:
|
|
// TYPES
|
|
using traceBaseModelCb_t
|
|
= std::function<void(VerilatedTraceBaseC*, int, int)>; // Type of traceBaseModel callbacks
|
|
|
|
// MEMBERS
|
|
// Slow path variables
|
|
mutable VerilatedMutex m_mutex; // Mutex for most s_s/s_ns members
|
|
|
|
struct Serialized final { // All these members serialized/deserialized
|
|
// No std::strings or pointers or will serialize badly!
|
|
// Fast path
|
|
uint64_t m_time = 0; // Current $time (unscaled), 0=at zero, or legacy
|
|
std::atomic<uint32_t> m_assertOn{
|
|
std::numeric_limits<uint32_t>::max()}; // Enabled assertions,
|
|
// for each VerilatedAssertType we store
|
|
// 3-bits, one for each directive type. Last
|
|
// bit guards internal directive types.
|
|
bool m_calcUnusedSigs = false; // Waves file on, need all signals calculated
|
|
bool m_fatalOnError = true; // Fatal on $stop/non-fatal error
|
|
bool m_fatalOnVpiError = true; // Fatal on vpi error/unsupported
|
|
bool m_gotError = false; // A $finish statement executed
|
|
bool m_gotFinish = false; // A $finish or $stop statement executed
|
|
bool m_quiet = false; // Quiet, no summary report
|
|
// Slow path
|
|
int8_t m_timeunit; // Time unit as 0..15
|
|
int8_t m_timeprecision; // Time precision as 0..15
|
|
int m_errorCount = 0; // Number of errors
|
|
int m_errorLimit = 1; // Stop on error number
|
|
int m_randReset = 0; // Random reset: 0=all 0s, 1=all 1s, 2=random
|
|
int m_randSeed = 0; // Random seed: 0=random
|
|
enum { UNITS_NONE = 99 }; // Default based on precision
|
|
int m_timeFormatUnits = UNITS_NONE; // $timeformat units
|
|
int m_timeFormatPrecision = 0; // $timeformat number of decimal places
|
|
int m_timeFormatWidth = 20; // $timeformat character width
|
|
// CONSTRUCTORS
|
|
Serialized();
|
|
~Serialized() = default;
|
|
} m_s;
|
|
|
|
mutable VerilatedMutex m_timeDumpMutex; // Protect misc slow strings
|
|
std::string m_timeFormatSuffix VL_GUARDED_BY(m_timeDumpMutex); // $timeformat printf format
|
|
std::string m_dumpfile VL_GUARDED_BY(m_timeDumpMutex); // $dumpfile setting
|
|
|
|
struct NonSerialized final { // Non-serialized information
|
|
// These are reloaded from on command-line settings, so do not need to persist
|
|
// Fast path
|
|
uint64_t m_profExecStart = 1; // +prof+exec+start time
|
|
uint32_t m_profExecWindow = 2; // +prof+exec+window size
|
|
// Slow path
|
|
std::string m_coverageFilename; // +coverage+file filename
|
|
std::string m_profExecFilename; // +prof+exec+file filename
|
|
std::string m_profVltFilename; // +prof+vlt filename
|
|
std::string m_solverProgram; // SMT solver program
|
|
VlOs::DeltaCpuTime m_cpuTimeStart{false}; // CPU time, starts when create first model
|
|
VlOs::DeltaWallTime m_wallTimeStart{false}; // Wall time, starts when create first model
|
|
std::vector<traceBaseModelCb_t> m_traceBaseModelCbs; // Callbacks to traceRegisterModel
|
|
} m_ns;
|
|
|
|
mutable VerilatedMutex m_argMutex; // Protect m_argVec, m_argVecLoaded
|
|
// no need to be save-restored (serialized) the
|
|
// assumption is that the restore is allowed to pass different arguments
|
|
struct NonSerializedCommandArgs final {
|
|
// Medium speed
|
|
std::vector<std::string> m_argVec; // Argument list
|
|
bool m_argVecLoaded = false; // Ever loaded argument list
|
|
} m_args VL_GUARDED_BY(m_argMutex);
|
|
|
|
// Implementation details
|
|
const std::unique_ptr<VerilatedContextImpData> m_impdatap;
|
|
// Number of threads to use for simulation (size of m_threadPool + 1 for main thread)
|
|
unsigned m_threads = std::thread::hardware_concurrency();
|
|
// Number of threads in added models
|
|
unsigned m_threadsInModels = 0;
|
|
// The thread pool shared by all models added to this context
|
|
std::unique_ptr<VerilatedVirtualBase> m_threadPool;
|
|
// The execution profiler shared by all models added to this context
|
|
std::unique_ptr<VerilatedVirtualBase> m_executionProfiler;
|
|
// Coverage access
|
|
std::unique_ptr<VerilatedVirtualBase> m_coveragep; // Pointer for coveragep()
|
|
|
|
// File I/O
|
|
// Not serialized
|
|
mutable VerilatedMutex m_fdMutex; // Protect m_fdps, m_fdFree
|
|
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); // File descriptors
|
|
// List of free descriptors (SLOW - FOPEN/CLOSE only)
|
|
std::vector<IData> m_fdFree VL_GUARDED_BY(m_fdMutex);
|
|
// List of free descriptors in the MCT region [4, 32)
|
|
std::vector<IData> m_fdFreeMct VL_GUARDED_BY(m_fdMutex);
|
|
|
|
// Magic to check for bad construction
|
|
static constexpr uint64_t MAGIC = 0xC35F9A6E5298EE6EULL; // SHA256 "VerilatedContext"
|
|
uint64_t m_magic = MAGIC;
|
|
|
|
private:
|
|
// CONSTRUCTORS
|
|
VL_UNCOPYABLE(VerilatedContext);
|
|
|
|
public:
|
|
/// Construct context. Also sets Verilated::threadContextp to the created context.
|
|
VerilatedContext();
|
|
~VerilatedContext();
|
|
|
|
// METHODS - User called
|
|
|
|
/// Return if assertions enabled
|
|
bool assertOn() const VL_MT_SAFE;
|
|
/// Enable all assertion types
|
|
void assertOn(bool flag) VL_MT_SAFE;
|
|
/// Get enabled status for given assertion types
|
|
bool assertOnGet(VerilatedAssertType_t type,
|
|
VerilatedAssertDirectiveType_t directive) const VL_MT_SAFE;
|
|
/// Set enabled status for given assertion types
|
|
void assertOnSet(VerilatedAssertType_t types,
|
|
VerilatedAssertDirectiveType_t directives) VL_MT_SAFE;
|
|
/// Clear enabled status for given assertion types
|
|
void assertOnClear(VerilatedAssertType_t types,
|
|
VerilatedAssertDirectiveType_t directives) VL_MT_SAFE;
|
|
/// Return if calculating of unused signals (for traces)
|
|
bool calcUnusedSigs() const VL_MT_SAFE { return m_s.m_calcUnusedSigs; }
|
|
/// Enable calculation of unused signals (for traces)
|
|
void calcUnusedSigs(bool flag) VL_MT_SAFE;
|
|
/// Record command-line arguments, for retrieval by $test$plusargs/$value$plusargs,
|
|
/// and for parsing +verilator+ run-time arguments.
|
|
/// This should be called before the first model is created.
|
|
void commandArgs(int argc, const char** argv) VL_MT_SAFE_EXCLUDES(m_argMutex);
|
|
void commandArgs(int argc, char** argv) VL_MT_SAFE {
|
|
commandArgs(argc, const_cast<const char**>(argv));
|
|
}
|
|
/// Add a command-line argument to existing arguments
|
|
void commandArgsAdd(int argc, const char** argv) VL_MT_SAFE_EXCLUDES(m_argMutex);
|
|
/// Match plusargs with a given prefix. Returns static char* valid only for a single call
|
|
const char* commandArgsPlusMatch(const char* prefixp) VL_MT_SAFE_EXCLUDES(m_argMutex);
|
|
/// Return VerilatedCovContext, allocate if needed
|
|
/// Note if get unresolved reference then likely forgot to link verilated_cov.cpp
|
|
VerilatedCovContext* coveragep() VL_MT_SAFE;
|
|
/// Return debug level
|
|
static inline int debug() VL_MT_SAFE; /// Set debug level
|
|
/// Debug is currently global, but for forward compatibility have a per-context method
|
|
static inline void debug(int val) VL_MT_SAFE;
|
|
/// Return current number of errors/assertions
|
|
int errorCount() const VL_MT_SAFE { return m_s.m_errorCount; }
|
|
/// Set current number of errors/assertions
|
|
void errorCount(int val) VL_MT_SAFE;
|
|
/// Increment current number of errors/assertions
|
|
void errorCountInc() VL_MT_SAFE;
|
|
/// Return number of errors/assertions before stop
|
|
int errorLimit() const VL_MT_SAFE { return m_s.m_errorLimit; }
|
|
/// Set number of errors/assertions before stop
|
|
void errorLimit(int val) VL_MT_SAFE;
|
|
/// Return if to throw fatal error on $stop/non-fatal
|
|
bool fatalOnError() const VL_MT_SAFE { return m_s.m_fatalOnError; }
|
|
/// Set to throw fatal error on $stop/non-fatal error
|
|
void fatalOnError(bool flag) VL_MT_SAFE;
|
|
/// Return if to throw fatal error on VPI errors
|
|
bool fatalOnVpiError() const VL_MT_SAFE { return m_s.m_fatalOnVpiError; }
|
|
/// Set to throw fatal error on VPI errors
|
|
void fatalOnVpiError(bool flag) VL_MT_SAFE;
|
|
/// Return if got a $stop or non-fatal error
|
|
bool gotError() const VL_MT_SAFE { return m_s.m_gotError; }
|
|
/// Set if got a $stop or non-fatal error
|
|
void gotError(bool flag) VL_MT_SAFE;
|
|
/// Return if got a $finish or $stop/error
|
|
bool gotFinish() const VL_MT_SAFE { return m_s.m_gotFinish; }
|
|
/// Set if got a $finish or $stop/error
|
|
void gotFinish(bool flag) VL_MT_SAFE;
|
|
/// Return if quiet enabled
|
|
bool quiet() const VL_MT_SAFE { return m_s.m_quiet; }
|
|
/// Enable quiet (also prevents need for OS calls to get CPU time)
|
|
void quiet(bool flag) VL_MT_SAFE;
|
|
/// Return randReset value
|
|
int randReset() VL_MT_SAFE { return m_s.m_randReset; }
|
|
/// Select initial value of otherwise uninitialized signals.
|
|
/// 0 = Set to zeros
|
|
/// 1 = Set all bits to one
|
|
/// 2 = Randomize all bits
|
|
void randReset(int val) VL_MT_SAFE;
|
|
/// Set default random seed, 0 = seed it automatically
|
|
int randSeed() const VL_MT_SAFE { return m_s.m_randSeed; }
|
|
/// Return default random seed
|
|
void randSeed(int val) VL_MT_SAFE;
|
|
|
|
/// Return statistic: CPU time delta from model created until now
|
|
double statCpuTimeSinceStart() const VL_MT_SAFE_EXCLUDES(m_mutex);
|
|
/// Return statistic: Wall time delta from model created until now
|
|
double statWallTimeSinceStart() const VL_MT_SAFE_EXCLUDES(m_mutex);
|
|
/// Print statistics summary (if not quiet)
|
|
void statsPrintSummary() VL_MT_UNSAFE;
|
|
|
|
// Time handling
|
|
/// Returns current simulation time in units of timeprecision().
|
|
///
|
|
/// How Verilator runtime gets the current simulation time:
|
|
///
|
|
/// * If using SystemC, time comes from the SystemC kernel-defined
|
|
/// sc_time_stamp64(). User's wrapper must not call
|
|
/// SimulationContext::time(value) nor timeInc(value).
|
|
///
|
|
/// * Else, if SimulationContext::time(value) or
|
|
/// SimulationContext::timeInc(value) is ever called with non-zero,
|
|
/// then time will come via the context. This allows multiple contexts
|
|
/// to exist and have different simulation times. This must not be used
|
|
/// with SystemC. Note Verilated::time(value) and
|
|
/// Verilated::timeInc(value) call into SimulationContext::time and
|
|
/// timeInc, operating on the thread's context.
|
|
///
|
|
/// * Else, if VL_TIME_STAMP64 is defined, time comes from the legacy
|
|
/// 'uint64_t vl_time_stamp64()' which must a function be defined by
|
|
/// the user's wrapper.
|
|
///
|
|
/// * Else, time comes from the legacy 'double sc_time_stamp()' which
|
|
/// must be a function defined by the user's wrapper.
|
|
inline uint64_t time() const VL_MT_SAFE;
|
|
/// Set current simulation time. See time() for side effect details
|
|
void time(uint64_t value) VL_MT_SAFE { m_s.m_time = value; }
|
|
/// Advance current simulation time. See time() for side effect details
|
|
void timeInc(uint64_t add) VL_MT_UNSAFE { m_s.m_time += add; }
|
|
/// Return time units as power-of-ten
|
|
int timeunit() const VL_MT_SAFE { return -m_s.m_timeunit; }
|
|
/// Set time units as power-of-ten
|
|
void timeunit(int value) VL_MT_SAFE;
|
|
/// Return time units as IEEE-standard text
|
|
const char* timeunitString() const VL_MT_SAFE;
|
|
/// Get time precision as power-of-ten
|
|
int timeprecision() const VL_MT_SAFE { return -m_s.m_timeprecision; }
|
|
/// Return time precision as power-of-ten
|
|
inline void timeprecision(int value) VL_MT_SAFE;
|
|
/// Get time precision as IEEE-standard text
|
|
const char* timeprecisionString() const VL_MT_SAFE;
|
|
|
|
/// Get number of threads used for simulation (including the main thread)
|
|
unsigned threads() const { return m_threads; }
|
|
/// Get number of threads in added models (for statistical use only)
|
|
unsigned threadsInModels() const { return m_threadsInModels; }
|
|
/// Set number of threads used for simulation (including the main thread)
|
|
/// Can only be called before the thread pool is created (before first model is added).
|
|
void threads(unsigned n);
|
|
|
|
/// Trace signals in models within the context; called by application code
|
|
void trace(VerilatedTraceBaseC* tfp, int levels, int options = 0);
|
|
/// Allow traces to at some point be enabled (disables some optimizations)
|
|
void traceEverOn(bool flag) VL_MT_SAFE {
|
|
if (flag) calcUnusedSigs(true);
|
|
}
|
|
|
|
/// For debugging, print much of the Verilator internal state.
|
|
/// The output of this function may change in future
|
|
/// releases - contact the authors before production use.
|
|
void internalsDump() const VL_MT_SAFE;
|
|
|
|
/// For debugging, print text list of all scope names with
|
|
/// dpiImport/Export context. This function may change in future
|
|
/// releases - contact the authors before production use.
|
|
void scopesDump() const VL_MT_SAFE;
|
|
|
|
// METHODS - public but for internal use only
|
|
|
|
// Internal: access to implementation class
|
|
VerilatedContextImp* impp() VL_MT_SAFE { return reinterpret_cast<VerilatedContextImp*>(this); }
|
|
const VerilatedContextImp* impp() const VL_MT_SAFE {
|
|
return reinterpret_cast<const VerilatedContextImp*>(this);
|
|
}
|
|
|
|
// Internal: Model and thread setup
|
|
void addModel(VerilatedModel*);
|
|
VerilatedVirtualBase* threadPoolp();
|
|
void prepareClone();
|
|
VerilatedVirtualBase* threadPoolpOnClone();
|
|
VerilatedVirtualBase*
|
|
enableExecutionProfiler(VerilatedVirtualBase* (*construct)(VerilatedContext&));
|
|
|
|
// Internal: coverage
|
|
std::string coverageFilename() const VL_MT_SAFE;
|
|
void coverageFilename(const std::string& flag) VL_MT_SAFE;
|
|
|
|
// Internal: $dumpfile
|
|
std::string dumpfile() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
|
|
void dumpfile(const std::string& flag) VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
|
|
std::string dumpfileCheck() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
|
|
|
|
// Internal: --prof-exec related settings
|
|
uint64_t profExecStart() const VL_MT_SAFE { return m_ns.m_profExecStart; }
|
|
void profExecStart(uint64_t flag) VL_MT_SAFE;
|
|
uint32_t profExecWindow() const VL_MT_SAFE { return m_ns.m_profExecWindow; }
|
|
void profExecWindow(uint64_t flag) VL_MT_SAFE;
|
|
std::string profExecFilename() const VL_MT_SAFE;
|
|
void profExecFilename(const std::string& flag) VL_MT_SAFE;
|
|
std::string profVltFilename() const VL_MT_SAFE;
|
|
void profVltFilename(const std::string& flag) VL_MT_SAFE;
|
|
|
|
// Internal: SMT solver program
|
|
std::string solverProgram() const VL_MT_SAFE;
|
|
void solverProgram(const std::string& flag) VL_MT_SAFE;
|
|
|
|
// Internal: Find scope
|
|
const VerilatedScope* scopeFind(const char* namep) const VL_MT_SAFE;
|
|
const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE;
|
|
|
|
// Internal: Serialization setup
|
|
static constexpr size_t serialized1Size() VL_PURE { return sizeof(m_s); }
|
|
void* serialized1Ptr() VL_MT_UNSAFE { return &m_s; }
|
|
|
|
// Internal: trace registration
|
|
void traceBaseModelCbAdd(traceBaseModelCb_t cb) VL_MT_SAFE;
|
|
|
|
// Internal: Check magic number
|
|
static void checkMagic(const VerilatedContext* contextp);
|
|
void selfTestClearMagic() { m_magic = 0x2; }
|
|
};
|
|
|
|
//===========================================================================
|
|
// 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
|
|
// MEMBERS
|
|
// Keep first so is at zero offset for fastest code
|
|
VerilatedContext* const _vm_contextp__; // Context for current model
|
|
VerilatedEvalMsgQueue* __Vm_evalMsgQp;
|
|
explicit VerilatedSyms(VerilatedContext* contextp); // Pass null for default context
|
|
~VerilatedSyms();
|
|
VL_UNCOPYABLE(VerilatedSyms);
|
|
};
|
|
|
|
//===========================================================================
|
|
// Verilator scope information class
|
|
// Used for internal VPI implementation, and introspection into scopes
|
|
|
|
class VerilatedScope final {
|
|
public:
|
|
enum Type : uint8_t {
|
|
SCOPE_MODULE,
|
|
SCOPE_OTHER,
|
|
SCOPE_PACKAGE
|
|
}; // Type of a scope, currently only module and package are interesting
|
|
private:
|
|
// Fastpath:
|
|
VerilatedSyms* m_symsp = nullptr; // Symbol table
|
|
void** m_callbacksp = nullptr; // Callback table pointer (Fastpath)
|
|
int m_funcnumMax = 0; // Maximum function number stored (Fastpath)
|
|
// 4 bytes padding (on -m64), for rent.
|
|
VerilatedVarNameMap* m_varsp = nullptr; // Variable map
|
|
const char* m_namep = nullptr; // Scope name (Slowpath)
|
|
const char* m_identifierp = nullptr; // Identifier of scope (with escapes removed)
|
|
int8_t m_timeunit = 0; // Timeunit in negative power-of-10
|
|
Type m_type = SCOPE_OTHER; // Type of the scope
|
|
|
|
public: // But internals only - called from VerilatedModule's
|
|
VerilatedScope() = default;
|
|
~VerilatedScope();
|
|
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
|
|
const char* identifier, int8_t timeunit, const Type& type) VL_MT_UNSAFE;
|
|
void exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE;
|
|
void varInsert(int finalize, const char* namep, void* datap, bool isParam,
|
|
VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE;
|
|
// ACCESSORS
|
|
const char* name() const VL_MT_SAFE_POSTINIT { return m_namep; }
|
|
const char* identifier() const VL_MT_SAFE_POSTINIT { return m_identifierp; }
|
|
int8_t timeunit() const VL_MT_SAFE_POSTINIT { return m_timeunit; }
|
|
VerilatedSyms* symsp() const VL_MT_SAFE_POSTINIT { return m_symsp; }
|
|
VerilatedVar* varFind(const char* namep) const VL_MT_SAFE_POSTINIT;
|
|
VerilatedVarNameMap* varsp() const VL_MT_SAFE_POSTINIT { return m_varsp; }
|
|
void scopeDump() const;
|
|
void* exportFindError(int funcnum) const VL_MT_SAFE;
|
|
static void* exportFindNullError(int funcnum) VL_MT_SAFE;
|
|
static void* exportFind(const VerilatedScope* scopep, int funcnum) VL_MT_SAFE {
|
|
if (VL_UNLIKELY(!scopep)) return exportFindNullError(funcnum);
|
|
if (VL_LIKELY(funcnum < scopep->m_funcnumMax)) {
|
|
// m_callbacksp must be declared, as Max'es are > 0
|
|
return scopep->m_callbacksp[funcnum];
|
|
} else { // LCOV_EXCL_LINE
|
|
return scopep->exportFindError(funcnum); // LCOV_EXCL_LINE
|
|
}
|
|
}
|
|
Type type() const { return m_type; }
|
|
};
|
|
|
|
class VerilatedHierarchy final {
|
|
public:
|
|
static void add(VerilatedScope* fromp, VerilatedScope* top);
|
|
static void remove(VerilatedScope* fromp, VerilatedScope* top);
|
|
};
|
|
|
|
//===========================================================================
|
|
/// Verilator global static information class
|
|
|
|
class Verilated final {
|
|
// MEMBERS
|
|
|
|
// Internal Note: There should be no Serialized state in Verilated::,
|
|
// instead serialized state should all be in VerilatedContext:: as by
|
|
// definition it needs to vary per-simulation
|
|
|
|
// Internal note: Globals may multi-construct, see verilated.cpp top.
|
|
|
|
// Debug is reloaded from on command-line settings, so do not need to persist
|
|
static int s_debug; // See accessors... only when VL_DEBUG set
|
|
|
|
static VerilatedContext* s_lastContextp; // Last context constructed/attached
|
|
|
|
// Not covered by mutex, as per-thread
|
|
static thread_local struct ThreadLocal {
|
|
// No non-POD objects here due to this:
|
|
// Internal note: Globals may multi-construct, see verilated.cpp top.
|
|
|
|
// Fast path
|
|
VerilatedContext* t_contextp = nullptr; // Thread's context
|
|
uint32_t t_mtaskId = 0; // mtask# executing on this thread
|
|
// Messages maybe pending on thread, needs end-of-eval calls
|
|
uint32_t t_endOfEvalReqd = 0;
|
|
const VerilatedScope* t_dpiScopep = nullptr; // DPI context scope
|
|
const char* t_dpiFilename = nullptr; // DPI context filename
|
|
int t_dpiLineno = 0; // DPI context line number
|
|
|
|
ThreadLocal() = default;
|
|
~ThreadLocal() = default;
|
|
} t_s;
|
|
|
|
friend struct VerilatedInitializer;
|
|
|
|
// CONSTRUCTORS
|
|
VL_UNCOPYABLE(Verilated);
|
|
|
|
public:
|
|
// METHODS - User called
|
|
|
|
#ifdef VL_DEBUG
|
|
/// Return debug level
|
|
/// When multithreaded this may not immediately react to another thread
|
|
/// changing the level (no mutex)
|
|
static int debug() VL_MT_SAFE { return s_debug; }
|
|
#else
|
|
/// Return constant 0 debug level, so C++'s optimizer rips up
|
|
static constexpr int debug() VL_PURE { return 0; }
|
|
#endif
|
|
/// Enable debug of internal verilated code
|
|
static void debug(int level) VL_MT_SAFE;
|
|
|
|
/// Set the last VerilatedContext accessed
|
|
/// Generally threadContextp(value) should be called instead
|
|
static void lastContextp(VerilatedContext* contextp) VL_MT_SAFE { s_lastContextp = contextp; }
|
|
/// Return the last VerilatedContext accessed
|
|
/// Generally threadContextp() should be called instead
|
|
static VerilatedContext* lastContextp() VL_MT_SAFE {
|
|
if (!s_lastContextp) lastContextp(defaultContextp());
|
|
return s_lastContextp;
|
|
}
|
|
/// Set the VerilatedContext used by the current thread
|
|
|
|
/// If using multiple contexts, and threads are created by the user's
|
|
/// wrapper (not Verilator itself) then this must be called to set the
|
|
/// context that applies to each thread
|
|
static void threadContextp(VerilatedContext* contextp) VL_MT_SAFE {
|
|
t_s.t_contextp = contextp;
|
|
lastContextp(contextp);
|
|
}
|
|
/// Return the VerilatedContext for the current thread
|
|
static VerilatedContext* threadContextp() VL_MT_SAFE {
|
|
if (VL_UNLIKELY(!t_s.t_contextp)) t_s.t_contextp = lastContextp();
|
|
return t_s.t_contextp;
|
|
}
|
|
/// Return the global VerilatedContext, used if none created by user
|
|
static VerilatedContext* defaultContextp() VL_MT_SAFE {
|
|
static VerilatedContext s_s;
|
|
return &s_s;
|
|
}
|
|
|
|
#ifndef VL_NO_LEGACY
|
|
/// Return VerilatedContext::assertOn() using current thread's VerilatedContext
|
|
static bool assertOn() VL_MT_SAFE { return Verilated::threadContextp()->assertOn(); }
|
|
/// Call VerilatedContext::assertOn using current thread's VerilatedContext
|
|
static void assertOn(bool flag) VL_MT_SAFE { Verilated::threadContextp()->assertOn(flag); }
|
|
/// Return VerilatedContext::calcUnusedSigs using current thread's VerilatedContext
|
|
static bool calcUnusedSigs() VL_MT_SAFE {
|
|
return Verilated::threadContextp()->calcUnusedSigs();
|
|
}
|
|
/// Call VerilatedContext::calcUnusedSigs using current thread's VerilatedContext
|
|
static void calcUnusedSigs(bool flag) VL_MT_SAFE {
|
|
Verilated::threadContextp()->calcUnusedSigs(flag);
|
|
}
|
|
/// Call VerilatedContext::commandArgs using current thread's VerilatedContext
|
|
static void commandArgs(int argc, const char** argv) VL_MT_SAFE {
|
|
Verilated::threadContextp()->commandArgs(argc, argv);
|
|
}
|
|
static void commandArgs(int argc, char** argv) VL_MT_SAFE {
|
|
commandArgs(argc, const_cast<const char**>(argv));
|
|
}
|
|
/// Call VerilatedContext::commandArgsAdd using current thread's VerilatedContext
|
|
static void commandArgsAdd(int argc, const char** argv) {
|
|
Verilated::threadContextp()->commandArgsAdd(argc, argv);
|
|
}
|
|
/// Return VerilatedContext::commandArgsPlusMatch using current thread's VerilatedContext
|
|
static const char* commandArgsPlusMatch(const char* prefixp) VL_MT_SAFE {
|
|
return Verilated::threadContextp()->commandArgsPlusMatch(prefixp);
|
|
}
|
|
/// Return VerilatedContext::errorLimit using current thread's VerilatedContext
|
|
static int errorLimit() VL_MT_SAFE { return Verilated::threadContextp()->errorLimit(); }
|
|
/// Call VerilatedContext::errorLimit using current thread's VerilatedContext
|
|
static void errorLimit(int val) VL_MT_SAFE { Verilated::threadContextp()->errorLimit(val); }
|
|
/// Return VerilatedContext::fatalOnError using current thread's VerilatedContext
|
|
static bool fatalOnError() VL_MT_SAFE { return Verilated::threadContextp()->fatalOnError(); }
|
|
/// Call VerilatedContext::fatalOnError using current thread's VerilatedContext
|
|
static void fatalOnError(bool flag) VL_MT_SAFE {
|
|
Verilated::threadContextp()->fatalOnError(flag);
|
|
}
|
|
/// Return VerilatedContext::fatalOnVpiError using current thread's VerilatedContext
|
|
static bool fatalOnVpiError() VL_MT_SAFE {
|
|
return Verilated::threadContextp()->fatalOnVpiError();
|
|
}
|
|
/// Call VerilatedContext::fatalOnVpiError using current thread's VerilatedContext
|
|
static void fatalOnVpiError(bool flag) VL_MT_SAFE {
|
|
Verilated::threadContextp()->fatalOnVpiError(flag);
|
|
}
|
|
/// Return VerilatedContext::gotError using current thread's VerilatedContext
|
|
static bool gotError() VL_MT_SAFE { return Verilated::threadContextp()->gotError(); }
|
|
/// Call VerilatedContext::gotError using current thread's VerilatedContext
|
|
static void gotError(bool flag) VL_MT_SAFE { Verilated::threadContextp()->gotError(flag); }
|
|
/// Return VerilatedContext::gotFinish using current thread's VerilatedContext
|
|
static bool gotFinish() VL_MT_SAFE { return Verilated::threadContextp()->gotFinish(); }
|
|
/// Call VerilatedContext::gotFinish using current thread's VerilatedContext
|
|
static void gotFinish(bool flag) VL_MT_SAFE { Verilated::threadContextp()->gotFinish(flag); }
|
|
/// Return VerilatedContext::randReset using current thread's VerilatedContext
|
|
static int randReset() VL_MT_SAFE { return Verilated::threadContextp()->randReset(); }
|
|
/// Call VerilatedContext::randReset using current thread's VerilatedContext
|
|
static void randReset(int val) VL_MT_SAFE { Verilated::threadContextp()->randReset(val); }
|
|
/// Return VerilatedContext::randSeed using current thread's VerilatedContext
|
|
static int randSeed() VL_MT_SAFE { return Verilated::threadContextp()->randSeed(); }
|
|
/// Call VerilatedContext::randSeed using current thread's VerilatedContext
|
|
static void randSeed(int val) VL_MT_SAFE { Verilated::threadContextp()->randSeed(val); }
|
|
/// Return VerilatedContext::time using current thread's VerilatedContext
|
|
static uint64_t time() VL_MT_SAFE { return Verilated::threadContextp()->time(); }
|
|
/// Call VerilatedContext::time using current thread's VerilatedContext
|
|
static void time(uint64_t val) VL_MT_SAFE { Verilated::threadContextp()->time(val); }
|
|
/// Call VerilatedContext::timeInc using current thread's VerilatedContext
|
|
static void timeInc(uint64_t add) VL_MT_UNSAFE { Verilated::threadContextp()->timeInc(add); }
|
|
// Deprecated
|
|
static int timeunit() VL_MT_SAFE { return Verilated::threadContextp()->timeunit(); }
|
|
static int timeprecision() VL_MT_SAFE { return Verilated::threadContextp()->timeprecision(); }
|
|
/// Call VerilatedContext::tracesEverOn using current thread's VerilatedContext
|
|
static void traceEverOn(bool flag) VL_MT_SAFE {
|
|
Verilated::threadContextp()->traceEverOn(flag);
|
|
}
|
|
#endif
|
|
|
|
/// Callback typedef for addFlushCb, addExitCb
|
|
using VoidPCb = void (*)(void*);
|
|
/// Add callback to run on global flush
|
|
static void addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE;
|
|
/// Remove callback to run on global flush
|
|
static void removeFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE;
|
|
/// Run flush callbacks registered with addFlushCb
|
|
static void runFlushCallbacks() VL_MT_SAFE;
|
|
#ifndef VL_NO_LEGACY
|
|
static void flushCall() VL_MT_SAFE { runFlushCallbacks(); } // Deprecated
|
|
#endif
|
|
/// Add callback to run prior to exit termination
|
|
static void addExitCb(VoidPCb cb, void* datap) VL_MT_SAFE;
|
|
/// Remove callback to run prior to exit termination
|
|
static void removeExitCb(VoidPCb cb, void* datap) VL_MT_SAFE;
|
|
/// Run exit callbacks registered with addExitCb
|
|
static void runExitCallbacks() VL_MT_SAFE;
|
|
|
|
/// Return product name for (at least) VPI
|
|
static const char* productName() VL_PURE;
|
|
/// Return product version for (at least) VPI
|
|
static const char* productVersion() VL_PURE;
|
|
|
|
/// Call OS to make a directory
|
|
static void mkdir(const char* dirname) VL_MT_UNSAFE;
|
|
|
|
/// When multithreaded, quiesce the model to prepare for trace/saves/coverage
|
|
/// This may only be called when no locks are held.
|
|
static void quiesce() VL_MT_SAFE;
|
|
|
|
#ifndef VL_NO_LEGACY
|
|
/// For debugging, print much of the Verilator internal state.
|
|
/// The output of this function may change in future
|
|
/// releases - contact the authors before production use.
|
|
static void internalsDump() VL_MT_SAFE { Verilated::threadContextp()->internalsDump(); }
|
|
/// For debugging, print text list of all scope names with
|
|
/// dpiImport/Export context. This function may change in future
|
|
/// releases - contact the authors before production use.
|
|
static void scopesDump() VL_MT_SAFE { Verilated::threadContextp()->scopesDump(); }
|
|
// Internal: Find scope
|
|
static const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
|
|
return Verilated::threadContextp()->scopeFind(namep);
|
|
}
|
|
static const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE {
|
|
return Verilated::threadContextp()->scopeNameMap();
|
|
}
|
|
#endif
|
|
|
|
// METHODS - INTERNAL USE ONLY (but public due to what uses it)
|
|
// Internal: Create a new module name by concatenating two strings
|
|
// Returns pointer to thread-local static data (overwritten on next call)
|
|
static const char* catName(const char* n1, const char* n2,
|
|
const char* delimiter = ".") VL_MT_SAFE;
|
|
|
|
// Internal: Throw signal assertion
|
|
static void nullPointerError(const char* filename, int linenum) VL_ATTR_NORETURN VL_MT_SAFE;
|
|
static void overWidthError(const char* signame) VL_ATTR_NORETURN VL_MT_SAFE;
|
|
static void scTimePrecisionError(int sc_prec, int vl_prec) VL_ATTR_NORETURN VL_MT_SAFE;
|
|
static void scTraceBeforeElaborationError() VL_ATTR_NORETURN VL_MT_SAFE;
|
|
static void stackCheck(QData needSize) VL_MT_UNSAFE;
|
|
|
|
// Internal: Get and set DPI context
|
|
static const VerilatedScope* dpiScope() VL_MT_SAFE { return t_s.t_dpiScopep; }
|
|
static void dpiScope(const VerilatedScope* scopep) VL_MT_SAFE { t_s.t_dpiScopep = scopep; }
|
|
static void dpiContext(const VerilatedScope* scopep, const char* filenamep,
|
|
int lineno) VL_MT_SAFE {
|
|
t_s.t_dpiScopep = scopep;
|
|
t_s.t_dpiFilename = filenamep;
|
|
t_s.t_dpiLineno = lineno;
|
|
}
|
|
static void dpiClearContext() VL_MT_SAFE { t_s.t_dpiScopep = nullptr; }
|
|
static bool dpiInContext() VL_MT_SAFE { return t_s.t_dpiScopep != nullptr; }
|
|
static const char* dpiFilenamep() VL_MT_SAFE { return t_s.t_dpiFilename; }
|
|
static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; }
|
|
static int exportFuncNum(const char* namep) VL_MT_SAFE;
|
|
|
|
// Internal: Set the mtaskId, called when an mtask starts
|
|
// Per thread, so no need to be in VerilatedContext
|
|
static uint32_t mtaskId() VL_MT_SAFE { return t_s.t_mtaskId; }
|
|
static void mtaskId(uint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; }
|
|
static void endOfEvalReqdInc() VL_MT_SAFE { ++t_s.t_endOfEvalReqd; }
|
|
static void endOfEvalReqdDec() VL_MT_SAFE { --t_s.t_endOfEvalReqd; }
|
|
|
|
// Internal: Called at end of each thread mtask, before finishing eval
|
|
static void endOfThreadMTask(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
|
|
mtaskId(0);
|
|
if (VL_UNLIKELY(t_s.t_endOfEvalReqd)) endOfThreadMTaskGuts(evalMsgQp);
|
|
}
|
|
// Internal: Called at end of eval loop
|
|
static void endOfEval(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE;
|
|
|
|
private:
|
|
static void endOfThreadMTaskGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE;
|
|
};
|
|
|
|
void VerilatedContext::debug(int val) VL_MT_SAFE { Verilated::debug(val); }
|
|
int VerilatedContext::debug() VL_MT_SAFE { return Verilated::debug(); }
|
|
|
|
//=========================================================================
|
|
// Data Types
|
|
|
|
#include "verilated_types.h"
|
|
|
|
//=========================================================================
|
|
// Functions
|
|
|
|
#include "verilated_funcs.h"
|
|
|
|
//======================================================================
|
|
|
|
void VerilatedContext::timeprecision(int value) VL_MT_SAFE {
|
|
if (value < 0) value = -value; // Stored as 0..15
|
|
#if VM_SC
|
|
int sc_prec = 99;
|
|
#endif
|
|
{
|
|
const VerilatedLockGuard lock{m_mutex};
|
|
m_s.m_timeprecision = value;
|
|
#if VM_SC
|
|
const sc_core::sc_time sc_res = sc_core::sc_get_time_resolution();
|
|
if (sc_res == sc_core::sc_time(1, sc_core::SC_SEC)) {
|
|
sc_prec = 0;
|
|
} else if (sc_res == sc_core::sc_time(1, sc_core::SC_MS)) {
|
|
sc_prec = 3;
|
|
} else if (sc_res == sc_core::sc_time(1, sc_core::SC_US)) {
|
|
sc_prec = 6;
|
|
} else if (sc_res == sc_core::sc_time(1, sc_core::SC_NS)) {
|
|
sc_prec = 9;
|
|
} else if (sc_res == sc_core::sc_time(1, sc_core::SC_PS)) {
|
|
sc_prec = 12;
|
|
} else if (sc_res == sc_core::sc_time(1, sc_core::SC_FS)) {
|
|
sc_prec = 15;
|
|
}
|
|
// SC_AS, SC_ZS, SC_YS not supported as no Verilog equivalent; will error below
|
|
#endif
|
|
}
|
|
#if VM_SC
|
|
if (VL_UNLIKELY(value != sc_prec)) Verilated::scTimePrecisionError(sc_prec, value);
|
|
#endif
|
|
}
|
|
|
|
#undef VERILATOR_VERILATED_H_INTERNAL_
|
|
#endif // Guard
|