verilator/src/V3Global.h

223 lines
9.5 KiB
C
Raw Normal View History

// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Common headers
//
2019-11-08 04:33:59 +01:00
// Code available from: https://verilator.org
//
//*************************************************************************
//
2025-01-01 14:30:25 +01:00
// Copyright 2003-2025 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
//
//*************************************************************************
#ifndef VERILATOR_V3GLOBAL_H_
#define VERILATOR_V3GLOBAL_H_
// clang-format off
#include "config_build.h"
#ifndef HAVE_CONFIG_PACKAGE
# error "Something failed during ./configure as config_package.h is incomplete. Perhaps you used autoreconf, don't."
2018-06-29 00:55:36 +02:00
#endif
// clang-format on
2018-06-29 00:55:36 +02:00
#include "verilatedos.h"
#include "V3Error.h"
#include "V3FileLine.h"
#include "V3Mutex.h"
#include "V3Options.h"
#include <string>
#include <thread>
#include <unordered_map>
#include <unordered_set>
class AstNetlist;
class V3HierGraph;
class V3ThreadPool;
//======================================================================
// Restorer
/// Save a given variable's value on the stack, restoring it at end-of-scope.
// Object must be named, or it will not persist until end-of-scope.
// Constructor needs () or GCC 4.8 false warning.
#define VL_RESTORER(var) const VRestorer<typename std::decay_t<decltype(var)>> restorer_##var(var);
/// Get the copy of the variable previously saved by VL_RESTORER()
#define VL_RESTORER_PREV(var) restorer_##var.saved()
// Object used by VL_RESTORER. This object must be an auto variable, not
// allocated on the heap or otherwise.
template <typename T>
class VRestorer final {
T& m_ref; // Reference to object we're saving and restoring
const T m_saved; // Value saved, for later restore
public:
explicit VRestorer(T& permr)
: m_ref{permr}
, m_saved{permr} {}
~VRestorer() { m_ref = m_saved; }
const T& saved() const { return m_saved; }
VL_UNCOPYABLE(VRestorer);
};
//######################################################################
class VWidthMinUsage final {
public:
enum en : uint8_t { LINT_WIDTH, MATCHES_WIDTH, VERILOG_WIDTH };
enum en m_e;
VWidthMinUsage()
: m_e{LINT_WIDTH} {}
2015-10-04 04:33:06 +02:00
// cppcheck-suppress noExplicitConstructor
constexpr VWidthMinUsage(en _e) VL_PURE : m_e{_e} {}
constexpr VWidthMinUsage(const VWidthMinUsage& _e) VL_PURE = default;
explicit VWidthMinUsage(int _e)
2020-08-18 14:10:44 +02:00
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
constexpr operator en() const { return m_e; }
constexpr VWidthMinUsage& operator=(const VWidthMinUsage& _e) VL_PURE = default;
};
constexpr bool operator==(const VWidthMinUsage& lhs, const VWidthMinUsage& rhs) {
return lhs.m_e == rhs.m_e;
}
constexpr bool operator==(const VWidthMinUsage& lhs, VWidthMinUsage::en rhs) VL_PURE {
return lhs.m_e == rhs;
}
constexpr bool operator==(VWidthMinUsage::en lhs, const VWidthMinUsage& rhs) {
return lhs == rhs.m_e;
}
//######################################################################
// V3Global - The top level class for the entire program
class V3Global final {
// Globals
// Root of entire netlist, created by makeInitNetlist(} so static constructors run first
AstNetlist* m_rootp = nullptr;
// Hierarchical block graph (plan) iff hierarchical verilation is performed
V3HierGraph* m_hierGraphp = nullptr;
// Thread Pool, nullptr unless 'verilatedJobs' is known, set via threadPoolp(V3ThreadPool*)
V3ThreadPool* m_threadPoolp = nullptr;
VWidthMinUsage m_widthMinUsage
= VWidthMinUsage::LINT_WIDTH; // What AstNode::widthMin() is used for
2012-02-02 02:20:43 +01:00
std::atomic_int m_debugFileNumber{0}; // Number to append to debug files created
bool m_assertDTypesResolved = false; // Tree should have dtypep()'s
bool m_assertScoped = false; // Tree is scoped
bool m_assignsEvents = false; // Design uses assignments on SystemVerilog Events
bool m_constRemoveXs = false; // Const needs to strip any Xs
// Experimenting with always requiring heavy, see issue #2701
bool m_needTraceDumper = false; // Need __Vm_dumperp in symbols
bool m_dpi = false; // Need __Dpi include files
bool m_hasEvents = false; // Design uses SystemVerilog named events
bool m_hasClasses = false; // Design uses SystemVerilog classes
bool m_hasSampled = false; // Design uses SAMPLED expresions
bool m_hasTable = false; // Desgin has the UDP Table.
bool m_hasVirtIfaces = false; // Design uses virtual interfaces
bool m_usesProbDist = false; // Uses $dist_*
bool m_usesStdPackage = false; // Design uses the std package
Timing support (#3363) Adds timing support to Verilator. It makes it possible to use delays, event controls within processes (not just at the start), wait statements, and forks. Building a design with those constructs requires a compiler that supports C++20 coroutines (GCC 10, Clang 5). The basic idea is to have processes and tasks with delays/event controls implemented as C++20 coroutines. This allows us to suspend and resume them at any time. There are five main runtime classes responsible for managing suspended coroutines: * `VlCoroutineHandle`, a wrapper over C++20's `std::coroutine_handle` with move semantics and automatic cleanup. * `VlDelayScheduler`, for coroutines suspended by delays. It resumes them at a proper simulation time. * `VlTriggerScheduler`, for coroutines suspended by event controls. It resumes them if its corresponding trigger was set. * `VlForkSync`, used for syncing `fork..join` and `fork..join_any` blocks. * `VlCoroutine`, the return type of all verilated coroutines. It allows for suspending a stack of coroutines (normally, C++ coroutines are stackless). There is a new visitor in `V3Timing.cpp` which: * scales delays according to the timescale, * simplifies intra-assignment timing controls and net delays into regular timing controls and assignments, * simplifies wait statements into loops with event controls, * marks processes and tasks with timing controls in them as suspendable, * creates delay, trigger scheduler, and fork sync variables, * transforms timing controls and fork joins into C++ awaits There are new functions in `V3SchedTiming.cpp` (used by `V3Sched.cpp`) that integrate static scheduling with timing. This involves providing external domains for variables, so that the necessary combinational logic gets triggered after coroutine resumption, as well as statements that need to be injected into the design eval function to perform this resumption at the correct time. There is also a function that transforms forked processes into separate functions. See the comments in `verilated_timing.h`, `verilated_timing.cpp`, `V3Timing.cpp`, and `V3SchedTiming.cpp`, as well as the internals documentation for more details. Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
2022-08-22 14:26:32 +02:00
bool m_usesTiming = false; // Design uses timing constructs
bool m_hasForceableSignals = false; // Need to apply V3Force pass
bool m_hasSystemCSections = false; // Has AstSystemCSection that need to be emitted
bool m_useParallelBuild = false; // Use parallel build for model
bool m_useRandomizeMethods = false; // Need to define randomize() class methods
2025-09-13 16:19:00 +02:00
uint64_t m_currentHierBlockCost = 0; // Total cost of this hier block, used for scheduling
// Memory address to short string mapping (for debug)
std::unordered_map<const void*, std::string>
m_ptrToId; // The actual 'address' <=> 'short string' bijection
// Names of fields that were dumped by dumpJsonPtr()
std::unordered_set<std::string> m_jsonPtrNames;
// Id of the main thread
const std::thread::id m_mainThreadId = std::this_thread::get_id();
public:
// Options
V3Options opt; // All options; let user see them directly
// CONSTRUCTORS
V3Global() {}
2022-07-13 19:24:48 +02:00
void boot();
void shutdown(); // Release allocated resources
void vlExit(int status);
// ACCESSORS (general)
AstNetlist* rootp() const VL_MT_SAFE { return m_rootp; }
V3ThreadPool* threadPoolp() const VL_PURE { return m_threadPoolp; }
void threadPoolp(V3ThreadPool* threadPoolp) {
UASSERT(!m_threadPoolp, "attempted to create multiple threadPool singletons");
m_threadPoolp = threadPoolp;
}
VWidthMinUsage widthMinUsage() const VL_PURE { return m_widthMinUsage; }
bool assertDTypesResolved() const { return m_assertDTypesResolved; }
bool assertScoped() const { return m_assertScoped; }
// METHODS
void readFiles() VL_MT_DISABLED;
void removeStd() VL_MT_DISABLED;
void checkTree() const;
static void dumpCheckGlobalTree(const string& stagename, int newNumber = 0,
bool doDump = true);
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
void assertScoped(bool flag) { m_assertScoped = flag; }
void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; }
bool constRemoveXs() const { return m_constRemoveXs; }
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
string debugFilename(const string& nameComment, int newNumber = 0);
static string digitsFilename(int number);
2020-04-05 02:48:03 +02:00
bool needTraceDumper() const { return m_needTraceDumper; }
void needTraceDumper(bool flag) { m_needTraceDumper = flag; }
bool dpi() const VL_MT_SAFE { return m_dpi; }
void dpi(bool flag) { m_dpi = flag; }
bool assignsEvents() const { return m_assignsEvents; }
void setAssignsEvents() { m_assignsEvents = true; }
bool hasEvents() const { return m_hasEvents; }
void setHasEvents() { m_hasEvents = true; }
bool hasClasses() const { return m_hasClasses; }
void setHasClasses() { m_hasClasses = true; }
bool hasSampled() const { return m_hasSampled; }
void setHasSampled() { m_hasSampled = true; }
bool hasTable() const { return m_hasTable; }
void setHasTable() { m_hasTable = true; }
bool hasVirtIfaces() const { return m_hasVirtIfaces; }
void setHasVirtIfaces() { m_hasVirtIfaces = true; }
bool usesProbDist() const { return m_usesProbDist; }
void setUsesProbDist() { m_usesProbDist = true; }
bool usesStdPackage() const { return m_usesStdPackage; }
void setUsesStdPackage() { m_usesStdPackage = true; }
Timing support (#3363) Adds timing support to Verilator. It makes it possible to use delays, event controls within processes (not just at the start), wait statements, and forks. Building a design with those constructs requires a compiler that supports C++20 coroutines (GCC 10, Clang 5). The basic idea is to have processes and tasks with delays/event controls implemented as C++20 coroutines. This allows us to suspend and resume them at any time. There are five main runtime classes responsible for managing suspended coroutines: * `VlCoroutineHandle`, a wrapper over C++20's `std::coroutine_handle` with move semantics and automatic cleanup. * `VlDelayScheduler`, for coroutines suspended by delays. It resumes them at a proper simulation time. * `VlTriggerScheduler`, for coroutines suspended by event controls. It resumes them if its corresponding trigger was set. * `VlForkSync`, used for syncing `fork..join` and `fork..join_any` blocks. * `VlCoroutine`, the return type of all verilated coroutines. It allows for suspending a stack of coroutines (normally, C++ coroutines are stackless). There is a new visitor in `V3Timing.cpp` which: * scales delays according to the timescale, * simplifies intra-assignment timing controls and net delays into regular timing controls and assignments, * simplifies wait statements into loops with event controls, * marks processes and tasks with timing controls in them as suspendable, * creates delay, trigger scheduler, and fork sync variables, * transforms timing controls and fork joins into C++ awaits There are new functions in `V3SchedTiming.cpp` (used by `V3Sched.cpp`) that integrate static scheduling with timing. This involves providing external domains for variables, so that the necessary combinational logic gets triggered after coroutine resumption, as well as statements that need to be injected into the design eval function to perform this resumption at the correct time. There is also a function that transforms forked processes into separate functions. See the comments in `verilated_timing.h`, `verilated_timing.cpp`, `V3Timing.cpp`, and `V3SchedTiming.cpp`, as well as the internals documentation for more details. Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
2022-08-22 14:26:32 +02:00
bool usesTiming() const { return m_usesTiming; }
void setUsesTiming() { m_usesTiming = true; }
bool hasForceableSignals() const { return m_hasForceableSignals; }
void setHasForceableSignals() { m_hasForceableSignals = true; }
bool hasSystemCSections() const VL_MT_SAFE { return m_hasSystemCSections; }
void setHasSystemCSections() { m_hasSystemCSections = true; }
V3HierGraph* hierGraphp() const { return m_hierGraphp; }
void hierGraphp(V3HierGraph* graphp) { m_hierGraphp = graphp; }
bool useParallelBuild() const { return m_useParallelBuild; }
void useParallelBuild(bool flag) { m_useParallelBuild = flag; }
bool useRandomizeMethods() const { return m_useRandomizeMethods; }
void useRandomizeMethods(bool flag) { m_useRandomizeMethods = flag; }
void saveJsonPtrFieldName(const std::string& fieldName);
void ptrNamesDumpJson(std::ostream& os);
void idPtrMapDumpJson(std::ostream& os);
const std::string& ptrToId(const void* p);
std::thread::id mainThreadId() const { return m_mainThreadId; }
static std::vector<std::string> verilatedCppFiles();
2025-09-13 16:19:00 +02:00
uint64_t currentHierBlockCost() const { return m_currentHierBlockCost; }
void currentHierBlockCost(uint64_t cost) { m_currentHierBlockCost = cost; }
};
extern V3Global v3Global;
//######################################################################
#endif // guard