verilator/src/V3Options.h

687 lines
34 KiB
C
Raw Normal View History

// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Command line options
//
2019-11-08 04:33:59 +01:00
// Code available from: https://verilator.org
//
//*************************************************************************
//
2022-01-01 14:26:40 +01:00
// Copyright 2003-2022 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_V3OPTIONS_H_
#define VERILATOR_V3OPTIONS_H_
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3LangCode.h"
2009-01-21 22:56:50 +01:00
#include <map>
#include <set>
#include <string>
#include <vector>
class V3OptionsImp;
class FileLine;
//######################################################################
class VOptionBool final {
// Class to track options that are either not specified (and default
// true/false), versus user setting the option to true or false
public:
2021-03-08 03:05:15 +01:00
enum en : uint8_t { OPT_DEFAULT_FALSE = 0, OPT_DEFAULT_TRUE, OPT_TRUE, OPT_FALSE };
enum en m_e;
VOptionBool()
: m_e{OPT_DEFAULT_FALSE} {}
// cppcheck-suppress noExplicitConstructor
constexpr VOptionBool(en _e)
: m_e{_e} {}
explicit VOptionBool(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; }
bool isDefault() const { return m_e == OPT_DEFAULT_FALSE || m_e == OPT_DEFAULT_TRUE; }
bool isTrue() const { return m_e == OPT_TRUE || m_e == OPT_DEFAULT_TRUE; }
2020-04-10 05:26:03 +02:00
bool isSetTrue() const { return m_e == OPT_TRUE; }
bool isSetFalse() const { return m_e == OPT_FALSE; }
void setTrueOrFalse(bool flag) { m_e = flag ? OPT_TRUE : OPT_FALSE; }
};
constexpr bool operator==(const VOptionBool& lhs, const VOptionBool& rhs) {
return lhs.m_e == rhs.m_e;
}
constexpr bool operator==(const VOptionBool& lhs, VOptionBool::en rhs) { return lhs.m_e == rhs; }
constexpr bool operator==(VOptionBool::en lhs, const VOptionBool& rhs) { return lhs == rhs.m_e; }
// ######################################################################
class VTimescale final {
public:
enum en : uint8_t {
// clang-format off
2020-05-11 14:15:52 +02:00
TS_100S = 0, TS_10S = 1, TS_1S = 2,
TS_100MS = 3, TS_10MS = 4, TS_1MS = 5,
TS_100US = 6, TS_10US = 7, TS_1US = 8,
TS_100NS = 9, TS_10NS = 10, TS_1NS = 11,
TS_100PS = 12, TS_10PS = 13, TS_1PS = 14,
TS_100FS = 15, TS_10FS = 16, TS_1FS = 17,
// clang-format on
2020-05-11 14:15:52 +02:00
NONE = 18,
_ENUM_END
};
enum : uint8_t { TS_DEFAULT = TS_1PS };
enum en m_e;
// CONSTRUCTOR
VTimescale()
: m_e{NONE} {}
// cppcheck-suppress noExplicitConstructor
constexpr VTimescale(en _e)
: m_e{_e} {}
explicit VTimescale(int _e)
2020-08-18 14:10:44 +02:00
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
// Construct from string
VTimescale(const string& value, bool& badr);
VTimescale(double value, bool& badr) {
badr = false;
2021-03-08 03:05:15 +01:00
for (int i = TS_100S; i < _ENUM_END; ++i) {
m_e = static_cast<en>(i);
if (multiplier() == value) break;
}
if (multiplier() != value) {
m_e = NONE;
badr = true;
}
}
bool isNone() const { return m_e == NONE; }
// Parse a "unit/precision" string into two VTimescales, with error checking
static void parseSlashed(FileLine* fl, const char* textp, VTimescale& unitr, VTimescale& precr,
bool allowEmpty = false);
const char* ascii() const {
static const char* const names[]
2020-05-11 14:15:52 +02:00
= {"100s", "10s", "1s", "100ms", "10ms", "1ms", "100us", "10us", "1us", "100ns",
"10ns", "1ns", "100ps", "10ps", "1ps", "100fs", "10fs", "1fs", "NONE"};
return names[m_e];
}
2020-06-02 05:16:02 +02:00
int powerOfTen() const { return 2 - static_cast<int>(m_e); }
double multiplier() const {
2020-05-29 03:04:36 +02:00
static const double values[]
= {100, 10, 1, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7,
1e-8, 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 0};
return values[m_e];
}
};
constexpr bool operator==(const VTimescale& lhs, const VTimescale& rhs) {
return lhs.m_e == rhs.m_e;
}
constexpr bool operator==(const VTimescale& lhs, VTimescale::en rhs) { return lhs.m_e == rhs; }
constexpr bool operator==(VTimescale::en lhs, const VTimescale& rhs) { return lhs == rhs.m_e; }
// Comparisons are based on time, not enum values, so seconds > milliseconds
constexpr bool operator<(const VTimescale& lhs, const VTimescale& rhs) {
return lhs.m_e > rhs.m_e;
}
inline std::ostream& operator<<(std::ostream& os, const VTimescale& rhs) {
return os << rhs.ascii();
}
// ######################################################################
class TraceFormat final {
public:
enum en : uint8_t { VCD = 0, FST } m_e;
// cppcheck-suppress noExplicitConstructor
constexpr TraceFormat(en _e = VCD)
: m_e{_e} {}
explicit TraceFormat(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; }
bool fst() const { return m_e == FST; }
bool vcd() const { return m_e == VCD; }
string classBase() const {
static const char* const names[] = {"VerilatedVcd", "VerilatedFst"};
return names[m_e];
}
string sourceName() const {
static const char* const names[] = {"verilated_vcd", "verilated_fst"};
return names[m_e];
}
};
constexpr bool operator==(const TraceFormat& lhs, const TraceFormat& rhs) {
return lhs.m_e == rhs.m_e;
}
constexpr bool operator==(const TraceFormat& lhs, TraceFormat::en rhs) { return lhs.m_e == rhs; }
constexpr bool operator==(TraceFormat::en lhs, const TraceFormat& rhs) { return lhs == rhs.m_e; }
using V3StringList = std::vector<std::string>;
using V3StringSet = std::set<std::string>;
// ######################################################################
// Information given by --hierarchical-block option
class V3HierarchicalBlockOption final {
public:
// key:parameter name, value:value (as string)
using ParamStrMap = std::map<const std::string, std::string>;
private:
string m_origName; // module name
// module name after uniquified
// same as m_origName for non-parameterized module
string m_mangledName;
// overriding parameter values specified by -G option
ParamStrMap m_parameters;
public:
explicit V3HierarchicalBlockOption(const string& optstring);
const string& origName() const { return m_origName; }
const string& mangledName() const { return m_mangledName; }
const ParamStrMap params() const { return m_parameters; }
};
using V3HierBlockOptSet = std::map<const std::string, V3HierarchicalBlockOption>;
//######################################################################
// V3Options - Command line options
class V3Options final {
public:
private:
2009-01-21 22:56:50 +01:00
// TYPES
using DebugLevelMap = std::map<const std::string, unsigned>;
2009-01-21 22:56:50 +01:00
// MEMBERS (general options)
V3OptionsImp* m_impp; // Slow hidden options
// clang-format off
V3StringSet m_cppFiles; // argument: C++ files to link against
V3StringList m_cFlags; // argument: user CFLAGS
V3StringList m_ldLibs; // argument: user LDFLAGS
V3StringList m_makeFlags; // argument: user MAKEFLAGS
V3StringSet m_futures; // argument: -Wfuture- list
2022-08-20 20:01:13 +02:00
V3StringSet m_future0s; // argument: -future list
V3StringSet m_future1s; // argument: -future1 list
V3StringSet m_libraryFiles; // argument: Verilog -v files
V3StringSet m_clockers; // argument: Verilog -clk signals
V3StringSet m_noClockers; // argument: Verilog -noclk signals
V3StringList m_vFiles; // argument: Verilog files to read
V3StringList m_forceIncs; // argument: -FI
DebugLevelMap m_debugLevel; // argument: --debugi-<srcfile/tag> <level>
DebugLevelMap m_dumpLevel; // argument: --dumpi-<srcfile/tag> <level>
std::map<const string, string> m_parameters; // Parameters
std::map<const string, V3HierarchicalBlockOption> m_hierBlocks; // main switch: --hierarchical-block
Introduce DFG based combinational logic optimizer (#3527) Added a new data-flow graph (DFG) based combinational logic optimizer. The capabilities of this covers a combination of V3Const and V3Gate, but is also more capable of transforming combinational logic into simplified forms and more. This entail adding a new internal representation, `DfgGraph`, and appropriate `astToDfg` and `dfgToAst` conversion functions. The graph represents some of the combinational equations (~continuous assignments) in a module, and for the duration of the DFG passes, it takes over the role of AstModule. A bulk of the Dfg vertices represent expressions. These vertex classes, and the corresponding conversions to/from AST are mostly auto-generated by astgen, together with a DfgVVisitor that can be used for dynamic dispatch based on vertex (operation) types. The resulting combinational logic graph (a `DfgGraph`) is then optimized in various ways. Currently we perform common sub-expression elimination, variable inlining, and some specific peephole optimizations, but there is scope for more optimizations in the future using the same representation. The optimizer is run directly before and after inlining. The pre inline pass can operate on smaller graphs and hence converges faster, but still has a chance of substantially reducing the size of the logic on some designs, making inlining both faster and less memory intensive. The post inline pass can then optimize across the inlined module boundaries. No optimization is performed across a module boundary. For debugging purposes, each peephole optimization can be disabled individually via the -fno-dfg-peepnole-<OPT> option, where <OPT> is one of the optimizations listed in V3DfgPeephole.h, for example -fno-dfg-peephole-remove-not-not. The peephole patterns currently implemented were mostly picked based on the design that inspired this work, and on that design the optimizations yields ~30% single threaded speedup, and ~50% speedup on 4 threads. As you can imagine not having to haul around redundant combinational networks in the rest of the compilation pipeline also helps with memory consumption, and up to 30% peak memory usage of Verilator was observed on the same design. Gains on other arbitrary designs are smaller (and can be improved by analyzing those designs). For example OpenTitan gains between 1-15% speedup depending on build type.
2022-09-23 17:46:22 +02:00
V3StringSet m_fDfgPeepholeDisabled; // argument: -f[no-]dfg-peephole-<name>
bool m_preprocOnly = false; // main switch: -E
bool m_makePhony = false; // main switch: -MP
bool m_preprocNoLine = false; // main switch: -P
bool m_assert = false; // main switch: --assert
bool m_autoflush = false; // main switch: --autoflush
bool m_bboxSys = false; // main switch: --bbox-sys
bool m_bboxUnsup = false; // main switch: --bbox-unsup
bool m_build = false; // main switch: --build
bool m_cdc = false; // main switch: --cdc
bool m_cmake = false; // main switch: --make cmake
bool m_context = true; // main switch: --Wcontext
bool m_coverageLine = false; // main switch: --coverage-block
bool m_coverageToggle = false; // main switch: --coverage-toggle
bool m_coverageUnderscore = false; // main switch: --coverage-underscore
bool m_coverageUser = false; // main switch: --coverage-func
bool m_debugCheck = false; // main switch: --debug-check
bool m_debugCollision = false; // main switch: --debug-collision
bool m_debugEmitV = false; // main switch: --debug-emitv
bool m_debugExitParse = false; // main switch: --debug-exit-parse
2020-08-23 15:05:18 +02:00
bool m_debugExitUvm = false; // main switch: --debug-exit-uvm
bool m_debugLeak = true; // main switch: --debug-leak
bool m_debugNondeterminism = false; // main switch: --debug-nondeterminism
bool m_debugPartition = false; // main switch: --debug-partition
bool m_debugProtect = false; // main switch: --debug-protect
bool m_debugSelfTest = false; // main switch: --debug-self-test
bool m_decoration = true; // main switch: --decoration
bool m_dpiHdrOnly = false; // main switch: --dpi-hdr-only
bool m_exe = false; // main switch: --exe
bool m_flatten = false; // main switch: --flatten
bool m_hierarchical = false; // main switch: --hierarchical
bool m_ignc = false; // main switch: --ignc
bool m_lintOnly = false; // main switch: --lint-only
bool m_gmake = false; // main switch: --make gmake
bool m_main = false; // main swithc: --main
bool m_outFormatOk = false; // main switch: --cc, --sc or --sp was specified
bool m_pedantic = false; // main switch: --Wpedantic
bool m_pinsScUint = false; // main switch: --pins-sc-uint
bool m_pinsScBigUint = false; // main switch: --pins-sc-biguint
bool m_pinsUint8 = false; // main switch: --pins-uint8
bool m_ppComments = false; // main switch: --pp-comments
bool m_profC = false; // main switch: --prof-c
bool m_profCFuncs = false; // main switch: --prof-cfuncs
bool m_profExec = false; // main switch: --prof-exec
bool m_profPgo = false; // main switch: --prof-pgo
bool m_protectIds = false; // main switch: --protect-ids
bool m_public = false; // main switch: --public
bool m_publicFlatRW = false; // main switch: --public-flat-rw
bool m_quietExit = false; // main switch: --quiet-exit
bool m_relativeIncludes = false; // main switch: --relative-includes
bool m_reportUnoptflat = false; // main switch: --report-unoptflat
bool m_savable = false; // main switch: --savable
bool m_structsPacked = true; // main switch: --structs-packed
bool m_systemC = false; // main switch: --sc: System C instead of simple C++
bool m_stats = false; // main switch: --stats
bool m_statsVars = false; // main switch: --stats-vars
bool m_threadsCoarsen = true; // main switch: --threads-coarsen
bool m_threadsDpiPure = true; // main switch: --threads-dpi all/pure
bool m_threadsDpiUnpure = false; // main switch: --threads-dpi all
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
VOptionBool m_timing; // main switch: --timing
bool m_trace = false; // main switch: --trace
bool m_traceCoverage = false; // main switch: --trace-coverage
bool m_traceParams = true; // main switch: --trace-params
bool m_traceStructs = false; // main switch: --trace-structs
bool m_traceUnderscore = false; // main switch: --trace-underscore
bool m_underlineZero = false; // main switch: --underline-zero; undocumented old Verilator 2
bool m_verilate = true; // main swith: --verilate
bool m_vpi = false; // main switch: --vpi
bool m_xInitialEdge = false; // main switch: --x-initial-edge
bool m_xmlOnly = false; // main switch: --xml-only
int m_buildJobs = -1; // main switch: --build-jobs, -j
int m_convergeLimit = 100; // main switch: --converge-limit
2021-03-30 00:54:51 +02:00
int m_coverageMaxWidth = 256; // main switch: --coverage-max-width
2021-06-06 16:27:01 +02:00
int m_expandLimit = 64; // main switch: --expand-limit
int m_gateStmts = 100; // main switch: --gate-stmts
int m_hierChild = 0; // main switch: --hierarchical-child
int m_ifDepth = 0; // main switch: --if-depth
int m_inlineMult = 2000; // main switch: --inline-mult
int m_instrCountDpi = 200; // main switch: --instr-count-dpi
VOptionBool m_makeDepend; // main switch: -MMD
int m_maxNumWidth = 65536; // main switch: --max-num-width
int m_moduleRecursion = 100; // main switch: --module-recursion-depth
int m_outputSplit = 20000; // main switch: --output-split
int m_outputSplitCFuncs = -1; // main switch: --output-split-cfuncs
int m_outputSplitCTrace = -1; // main switch: --output-split-ctrace
int m_pinsBv = 65; // main switch: --pins-bv
int m_reloopLimit = 40; // main switch: --reloop-limit
VOptionBool m_skipIdentical; // main switch: --skip-identical
int m_threads = 0; // main switch: --threads (0 == --no-threads)
int m_threadsMaxMTasks = 0; // main switch: --threads-max-mtasks
VTimescale m_timeDefaultPrec; // main switch: --timescale
VTimescale m_timeDefaultUnit; // main switch: --timescale
VTimescale m_timeOverridePrec; // main switch: --timescale-override
VTimescale m_timeOverrideUnit; // main switch: --timescale-override
int m_traceDepth = 0; // main switch: --trace-depth
TraceFormat m_traceFormat; // main switch: --trace or --trace-fst
int m_traceMaxArray = 32; // main switch: --trace-max-array
int m_traceMaxWidth = 256; // main switch: --trace-max-width
int m_traceThreads = 0; // main switch: --trace-threads
int m_unrollCount = 64; // main switch: --unroll-count
int m_unrollStmts = 30000; // main switch: --unroll-stmts
int m_compLimitBlocks = 0; // compiler selection; number of nested blocks
int m_compLimitMembers = 64; // compiler selection; number of members in struct before make anon array
int m_compLimitParens = 240; // compiler selection; number of nested parens
2022-09-18 16:32:43 +02:00
string m_buildDepBin; // main switch: --build-dep-bin {filename}
string m_exeName; // main switch: -o {name}
string m_flags; // main switch: -f {name}
string m_l2Name; // main switch: --l2name; "" for top-module's name
string m_libCreate; // main switch: --lib-create {lib_name}
string m_makeDir; // main switch: -Mdir
string m_modPrefix; // main switch: --mod-prefix
string m_pipeFilter; // main switch: --pipe-filter
string m_prefix; // main switch: --prefix
string m_protectKey; // main switch: --protect-key
string m_topModule; // main switch: --top-module
string m_unusedRegexp; // main switch: --unused-regexp
string m_waiverOutput; // main switch: --waiver-output {filename}
string m_xAssign; // main switch: --x-assign
string m_xInitial; // main switch: --x-initial
2019-11-01 02:17:05 +01:00
string m_xmlOutput; // main switch: --xml-output
// Language is now held in FileLine, on a per-node basis. However we still
// have a concept of the default language at a global level.
V3LangCode m_defaultLanguage; // main switch: --language
// MEMBERS (optimizations)
bool m_fAcycSimp; // main switch: -fno-acyc-simp: acyclic pre-optimizations
bool m_fAssemble; // main switch: -fno-assemble: assign assemble
bool m_fCase; // main switch: -fno-case: case tree conversion
bool m_fCombine; // main switch: -fno-combine: common icode packing
bool m_fConst; // main switch: -fno-const: constant folding
bool m_fConstBeforeDfg = true; // main switch: -fno-const-before-dfg for testing only!
bool m_fConstBitOpTree; // main switch: -fno-const-bit-op-tree constant bit op tree
bool m_fDedupe; // main switch: -fno-dedupe: logic deduplication
Introduce DFG based combinational logic optimizer (#3527) Added a new data-flow graph (DFG) based combinational logic optimizer. The capabilities of this covers a combination of V3Const and V3Gate, but is also more capable of transforming combinational logic into simplified forms and more. This entail adding a new internal representation, `DfgGraph`, and appropriate `astToDfg` and `dfgToAst` conversion functions. The graph represents some of the combinational equations (~continuous assignments) in a module, and for the duration of the DFG passes, it takes over the role of AstModule. A bulk of the Dfg vertices represent expressions. These vertex classes, and the corresponding conversions to/from AST are mostly auto-generated by astgen, together with a DfgVVisitor that can be used for dynamic dispatch based on vertex (operation) types. The resulting combinational logic graph (a `DfgGraph`) is then optimized in various ways. Currently we perform common sub-expression elimination, variable inlining, and some specific peephole optimizations, but there is scope for more optimizations in the future using the same representation. The optimizer is run directly before and after inlining. The pre inline pass can operate on smaller graphs and hence converges faster, but still has a chance of substantially reducing the size of the logic on some designs, making inlining both faster and less memory intensive. The post inline pass can then optimize across the inlined module boundaries. No optimization is performed across a module boundary. For debugging purposes, each peephole optimization can be disabled individually via the -fno-dfg-peepnole-<OPT> option, where <OPT> is one of the optimizations listed in V3DfgPeephole.h, for example -fno-dfg-peephole-remove-not-not. The peephole patterns currently implemented were mostly picked based on the design that inspired this work, and on that design the optimizations yields ~30% single threaded speedup, and ~50% speedup on 4 threads. As you can imagine not having to haul around redundant combinational networks in the rest of the compilation pipeline also helps with memory consumption, and up to 30% peak memory usage of Verilator was observed on the same design. Gains on other arbitrary designs are smaller (and can be improved by analyzing those designs). For example OpenTitan gains between 1-15% speedup depending on build type.
2022-09-23 17:46:22 +02:00
bool m_fDfgPeephole = true; // main switch: -fno-dfg-peephole
bool m_fDfgPreInline; // main switch: -fno-dfg-pre-inline and -fno-dfg
bool m_fDfgPostInline; // main switch: -fno-dfg-post-inline and -fno-dfg
bool m_fExpand; // main switch: -fno-expand: expansion of C macros
bool m_fGate; // main switch: -fno-gate: gate wire elimination
bool m_fInline; // main switch: -fno-inline: module inlining
bool m_fLife; // main switch: -fno-life: variable lifetime
bool m_fLifePost; // main switch: -fno-life-post: delayed assignment elimination
bool m_fLocalize; // main switch: -fno-localize: convert temps to local variables
bool m_fMergeCond; // main switch: -fno-merge-cond: merge conditionals
bool m_fMergeCondMotion = true; // main switch: -fno-merge-cond-motion: perform code motion
bool m_fMergeConstPool = true; // main switch: -fno-merge-const-pool
bool m_fReloop; // main switch: -fno-reloop: reform loops
bool m_fReorder; // main switch: -fno-reorder: reorder assignments in blocks
bool m_fSplit; // main switch: -fno-split: always assignment splitting
bool m_fSubst; // main switch: -fno-subst: substitute expression temp values
bool m_fSubstConst; // main switch: -fno-subst-const: final constant substitution
bool m_fTable; // main switch: -fno-table: lookup table creation
// clang-format on
bool m_available = false; // Set to true at the end of option parsing
private:
// METHODS
void addArg(const string& arg);
void addDefine(const string& defline, bool allowPlus);
void addFuture(const string& flag);
2022-08-20 20:01:13 +02:00
void addFuture0(const string& flag);
void addFuture1(const string& flag);
void addIncDirUser(const string& incdir); // User requested
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
void addParameter(const string& paramline, bool allowPlus);
2013-02-03 19:27:37 +01:00
void addLangExt(const string& langext, const V3LangCode& lc);
void addLibExtV(const string& libext);
void optimize(int level);
void showVersion(bool verbose);
2008-12-12 21:34:02 +01:00
void coverage(bool flag) { m_coverageLine = m_coverageToggle = m_coverageUser = flag; }
static bool suffixed(const string& sw, const char* arg);
static string parseFileArg(const string& optdir, const string& relfilename);
string filePathCheckOneDir(const string& modname, const string& dirname);
static int stripOptionsForChildRun(const string& opt, bool forTop);
// CONSTRUCTORS
VL_UNCOPYABLE(V3Options);
public:
V3Options();
~V3Options();
void setDebugMode(int level);
unsigned debugLevel(const string& tag) const;
unsigned debugSrcLevel(const string& srcfile_path) const;
unsigned dumpLevel(const string& tag) const;
unsigned dumpSrcLevel(const string& srcfile_path) const;
// METHODS
void addCppFile(const string& filename);
void addCFlags(const string& filename);
void addLdLibs(const string& filename);
void addMakeFlags(const string& filename);
void addLibraryFile(const string& filename);
void addClocker(const string& signame);
void addNoClocker(const string& signame);
void addVFile(const string& filename);
void addForceInc(const string& filename);
bool available() const { return m_available; }
void ccSet();
void notify();
// ACCESSORS (options)
bool preprocOnly() const { return m_preprocOnly; }
bool makePhony() const { return m_makePhony; }
bool preprocNoLine() const { return m_preprocNoLine; }
bool underlineZero() const { return m_underlineZero; }
string flags() const { return m_flags; }
bool systemC() const { return m_systemC; }
bool savable() const { return m_savable; }
bool stats() const { return m_stats; }
2014-12-20 14:28:31 +01:00
bool statsVars() const { return m_statsVars; }
bool structsPacked() const { return m_structsPacked; }
2009-01-21 22:56:50 +01:00
bool assertOn() const { return m_assert; } // assertOn as __FILE__ may be defined
2008-07-16 20:06:08 +02:00
bool autoflush() const { return m_autoflush; }
bool bboxSys() const { return m_bboxSys; }
bool bboxUnsup() const { return m_bboxUnsup; }
bool build() const { return m_build; }
2022-09-18 16:32:43 +02:00
string buildDepBin() const { return m_buildDepBin; }
void buildDepBin(const string& flag) { m_buildDepBin = flag; }
2010-01-07 22:41:19 +01:00
bool cdc() const { return m_cdc; }
bool cmake() const { return m_cmake; }
bool context() const { return m_context; }
2008-12-12 21:34:02 +01:00
bool coverage() const { return m_coverageLine || m_coverageToggle || m_coverageUser; }
bool coverageLine() const { return m_coverageLine; }
2008-12-12 21:34:02 +01:00
bool coverageToggle() const { return m_coverageToggle; }
bool coverageUnderscore() const { return m_coverageUnderscore; }
bool coverageUser() const { return m_coverageUser; }
bool debugCheck() const { return m_debugCheck; }
bool debugCollision() const { return m_debugCollision; }
bool debugEmitV() const { return m_debugEmitV; }
2020-06-09 04:10:55 +02:00
bool debugExitParse() const { return m_debugExitParse; }
2020-08-23 15:05:18 +02:00
bool debugExitUvm() const { return m_debugExitUvm; }
bool debugLeak() const { return m_debugLeak; }
bool debugNondeterminism() const { return m_debugNondeterminism; }
bool debugPartition() const { return m_debugPartition; }
bool debugProtect() const { return m_debugProtect; }
bool debugSelfTest() const { return m_debugSelfTest; }
bool decoration() const { return m_decoration; }
2019-08-28 03:36:59 +02:00
bool dpiHdrOnly() const { return m_dpiHdrOnly; }
bool dumpDefines() const { return m_dumpLevel.count("defines") && m_dumpLevel.at("defines"); }
2022-10-01 17:06:12 +02:00
bool dumpTreeDot() const {
return m_dumpLevel.count("tree-dot") && m_dumpLevel.at("tree-dot");
}
bool exe() const { return m_exe; }
bool flatten() const { return m_flatten; }
bool gmake() const { return m_gmake; }
bool threadsDpiPure() const { return m_threadsDpiPure; }
bool threadsDpiUnpure() const { return m_threadsDpiUnpure; }
bool threadsCoarsen() const { return m_threadsCoarsen; }
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
VOptionBool timing() const { return m_timing; }
bool trace() const { return m_trace; }
2019-10-27 14:27:18 +01:00
bool traceCoverage() const { return m_traceCoverage; }
2014-03-14 01:08:43 +01:00
bool traceParams() const { return m_traceParams; }
bool traceStructs() const { return m_traceStructs; }
bool traceUnderscore() const { return m_traceUnderscore; }
2020-04-22 02:45:23 +02:00
bool main() const { return m_main; }
bool outFormatOk() const { return m_outFormatOk; }
bool keepTempFiles() const { return (V3Error::debugDefault() != 0); }
2019-11-16 17:59:21 +01:00
bool pedantic() const { return m_pedantic; }
bool pinsScUint() const { return m_pinsScUint; }
bool pinsScBigUint() const { return m_pinsScBigUint; }
bool pinsUint8() const { return m_pinsUint8; }
2018-10-26 03:17:25 +02:00
bool ppComments() const { return m_ppComments; }
bool profC() const { return m_profC; }
bool profCFuncs() const { return m_profCFuncs; }
bool profExec() const { return m_profExec; }
bool profPgo() const { return m_profPgo; }
bool usesProfiler() const { return profExec() || profPgo(); }
bool protectIds() const { return m_protectIds; }
bool allPublic() const { return m_public; }
bool publicFlatRW() const { return m_publicFlatRW; }
bool lintOnly() const { return m_lintOnly; }
bool ignc() const { return m_ignc; }
bool quietExit() const { return m_quietExit; }
bool reportUnoptflat() const { return m_reportUnoptflat; }
bool verilate() const { return m_verilate; }
bool vpi() const { return m_vpi; }
bool xInitialEdge() const { return m_xInitialEdge; }
2012-03-20 21:13:10 +01:00
bool xmlOnly() const { return m_xmlOnly; }
bool topIfacesSupported() const { return lintOnly() && !hierarchical(); }
int buildJobs() const { return m_buildJobs; }
int convergeLimit() const { return m_convergeLimit; }
2021-03-30 00:54:51 +02:00
int coverageMaxWidth() const { return m_coverageMaxWidth; }
bool dumpTreeAddrids() const;
2021-06-06 16:27:01 +02:00
int expandLimit() const { return m_expandLimit; }
int gateStmts() const { return m_gateStmts; }
int ifDepth() const { return m_ifDepth; }
int inlineMult() const { return m_inlineMult; }
int instrCountDpi() const { return m_instrCountDpi; }
VOptionBool makeDepend() const { return m_makeDepend; }
int maxNumWidth() const { return m_maxNumWidth; }
int moduleRecursionDepth() const { return m_moduleRecursion; }
int outputSplit() const { return m_outputSplit; }
int outputSplitCFuncs() const { return m_outputSplitCFuncs; }
int outputSplitCTrace() const { return m_outputSplitCTrace; }
int pinsBv() const { return m_pinsBv; }
int reloopLimit() const { return m_reloopLimit; }
VOptionBool skipIdentical() const { return m_skipIdentical; }
int threads() const { return m_threads; }
int threadsMaxMTasks() const { return m_threadsMaxMTasks; }
bool mtasks() const { return (m_threads > 1); }
VTimescale timeDefaultPrec() const { return m_timeDefaultPrec; }
VTimescale timeDefaultUnit() const { return m_timeDefaultUnit; }
VTimescale timeOverridePrec() const { return m_timeOverridePrec; }
VTimescale timeOverrideUnit() const { return m_timeOverrideUnit; }
VTimescale timeComputePrec(const VTimescale& flag) const;
VTimescale timeComputeUnit(const VTimescale& flag) const;
int traceDepth() const { return m_traceDepth; }
TraceFormat traceFormat() const { return m_traceFormat; }
int traceMaxArray() const { return m_traceMaxArray; }
int traceMaxWidth() const { return m_traceMaxWidth; }
int traceThreads() const { return m_traceThreads; }
bool useTraceOffload() const { return trace() && traceFormat().fst() && traceThreads() > 1; }
bool useTraceParallel() const {
return trace() && traceFormat().vcd() && threads() && (threads() > 1 || hierChild() > 1);
}
bool useFstWriterThread() const { return traceThreads() && traceFormat().fst(); }
unsigned vmTraceThreads() const {
return useTraceParallel() ? threads() : useTraceOffload() ? 1 : 0;
}
int unrollCount() const { return m_unrollCount; }
int unrollStmts() const { return m_unrollStmts; }
int compLimitBlocks() const { return m_compLimitBlocks; }
int compLimitMembers() const { return m_compLimitMembers; }
int compLimitParens() const { return m_compLimitParens; }
string exeName() const { return m_exeName != "" ? m_exeName : prefix(); }
string l2Name() const { return m_l2Name; }
string libCreate() const { return m_libCreate; }
string libCreateName(bool shared) {
string libName = "lib" + libCreate();
if (shared) {
libName += ".so";
} else {
libName += ".a";
}
return libName;
}
string makeDir() const { return m_makeDir; }
string modPrefix() const { return m_modPrefix; }
string pipeFilter() const { return m_pipeFilter; }
string prefix() const { return m_prefix; }
// Not just called protectKey() to avoid bugs of not using protectKeyDefaulted()
bool protectKeyProvided() const { return !m_protectKey.empty(); }
string protectKeyDefaulted(); // Set default key if not set by user
string topModule() const { return m_topModule; }
2011-01-02 01:43:22 +01:00
string unusedRegexp() const { return m_unusedRegexp; }
string waiverOutput() const { return m_waiverOutput; }
bool isWaiverOutput() const { return !m_waiverOutput.empty(); }
string xAssign() const { return m_xAssign; }
2017-10-02 03:31:40 +02:00
string xInitial() const { return m_xInitial; }
2019-11-01 02:17:05 +01:00
string xmlOutput() const { return m_xmlOutput; }
const V3StringSet& cppFiles() const { return m_cppFiles; }
const V3StringList& cFlags() const { return m_cFlags; }
const V3StringList& ldLibs() const { return m_ldLibs; }
const V3StringList& makeFlags() const { return m_makeFlags; }
const V3StringSet& libraryFiles() const { return m_libraryFiles; }
const V3StringList& vFiles() const { return m_vFiles; }
const V3StringList& forceIncs() const { return m_forceIncs; }
bool hasParameter(const string& name);
string parameter(const string& name);
void checkParameters();
bool isFuture(const string& flag) const;
2022-08-20 20:01:13 +02:00
bool isFuture0(const string& flag) const;
bool isFuture1(const string& flag) const;
2010-12-30 01:34:33 +01:00
bool isLibraryFile(const string& filename) const;
bool isClocker(const string& signame) const;
bool isNoClocker(const string& signame) const;
// ACCESSORS (optimization options)
bool fAcycSimp() const { return m_fAcycSimp; }
bool fAssemble() const { return m_fAssemble; }
bool fCase() const { return m_fCase; }
bool fCombine() const { return m_fCombine; }
bool fConst() const { return m_fConst; }
bool fConstBeforeDfg() const { return m_fConstBeforeDfg; }
bool fConstBitOpTree() const { return m_fConstBitOpTree; }
bool fDedupe() const { return m_fDedupe; }
Introduce DFG based combinational logic optimizer (#3527) Added a new data-flow graph (DFG) based combinational logic optimizer. The capabilities of this covers a combination of V3Const and V3Gate, but is also more capable of transforming combinational logic into simplified forms and more. This entail adding a new internal representation, `DfgGraph`, and appropriate `astToDfg` and `dfgToAst` conversion functions. The graph represents some of the combinational equations (~continuous assignments) in a module, and for the duration of the DFG passes, it takes over the role of AstModule. A bulk of the Dfg vertices represent expressions. These vertex classes, and the corresponding conversions to/from AST are mostly auto-generated by astgen, together with a DfgVVisitor that can be used for dynamic dispatch based on vertex (operation) types. The resulting combinational logic graph (a `DfgGraph`) is then optimized in various ways. Currently we perform common sub-expression elimination, variable inlining, and some specific peephole optimizations, but there is scope for more optimizations in the future using the same representation. The optimizer is run directly before and after inlining. The pre inline pass can operate on smaller graphs and hence converges faster, but still has a chance of substantially reducing the size of the logic on some designs, making inlining both faster and less memory intensive. The post inline pass can then optimize across the inlined module boundaries. No optimization is performed across a module boundary. For debugging purposes, each peephole optimization can be disabled individually via the -fno-dfg-peepnole-<OPT> option, where <OPT> is one of the optimizations listed in V3DfgPeephole.h, for example -fno-dfg-peephole-remove-not-not. The peephole patterns currently implemented were mostly picked based on the design that inspired this work, and on that design the optimizations yields ~30% single threaded speedup, and ~50% speedup on 4 threads. As you can imagine not having to haul around redundant combinational networks in the rest of the compilation pipeline also helps with memory consumption, and up to 30% peak memory usage of Verilator was observed on the same design. Gains on other arbitrary designs are smaller (and can be improved by analyzing those designs). For example OpenTitan gains between 1-15% speedup depending on build type.
2022-09-23 17:46:22 +02:00
bool fDfgPeephole() const { return m_fDfgPeephole; }
bool fDfgPreInline() const { return m_fDfgPreInline; }
bool fDfgPostInline() const { return m_fDfgPostInline; }
bool fDfgPeepholeEnabled(const std::string& name) const {
return !m_fDfgPeepholeDisabled.count(name);
}
bool fExpand() const { return m_fExpand; }
bool fGate() const { return m_fGate; }
bool fInline() const { return m_fInline; }
bool fLife() const { return m_fLife; }
bool fLifePost() const { return m_fLifePost; }
bool fLocalize() const { return m_fLocalize; }
bool fMergeCond() const { return m_fMergeCond; }
bool fMergeCondMotion() const { return m_fMergeCondMotion; }
bool fMergeConstPool() const { return m_fMergeConstPool; }
bool fReloop() const { return m_fReloop; }
bool fReorder() const { return m_fReorder; }
bool fSplit() const { return m_fSplit; }
bool fSubst() const { return m_fSubst; }
bool fSubstConst() const { return m_fSubstConst; }
bool fTable() const { return m_fTable; }
string traceClassBase() const { return m_traceFormat.classBase(); }
2020-03-02 03:39:23 +01:00
string traceClassLang() const { return m_traceFormat.classBase() + (systemC() ? "Sc" : "C"); }
string traceSourceBase() const { return m_traceFormat.sourceName(); }
string traceSourceLang() const {
return m_traceFormat.sourceName() + (systemC() ? "_sc" : "_c");
}
bool hierarchical() const { return m_hierarchical; }
int hierChild() const { return m_hierChild; }
bool hierTop() const { return !m_hierChild && !m_hierBlocks.empty(); }
const V3HierBlockOptSet& hierBlocks() const { return m_hierBlocks; }
// Directory to save .tree, .dot, .dat, .vpp for hierarchical block top
// Returns makeDir() unless top module of hierarchical verilation.
string hierTopDataDir() const {
return hierTop() ? (makeDir() + '/' + prefix() + "__hier.dir") : makeDir();
}
// METHODS (from main)
static string version();
static string argString(int argc, char** argv); ///< Return list of arguments as simple string
2020-07-03 20:16:43 +02:00
string allArgsString() const; ///< Return all passed arguments as simple string
// Return options for child hierarchical blocks when forTop==false, otherwise returns args for
// the top module.
string allArgsStringForHierBlock(bool forTop) const;
void parseOpts(FileLine* fl, int argc, char** argv);
void parseOptsList(FileLine* fl, const string& optdir, int argc, char** argv);
void parseOptsFile(FileLine* fl, const string& filename, bool rel);
// METHODS (environment)
// Most of these may be built into the executable with --enable-defenv,
// see the README. If adding new variables, also see src/Makefile_obj.in
// Also add to V3Options::showVersion()
2017-09-24 00:03:39 +02:00
static string getenvBuiltins(const string& var);
static string getenvMAKE();
2010-12-18 01:40:08 +01:00
static string getenvPERL();
static string getenvSYSTEMC();
static string getenvSYSTEMC_ARCH();
2012-01-20 02:30:41 +01:00
static string getenvSYSTEMC_INCLUDE();
static string getenvSYSTEMC_LIBDIR();
static string getenvVERILATOR_ROOT();
static bool systemCSystemWide();
static bool systemCFound(); // SystemC installed, or environment points to it
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
static bool coroutineSupport(); // Compiler supports coroutines
// METHODS (file utilities using these options)
string fileExists(const string& filename);
string filePath(FileLine* fl, const string& modname, const string& lastpath,
const string& errmsg);
void filePathLookedMsg(FileLine* fl, const string& modname);
V3LangCode fileLanguage(const string& filename);
static bool fileStatNormal(const string& filename);
static void fileNfsFlush(const string& filename);
// METHODS (other OS)
static void throwSigsegv();
};
//######################################################################
#endif // guard