2012-04-13 03:08:20 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2006-08-26 13:35:28 +02:00
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Common headers
|
|
|
|
|
//
|
2019-11-08 04:33:59 +01:00
|
|
|
// Code available from: https://verilator.org
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2026-01-27 02:24:34 +01:00
|
|
|
// 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-FileCopyrightText: 2003-2026 Wilson Snyder
|
2020-03-21 16:24:24 +01:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
2019-10-05 02:17:11 +02:00
|
|
|
|
2021-03-04 03:57:07 +01:00
|
|
|
#ifndef VERILATOR_V3GLOBAL_H_
|
|
|
|
|
#define VERILATOR_V3GLOBAL_H_
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2020-04-14 04:51:35 +02:00
|
|
|
// clang-format off
|
2006-12-18 20:20:45 +01:00
|
|
|
#include "config_build.h"
|
2023-07-27 11:42:35 +02:00
|
|
|
#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
|
2020-04-14 04:51:35 +02:00
|
|
|
// clang-format on
|
2018-06-29 00:55:36 +02:00
|
|
|
|
2006-12-18 20:20:45 +01:00
|
|
|
#include "verilatedos.h"
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
#include "V3Error.h"
|
2014-11-22 17:48:39 +01:00
|
|
|
#include "V3FileLine.h"
|
2023-09-25 04:12:23 +02:00
|
|
|
#include "V3Mutex.h"
|
2006-08-26 13:35:28 +02:00
|
|
|
#include "V3Options.h"
|
2011-11-30 04:09:50 +01:00
|
|
|
|
2018-10-14 19:43:24 +02:00
|
|
|
#include <string>
|
2024-08-23 14:36:49 +02:00
|
|
|
#include <thread>
|
2026-07-04 18:27:07 +02:00
|
|
|
#include <type_traits>
|
2020-08-15 16:03:34 +02:00
|
|
|
#include <unordered_map>
|
2024-02-09 23:50:09 +01:00
|
|
|
#include <unordered_set>
|
2018-10-14 19:43:24 +02:00
|
|
|
|
2011-11-30 04:09:50 +01:00
|
|
|
class AstNetlist;
|
2025-10-09 21:41:23 +02:00
|
|
|
class V3HierGraph;
|
2025-12-16 17:21:46 +01:00
|
|
|
class V3LibMap;
|
2024-08-23 14:36:49 +02:00
|
|
|
class V3ThreadPool;
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
//======================================================================
|
2020-08-25 03:10:43 +02:00
|
|
|
// Restorer
|
|
|
|
|
|
2026-07-04 18:27:07 +02:00
|
|
|
// For all flavours, 'var' must be a named scalar variable (simple identifier).
|
|
|
|
|
|
|
|
|
|
// Copy given variable's value on the stack, copy saved value back at end-of-scope.
|
|
|
|
|
// Only usable for trivially copyable types; use VL_RESTORER_COPY/VL_RESTORER_CLEAR for
|
|
|
|
|
// non-trivially copyable types, which are more efficient.
|
|
|
|
|
#define VL_RESTORER(var) \
|
|
|
|
|
const VRestorerTrivial<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
|
|
|
|
|
|
|
|
|
// This is the equivalent of VL_RESTORER for non-trivially copyable types. Still more efficient
|
|
|
|
|
// than VL_RESTORER as uses move to restore.
|
|
|
|
|
#define VL_RESTORER_COPY(var) \
|
|
|
|
|
const VRestorerCopy<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
|
|
|
|
|
|
|
|
|
// Swap 'var' with a no-args constructed object of the same type, effectively clearing it, then
|
|
|
|
|
// swap back at end-of-scope. No copying involved. Use this e.g. for std containers where they
|
|
|
|
|
// would be .clear()'d right after the VL_RESTORER instance.
|
|
|
|
|
#define VL_RESTORER_CLEAR(var) \
|
|
|
|
|
const VRestorerClear<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
|
|
|
|
|
|
|
|
|
// Get const reference to the saved copy
|
2023-10-15 19:01:32 +02:00
|
|
|
#define VL_RESTORER_PREV(var) restorer_##var.saved()
|
2020-08-25 03:10:43 +02:00
|
|
|
|
2026-07-04 18:27:07 +02:00
|
|
|
// Implementation of VL_RESTORER
|
2022-08-05 11:56:57 +02:00
|
|
|
template <typename T>
|
2026-07-04 18:27:07 +02:00
|
|
|
class VRestorerTrivial final {
|
|
|
|
|
static_assert(std::is_trivially_copyable<T>::value,
|
|
|
|
|
"Use VL_RESTORER_{COPY,CLEAR} for non trivially copyable types");
|
2020-08-25 03:10:43 +02:00
|
|
|
T& m_ref; // Reference to object we're saving and restoring
|
|
|
|
|
const T m_saved; // Value saved, for later restore
|
|
|
|
|
|
|
|
|
|
public:
|
2026-07-04 18:27:07 +02:00
|
|
|
explicit VRestorerTrivial(T& val)
|
|
|
|
|
: m_ref{val}
|
|
|
|
|
, m_saved{val} {}
|
|
|
|
|
~VRestorerTrivial() { m_ref = m_saved; }
|
|
|
|
|
VL_UNCOPYABLE(VRestorerTrivial);
|
|
|
|
|
// Must be stack allocated
|
|
|
|
|
void* operator new(size_t) = delete;
|
|
|
|
|
void operator delete(void*) = delete;
|
|
|
|
|
|
|
|
|
|
const T& saved() const { return m_saved; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Implementation of VL_RESTORER_COPY
|
|
|
|
|
template <typename T>
|
|
|
|
|
class VRestorerCopy final {
|
|
|
|
|
static_assert(!std::is_trivially_copyable<T>::value,
|
|
|
|
|
"Use VL_RESTORER for trivially copyable types");
|
|
|
|
|
T& m_ref; // Reference to object we're saving and restoring
|
|
|
|
|
T m_saved; // Value saved, for later restore
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit VRestorerCopy(T& val)
|
|
|
|
|
: m_ref{val}
|
|
|
|
|
, m_saved{val} {}
|
|
|
|
|
~VRestorerCopy() { m_ref = std::move(m_saved); }
|
|
|
|
|
VL_UNCOPYABLE(VRestorerCopy);
|
|
|
|
|
// Must be stack allocated
|
|
|
|
|
void* operator new(size_t) = delete;
|
|
|
|
|
void operator delete(void*) = delete;
|
|
|
|
|
|
|
|
|
|
const T& saved() const { return m_saved; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Implementation of VL_RESTORER_CLEAR.
|
|
|
|
|
template <typename T>
|
|
|
|
|
class VRestorerClear final {
|
|
|
|
|
static_assert(!std::is_trivially_copyable<T>::value,
|
|
|
|
|
"Use VL_RESTORER for trivially copyable types");
|
|
|
|
|
T& m_ref; // Reference to object we're saving and restoring
|
|
|
|
|
T m_saved{}; // Owns the swapped-out value; starts empty
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit VRestorerClear(T& val)
|
|
|
|
|
: m_ref{val} {
|
|
|
|
|
std::swap(m_ref, m_saved);
|
|
|
|
|
}
|
|
|
|
|
~VRestorerClear() { std::swap(m_ref, m_saved); }
|
|
|
|
|
VL_UNCOPYABLE(VRestorerClear);
|
|
|
|
|
// Must be stack allocated
|
|
|
|
|
void* operator new(size_t) = delete;
|
|
|
|
|
void operator delete(void*) = delete;
|
|
|
|
|
|
2023-10-15 19:01:32 +02:00
|
|
|
const T& saved() const { return m_saved; }
|
2020-08-25 03:10:43 +02:00
|
|
|
};
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
2015-05-15 03:46:07 +02:00
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VWidthMinUsage final {
|
2015-05-15 03:46:07 +02:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t { LINT_WIDTH, MATCHES_WIDTH, VERILOG_WIDTH };
|
2015-05-15 03:46:07 +02:00
|
|
|
enum en m_e;
|
2020-12-02 00:49:03 +01:00
|
|
|
VWidthMinUsage()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{LINT_WIDTH} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2024-03-02 14:57:26 +01:00
|
|
|
constexpr VWidthMinUsage(en _e) VL_PURE : m_e{_e} {}
|
|
|
|
|
constexpr VWidthMinUsage(const VWidthMinUsage& _e) VL_PURE = default;
|
2020-12-02 00:49:03 +01:00
|
|
|
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
|
2022-09-23 11:57:01 +02:00
|
|
|
constexpr operator en() const { return m_e; }
|
2024-03-02 14:57:26 +01:00
|
|
|
constexpr VWidthMinUsage& operator=(const VWidthMinUsage& _e) VL_PURE = default;
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
2022-09-23 11:57:01 +02:00
|
|
|
constexpr bool operator==(const VWidthMinUsage& lhs, const VWidthMinUsage& rhs) {
|
2020-02-02 16:34:29 +01:00
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
2024-03-02 14:57:26 +01:00
|
|
|
constexpr bool operator==(const VWidthMinUsage& lhs, VWidthMinUsage::en rhs) VL_PURE {
|
2020-02-02 16:34:29 +01:00
|
|
|
return lhs.m_e == rhs;
|
|
|
|
|
}
|
2022-09-23 11:57:01 +02:00
|
|
|
constexpr bool operator==(VWidthMinUsage::en lhs, const VWidthMinUsage& rhs) {
|
2020-02-02 16:34:29 +01:00
|
|
|
return lhs == rhs.m_e;
|
|
|
|
|
}
|
2015-05-15 03:46:07 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// V3Global - The top level class for the entire program
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class V3Global final {
|
2006-08-26 13:35:28 +02:00
|
|
|
// Globals
|
2025-10-09 21:41:23 +02:00
|
|
|
// 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;
|
2025-12-16 17:21:46 +01:00
|
|
|
// Library Mapping, nullptr unless --libmap is used
|
|
|
|
|
V3LibMap* m_libMapp = nullptr;
|
2022-01-01 17:46:49 +01:00
|
|
|
VWidthMinUsage m_widthMinUsage
|
|
|
|
|
= VWidthMinUsage::LINT_WIDTH; // What AstNode::widthMin() is used for
|
2012-02-02 02:20:43 +01:00
|
|
|
|
2023-03-18 01:24:15 +01:00
|
|
|
std::atomic_int m_debugFileNumber{0}; // Number to append to debug files created
|
2020-08-15 19:11:27 +02:00
|
|
|
bool m_assertDTypesResolved = false; // Tree should have dtypep()'s
|
2020-11-14 22:13:06 +01:00
|
|
|
bool m_assertScoped = false; // Tree is scoped
|
2023-10-26 16:38:47 +02:00
|
|
|
bool m_assignsEvents = false; // Design uses assignments on SystemVerilog Events
|
2020-08-15 19:11:27 +02:00
|
|
|
bool m_constRemoveXs = false; // Const needs to strip any Xs
|
2023-09-16 00:12:11 +02:00
|
|
|
// Experimenting with always requiring heavy, see issue #2701
|
2020-08-15 19:11:27 +02:00
|
|
|
bool m_needTraceDumper = false; // Need __Vm_dumperp in symbols
|
|
|
|
|
bool m_dpi = false; // Need __Dpi include files
|
2022-05-15 17:03:32 +02:00
|
|
|
bool m_hasEvents = false; // Design uses SystemVerilog named events
|
2022-09-29 00:54:18 +02:00
|
|
|
bool m_hasClasses = false; // Design uses SystemVerilog classes
|
2024-07-10 00:31:58 +02:00
|
|
|
bool m_hasSampled = false; // Design uses SAMPLED expresions
|
2025-04-16 12:32:18 +02:00
|
|
|
bool m_hasTable = false; // Desgin has the UDP Table.
|
2023-12-05 04:11:07 +01:00
|
|
|
bool m_hasVirtIfaces = false; // Design uses virtual interfaces
|
2022-12-04 23:30:51 +01:00
|
|
|
bool m_usesProbDist = false; // Uses $dist_*
|
2022-11-28 16:53:55 +01:00
|
|
|
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
|
2026-04-21 17:54:42 +02:00
|
|
|
bool m_usesForce = false; // Design uses force/release statements
|
Support #0 delays with IEEE-1800 compliant semantics (#7079)
This patch adds IEEE-1800 compliant scheduling support for the Inactive
scheduling region used for #0 delays.
Implementing this requires that **all** IEEE-1800 active region events
are placed in the internal 'act' section. This has simulation
performance implications. It prevents some optimizations (e.g.
V3LifePost), which reduces single threaded performance. It also reduces
the available work and parallelism in the internal 'nba' section, which
reduced the effectiveness of multi-threading severely.
Performance impact on RTLMeter when using scheduling adjusted to support
proper #0 delays is ~10-20% slowdown in single-threaded mode, and ~100%
(2x slower) with --threads 4.
To avoid paying this performance penalty unconditionally, the scheduling
is only adjusted if either:
1. The input contains a statically known #0 delay
2. The input contains a variable #x delay unknown at compile time
If no #0 is present, but #x variable delays are, a ZERODLY warning is
issued advising the use of '--no-sched-zero-delay' which is a promise
by the user that none of the variable delays will evaluate to a zero
delay at run-time. This warning is turned off if '--sched-zero-delay'
is explicitly given. This is similar to the '--timing' option.
If '--no-sched-zero-delay' was used at compile time, then executing
a zero delay will fail at runtime.
A ZERODLY warning is also issued if a static #0 if found, but the user
specified '--no-sched-zero-delay'. In this case the scheduling is not
adjusted to support #0, so executing it will fail at runtime. Presumably
the user knows it won't be executed.
The intended behaviour with all this is the following:
No #0, no #var in the design (#constant is OK)
-> Same as current behaviour, scheduling not adjusted,
same code generated as before
Has static #0 and '--no-sched-zero-delay' is NOT given:
-> No warnings, scheduling adjusted so it just works, runs slow
Has static #0 and '--no-sched-zero-delay' is given:
-> ZERODLY on the #0, scheduling not adjusted, fails at runtime if hit
No static #0, but has #var and no option is given:
-> ZERODLY on the #var advising use of '--no-sched-zero-delay' or
'--sched-zero-delay' (similar to '--timing'), scheduling adjusted
assuming it can be a zero delay and it just works
No static #0, but has #var and '--no-sched-zero-delay' is given:
-> No warning, scheduling not adjusted, fails at runtime if zero delay
No static #0, but has #var and '--sched-zero-delay' is given:
-> No warning, scheduling adjusted so it just works
2026-02-16 04:55:55 +01:00
|
|
|
bool m_usesZeroDelay = false; // Design uses #0 delay (or non-constant delay)
|
2021-12-17 18:56:33 +01:00
|
|
|
bool m_hasForceableSignals = false; // Need to apply V3Force pass
|
2026-05-09 01:01:11 +02:00
|
|
|
bool m_hasAssignDeassign = false; // Need to apply V3Force pass for assign/deassign statements
|
2025-10-14 12:23:23 +02:00
|
|
|
bool m_hasSystemCSections = false; // Has AstSystemCSection that need to be emitted
|
2020-08-15 19:11:27 +02:00
|
|
|
bool m_useParallelBuild = false; // Use parallel build for model
|
2025-11-30 15:04:42 +01:00
|
|
|
bool m_useRandSequence = false; // Has `randsequence`
|
2026-06-05 15:35:01 +02:00
|
|
|
bool m_useCovergroup = false; // Has covergroup declarations
|
2020-12-07 23:55:22 +01:00
|
|
|
bool m_useRandomizeMethods = false; // Need to define randomize() class methods
|
2026-05-12 15:49:21 +02:00
|
|
|
bool m_hasPrintedObjects = false; // Design has format args printed with to_string()
|
2025-09-13 16:19:00 +02:00
|
|
|
uint64_t m_currentHierBlockCost = 0; // Total cost of this hier block, used for scheduling
|
2007-11-30 23:38:21 +01:00
|
|
|
|
2020-05-23 19:31:30 +02:00
|
|
|
// Memory address to short string mapping (for debug)
|
2021-03-12 23:26:53 +01:00
|
|
|
std::unordered_map<const void*, std::string>
|
|
|
|
|
m_ptrToId; // The actual 'address' <=> 'short string' bijection
|
2020-05-23 19:31:30 +02:00
|
|
|
|
2024-02-09 23:50:09 +01:00
|
|
|
// Names of fields that were dumped by dumpJsonPtr()
|
|
|
|
|
std::unordered_set<std::string> m_jsonPtrNames;
|
|
|
|
|
|
2024-08-23 14:36:49 +02:00
|
|
|
// Id of the main thread
|
|
|
|
|
const std::thread::id m_mainThreadId = std::this_thread::get_id();
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2007-11-30 23:38:21 +01:00
|
|
|
// Options
|
2019-05-19 22:13:13 +02:00
|
|
|
V3Options opt; // All options; let user see them directly
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2017-11-01 23:51:41 +01:00
|
|
|
// CONSTRUCTORS
|
2026-03-28 04:14:18 +01:00
|
|
|
V3Global() = default;
|
2022-07-13 19:24:48 +02:00
|
|
|
void boot();
|
2022-12-03 00:46:38 +01:00
|
|
|
void shutdown(); // Release allocated resources
|
2023-09-25 04:12:23 +02:00
|
|
|
|
2025-09-10 19:20:19 +02:00
|
|
|
void vlExit(int status);
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
// ACCESSORS (general)
|
2022-10-18 23:07:09 +02:00
|
|
|
AstNetlist* rootp() const VL_MT_SAFE { return m_rootp; }
|
2025-12-16 17:21:46 +01:00
|
|
|
V3LibMap* libMapp() const VL_PURE { return m_libMapp; }
|
2024-08-23 14:36:49 +02:00
|
|
|
V3ThreadPool* threadPoolp() const VL_PURE { return m_threadPoolp; }
|
|
|
|
|
void threadPoolp(V3ThreadPool* threadPoolp) {
|
|
|
|
|
UASSERT(!m_threadPoolp, "attempted to create multiple threadPool singletons");
|
|
|
|
|
m_threadPoolp = threadPoolp;
|
|
|
|
|
}
|
2024-03-02 14:57:26 +01:00
|
|
|
VWidthMinUsage widthMinUsage() const VL_PURE { return m_widthMinUsage; }
|
2011-11-30 04:36:51 +01:00
|
|
|
bool assertDTypesResolved() const { return m_assertDTypesResolved; }
|
2020-11-14 22:13:06 +01:00
|
|
|
bool assertScoped() const { return m_assertScoped; }
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// METHODS
|
2023-09-25 04:12:23 +02:00
|
|
|
void readFiles() VL_MT_DISABLED;
|
|
|
|
|
void removeStd() VL_MT_DISABLED;
|
2020-08-16 20:55:46 +02:00
|
|
|
void checkTree() const;
|
2026-03-06 02:03:48 +01:00
|
|
|
static void dumpCheckGlobalTree(const string& stagename, int newNumber = 0, bool doDump = true,
|
|
|
|
|
bool doCheck = true);
|
2011-11-30 04:36:51 +01:00
|
|
|
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
2020-11-14 22:13:06 +01:00
|
|
|
void assertScoped(bool flag) { m_assertScoped = flag; }
|
2015-05-15 03:46:07 +02:00
|
|
|
void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; }
|
2014-06-10 04:27:04 +02:00
|
|
|
bool constRemoveXs() const { return m_constRemoveXs; }
|
|
|
|
|
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
|
2023-03-18 01:24:15 +01:00
|
|
|
string debugFilename(const string& nameComment, int newNumber = 0);
|
2021-03-06 16:33:43 +01:00
|
|
|
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; }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool dpi() const VL_MT_SAFE { return m_dpi; }
|
2009-12-03 12:55:29 +01:00
|
|
|
void dpi(bool flag) { m_dpi = flag; }
|
2023-10-26 16:38:47 +02:00
|
|
|
bool assignsEvents() const { return m_assignsEvents; }
|
|
|
|
|
void setAssignsEvents() { m_assignsEvents = true; }
|
2022-05-15 17:03:32 +02:00
|
|
|
bool hasEvents() const { return m_hasEvents; }
|
|
|
|
|
void setHasEvents() { m_hasEvents = true; }
|
2022-09-29 00:54:18 +02:00
|
|
|
bool hasClasses() const { return m_hasClasses; }
|
|
|
|
|
void setHasClasses() { m_hasClasses = true; }
|
2024-07-10 00:31:58 +02:00
|
|
|
bool hasSampled() const { return m_hasSampled; }
|
|
|
|
|
void setHasSampled() { m_hasSampled = true; }
|
2025-04-16 12:32:18 +02:00
|
|
|
bool hasTable() const { return m_hasTable; }
|
|
|
|
|
void setHasTable() { m_hasTable = true; }
|
2023-12-05 04:11:07 +01:00
|
|
|
bool hasVirtIfaces() const { return m_hasVirtIfaces; }
|
|
|
|
|
void setHasVirtIfaces() { m_hasVirtIfaces = true; }
|
2022-12-04 23:30:51 +01:00
|
|
|
bool usesProbDist() const { return m_usesProbDist; }
|
|
|
|
|
void setUsesProbDist() { m_usesProbDist = true; }
|
2022-11-28 16:53:55 +01:00
|
|
|
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; }
|
Support #0 delays with IEEE-1800 compliant semantics (#7079)
This patch adds IEEE-1800 compliant scheduling support for the Inactive
scheduling region used for #0 delays.
Implementing this requires that **all** IEEE-1800 active region events
are placed in the internal 'act' section. This has simulation
performance implications. It prevents some optimizations (e.g.
V3LifePost), which reduces single threaded performance. It also reduces
the available work and parallelism in the internal 'nba' section, which
reduced the effectiveness of multi-threading severely.
Performance impact on RTLMeter when using scheduling adjusted to support
proper #0 delays is ~10-20% slowdown in single-threaded mode, and ~100%
(2x slower) with --threads 4.
To avoid paying this performance penalty unconditionally, the scheduling
is only adjusted if either:
1. The input contains a statically known #0 delay
2. The input contains a variable #x delay unknown at compile time
If no #0 is present, but #x variable delays are, a ZERODLY warning is
issued advising the use of '--no-sched-zero-delay' which is a promise
by the user that none of the variable delays will evaluate to a zero
delay at run-time. This warning is turned off if '--sched-zero-delay'
is explicitly given. This is similar to the '--timing' option.
If '--no-sched-zero-delay' was used at compile time, then executing
a zero delay will fail at runtime.
A ZERODLY warning is also issued if a static #0 if found, but the user
specified '--no-sched-zero-delay'. In this case the scheduling is not
adjusted to support #0, so executing it will fail at runtime. Presumably
the user knows it won't be executed.
The intended behaviour with all this is the following:
No #0, no #var in the design (#constant is OK)
-> Same as current behaviour, scheduling not adjusted,
same code generated as before
Has static #0 and '--no-sched-zero-delay' is NOT given:
-> No warnings, scheduling adjusted so it just works, runs slow
Has static #0 and '--no-sched-zero-delay' is given:
-> ZERODLY on the #0, scheduling not adjusted, fails at runtime if hit
No static #0, but has #var and no option is given:
-> ZERODLY on the #var advising use of '--no-sched-zero-delay' or
'--sched-zero-delay' (similar to '--timing'), scheduling adjusted
assuming it can be a zero delay and it just works
No static #0, but has #var and '--no-sched-zero-delay' is given:
-> No warning, scheduling not adjusted, fails at runtime if zero delay
No static #0, but has #var and '--sched-zero-delay' is given:
-> No warning, scheduling adjusted so it just works
2026-02-16 04:55:55 +01:00
|
|
|
bool usesZeroDelay() const { return m_usesZeroDelay; }
|
|
|
|
|
void setUsesZeroDelay() { m_usesZeroDelay = true; }
|
2021-12-17 18:56:33 +01:00
|
|
|
bool hasForceableSignals() const { return m_hasForceableSignals; }
|
|
|
|
|
void setHasForceableSignals() { m_hasForceableSignals = true; }
|
2026-05-09 01:01:11 +02:00
|
|
|
bool hasAssignDeassign() const { return m_hasAssignDeassign; }
|
|
|
|
|
void setHasAssignDeassign() { m_hasAssignDeassign = true; }
|
2026-04-21 17:54:42 +02:00
|
|
|
bool usesForce() const { return m_usesForce; }
|
|
|
|
|
void setUsesForce() { m_usesForce = true; }
|
2025-10-14 12:23:23 +02:00
|
|
|
bool hasSystemCSections() const VL_MT_SAFE { return m_hasSystemCSections; }
|
|
|
|
|
void setHasSystemCSections() { m_hasSystemCSections = true; }
|
2025-10-09 21:41:23 +02:00
|
|
|
V3HierGraph* hierGraphp() const { return m_hierGraphp; }
|
|
|
|
|
void hierGraphp(V3HierGraph* graphp) { m_hierGraphp = graphp; }
|
2020-05-25 22:12:34 +02:00
|
|
|
bool useParallelBuild() const { return m_useParallelBuild; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void useParallelBuild(bool flag) { m_useParallelBuild = flag; }
|
2025-11-30 15:04:42 +01:00
|
|
|
bool useRandSequence() const { return m_useRandSequence; }
|
|
|
|
|
void useRandSequence(bool flag) { m_useRandSequence = flag; }
|
2026-06-05 15:35:01 +02:00
|
|
|
bool useCovergroup() const { return m_useCovergroup; }
|
|
|
|
|
void useCovergroup(bool flag) { m_useCovergroup = flag; }
|
2020-12-07 23:55:22 +01:00
|
|
|
bool useRandomizeMethods() const { return m_useRandomizeMethods; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void useRandomizeMethods(bool flag) { m_useRandomizeMethods = flag; }
|
2026-05-12 15:49:21 +02:00
|
|
|
bool hasPrintedObjects() const { return m_hasPrintedObjects; }
|
|
|
|
|
void hasPrintedObjects(bool flag) { m_hasPrintedObjects = flag; }
|
2024-02-09 23:50:09 +01:00
|
|
|
void saveJsonPtrFieldName(const std::string& fieldName);
|
|
|
|
|
void ptrNamesDumpJson(std::ostream& os);
|
|
|
|
|
void idPtrMapDumpJson(std::ostream& os);
|
2020-05-23 19:31:30 +02:00
|
|
|
const std::string& ptrToId(const void* p);
|
2024-08-23 14:36:49 +02:00
|
|
|
std::thread::id mainThreadId() const { return m_mainThreadId; }
|
2025-04-09 04:30:44 +02:00
|
|
|
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; }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extern V3Global v3Global;
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2019-05-14 01:47:52 +02:00
|
|
|
#endif // guard
|