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: Error handling
|
|
|
|
|
//
|
2019-11-08 04:33:59 +01:00
|
|
|
// Code available from: https://verilator.org
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2023-01-01 16:18:39 +01:00
|
|
|
// Copyright 2003-2023 by Wilson Snyder. This program is free software; you
|
2020-03-21 16:24:24 +01:00
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 23:07:57 +02:00
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
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_V3ERROR_H_
|
|
|
|
|
#define VERILATOR_V3ERROR_H_
|
2018-10-14 19:43:24 +02:00
|
|
|
|
2006-12-18 20:20:45 +01:00
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
2018-10-14 19:43:24 +02:00
|
|
|
|
2023-04-11 13:23:24 +02:00
|
|
|
#include "V3Mutex.h"
|
2023-02-10 04:15:37 +01:00
|
|
|
|
2019-10-03 03:38:06 +02:00
|
|
|
// Limited V3 headers here - this is a base class for Vlc etc
|
|
|
|
|
#include "V3String.h"
|
2023-02-10 04:15:37 +01:00
|
|
|
#ifndef V3ERROR_NO_GLOBAL_
|
|
|
|
|
#include "V3ThreadPool.h"
|
|
|
|
|
#endif
|
2019-10-03 03:38:06 +02:00
|
|
|
|
2020-11-16 13:31:12 +01:00
|
|
|
#include <array>
|
2006-08-26 13:35:28 +02:00
|
|
|
#include <bitset>
|
2018-10-14 19:43:24 +02:00
|
|
|
#include <cassert>
|
2022-09-18 21:53:42 +02:00
|
|
|
#include <cctype>
|
2018-10-14 19:43:24 +02:00
|
|
|
#include <deque>
|
2011-10-11 13:07:24 +02:00
|
|
|
#include <map>
|
2012-05-22 03:31:52 +02:00
|
|
|
#include <set>
|
2018-10-14 19:43:24 +02:00
|
|
|
#include <sstream>
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class V3ErrorCode final {
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format off
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en: uint8_t {
|
2019-05-19 22:13:13 +02:00
|
|
|
EC_MIN=0, // Keep first
|
|
|
|
|
//
|
|
|
|
|
EC_INFO, // General information out
|
|
|
|
|
EC_FATAL, // Kill the program
|
2020-03-15 13:09:51 +01:00
|
|
|
EC_FATALEXIT, // Kill the program, suppress with --quiet-exit
|
2019-05-19 22:13:13 +02:00
|
|
|
EC_FATALSRC, // Kill the program, for internal source errors
|
|
|
|
|
EC_ERROR, // General error out, can't suppress
|
2021-04-18 16:16:18 +02:00
|
|
|
EC_FIRST_NAMED, // Just a code so the program knows where to start info/errors
|
2019-05-19 22:13:13 +02:00
|
|
|
// Boolean information we track per-line, but aren't errors
|
2020-06-07 17:58:53 +02:00
|
|
|
I_CELLDEFINE, // Inside cell define from `celldefine/`endcelldefine
|
2019-05-19 22:13:13 +02:00
|
|
|
I_COVERAGE, // Coverage is on/off from /*verilator coverage_on/off*/
|
|
|
|
|
I_TRACING, // Tracing is on/off from /*verilator tracing_on/off*/
|
|
|
|
|
I_LINT, // All lint messages
|
2022-10-18 01:51:13 +02:00
|
|
|
I_UNUSED, // Unused genvar, parameter or signal message (Backward Compatibility)
|
2019-05-19 22:13:13 +02:00
|
|
|
I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE)
|
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
|
|
|
I_TIMING, // Enable timing from /*verilator timing_on/off*/
|
2019-05-19 22:13:13 +02:00
|
|
|
// Error codes:
|
2019-02-28 03:06:07 +01:00
|
|
|
E_PORTSHORT, // Error: Output port is connected to a constant, electrical short
|
2020-06-10 01:20:16 +02:00
|
|
|
E_UNSUPPORTED, // Error: Unsupported (generally)
|
2019-02-28 03:06:07 +01:00
|
|
|
E_TASKNSVAR, // Error: Task I/O not simple
|
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
|
|
|
E_NEEDTIMINGOPT, // Error: --timing/--no-timing option not specified
|
|
|
|
|
E_NOTIMING, // Timing control encountered with --no-timing
|
2019-05-19 22:13:13 +02:00
|
|
|
//
|
|
|
|
|
// Warning codes:
|
|
|
|
|
EC_FIRST_WARN, // Just a code so the program knows where to start warnings
|
|
|
|
|
//
|
|
|
|
|
ALWCOMBORDER, // Always_comb with unordered statements
|
2023-03-21 01:44:11 +01:00
|
|
|
ASCRANGE, // Ascending bit range vector
|
2019-05-19 22:13:13 +02:00
|
|
|
ASSIGNDLY, // Assignment delays
|
|
|
|
|
ASSIGNIN, // Assigning to input
|
2021-04-27 00:16:24 +02:00
|
|
|
BADSTDPRAGMA, // Any error related to pragmas
|
2019-05-19 22:13:13 +02:00
|
|
|
BLKANDNBLK, // Blocked and non-blocking assignments to same variable
|
|
|
|
|
BLKLOOPINIT, // Delayed assignment to array inside for loops
|
|
|
|
|
BLKSEQ, // Blocking assignments in sequential block
|
|
|
|
|
BSSPACE, // Backslash space
|
|
|
|
|
CASEINCOMPLETE, // Case statement has missing values
|
|
|
|
|
CASEOVERLAP, // Case statements overlap
|
|
|
|
|
CASEWITHX, // Case with X values
|
|
|
|
|
CASEX, // Casex
|
2020-12-06 04:58:36 +01:00
|
|
|
CASTCONST, // Cast is constant
|
2023-02-14 04:49:51 +01:00
|
|
|
CDCRSTLOGIC, // Logic in async reset path. Historical, never issued.
|
2022-05-15 17:03:32 +02:00
|
|
|
CLKDATA, // Clock used as data. Historical, never issued.
|
2019-05-19 22:13:13 +02:00
|
|
|
CMPCONST, // Comparison is constant due to limited range
|
|
|
|
|
COLONPLUS, // :+ instead of +:
|
2018-11-26 23:58:18 +01:00
|
|
|
COMBDLY, // Combinatorial delayed assignment
|
2023-04-06 03:27:37 +02:00
|
|
|
CONSTRAINTIGN, // Constraint ignored
|
2018-12-01 16:12:10 +01:00
|
|
|
CONTASSREG, // Continuous assignment on reg
|
2018-11-26 23:58:18 +01:00
|
|
|
DECLFILENAME, // Declaration doesn't match filename
|
2022-11-19 02:58:24 +01:00
|
|
|
DEFPARAM, // Style: Defparam
|
2020-01-03 17:27:51 +01:00
|
|
|
DEPRECATED, // Feature will be deprecated
|
2022-11-19 02:58:24 +01:00
|
|
|
ENCAPSULATED, // Error: local/protected violation
|
2019-05-19 22:13:13 +02:00
|
|
|
ENDLABEL, // End lable name mismatch
|
2022-11-19 02:58:24 +01:00
|
|
|
ENUMVALUE, // Error: enum type needs explicit cast
|
2021-03-15 02:23:48 +01:00
|
|
|
EOFNEWLINE, // End-of-file missing newline
|
2022-05-15 17:03:32 +02:00
|
|
|
GENCLK, // Generated Clock. Historical, never issued.
|
2020-08-15 15:43:53 +02:00
|
|
|
HIERBLOCK, // Ignored hierarchical block setting
|
2019-05-19 22:13:13 +02:00
|
|
|
IFDEPTH, // If statements too deep
|
2019-09-09 13:50:21 +02:00
|
|
|
IGNOREDRETURN, // Ignoring return value (function as task)
|
2022-05-15 17:03:32 +02:00
|
|
|
IMPERFECTSCH, // Imperfect schedule (disabled by default). Historical, never issued.
|
2018-11-29 00:25:34 +01:00
|
|
|
IMPLICIT, // Implicit wire
|
2023-01-05 23:42:05 +01:00
|
|
|
IMPLICITSTATIC, // Implicit static function
|
2018-11-29 00:25:34 +01:00
|
|
|
IMPORTSTAR, // Import::* in $unit
|
|
|
|
|
IMPURE, // Impure function not being inlined
|
2019-05-19 22:13:13 +02:00
|
|
|
INCABSPATH, // Include has absolute path
|
2017-12-27 03:35:08 +01:00
|
|
|
INFINITELOOP, // Infinite loop
|
2019-05-19 22:13:13 +02:00
|
|
|
INITIALDLY, // Initial delayed statement
|
2019-10-06 19:24:21 +02:00
|
|
|
INSECURE, // Insecure options
|
2021-01-05 20:26:01 +01:00
|
|
|
LATCH, // Latch detected outside of always_latch block
|
2023-03-21 01:44:11 +01:00
|
|
|
LITENDIAN, // Little endian, renamed to ASCRANGE
|
2022-11-19 02:58:24 +01:00
|
|
|
MINTYPMAXDLY, // Unsupported: min/typ/max delay expressions
|
2019-05-19 22:13:13 +02:00
|
|
|
MODDUP, // Duplicate module
|
|
|
|
|
MULTIDRIVEN, // Driven from multiple blocks
|
2019-06-30 22:46:48 +02:00
|
|
|
MULTITOP, // Multiple top level modules
|
2021-01-05 20:26:01 +01:00
|
|
|
NOLATCH, // No latch detected in always_latch block
|
2021-04-09 16:39:46 +02:00
|
|
|
NULLPORT, // Null port detected in module definition
|
2021-04-02 00:17:42 +02:00
|
|
|
PINCONNECTEMPTY,// Cell pin connected by name with empty reference
|
2019-05-19 22:13:13 +02:00
|
|
|
PINMISSING, // Cell pin not specified
|
|
|
|
|
PINNOCONNECT, // Cell pin not connected
|
2021-04-02 00:17:42 +02:00
|
|
|
PINNOTFOUND, // instance port name not found in it's module
|
2020-08-23 01:42:21 +02:00
|
|
|
PKGNODECL, // Error: Package/class needs to be predeclared
|
2018-11-26 23:58:18 +01:00
|
|
|
PROCASSWIRE, // Procedural assignment on wire
|
2021-09-27 04:51:11 +02:00
|
|
|
PROFOUTOFDATE, // Profile data out of date
|
2021-04-27 00:16:24 +02:00
|
|
|
PROTECTED, // detected `pragma protected
|
2020-12-10 01:17:30 +01:00
|
|
|
RANDC, // Unsupported: 'randc' converted to 'rand'
|
2018-11-26 23:58:18 +01:00
|
|
|
REALCVT, // Real conversion
|
2019-05-19 22:13:13 +02:00
|
|
|
REDEFMACRO, // Redefining existing define macro
|
2022-11-19 02:58:24 +01:00
|
|
|
RISEFALLDLY, // Unsupported: rise/fall/turn-off delays
|
2019-05-19 22:13:13 +02:00
|
|
|
SELRANGE, // Selection index out of range
|
2019-11-23 14:34:40 +01:00
|
|
|
SHORTREAL, // Shortreal not supported
|
2020-02-29 01:15:08 +01:00
|
|
|
SPLITVAR, // Cannot split the variable
|
2023-03-17 12:48:41 +01:00
|
|
|
STATICVAR, // Static variable declared in a loop with a declaration assignment
|
2019-05-19 22:13:13 +02:00
|
|
|
STMTDLY, // Delayed statement
|
|
|
|
|
SYMRSVDWORD, // Symbol is Reserved Word
|
|
|
|
|
SYNCASYNCNET, // Mixed sync + async reset
|
2018-09-23 21:09:47 +02:00
|
|
|
TICKCOUNT, // Too large tick count
|
2020-04-16 01:39:03 +02:00
|
|
|
TIMESCALEMOD, // Need timescale for module
|
2019-05-19 22:13:13 +02:00
|
|
|
UNDRIVEN, // No drivers
|
2022-05-15 17:03:32 +02:00
|
|
|
UNOPT, // Unoptimizable block. Historical, never issued.
|
2019-05-19 22:13:13 +02:00
|
|
|
UNOPTFLAT, // Unoptimizable block after flattening
|
2018-07-22 18:09:27 +02:00
|
|
|
UNOPTTHREADS, // Thread partitioner unable to fill all requested threads
|
2019-05-19 22:13:13 +02:00
|
|
|
UNPACKED, // Unsupported unpacked
|
|
|
|
|
UNSIGNED, // Comparison is constant due to unsigned arithmetic
|
2022-10-18 01:51:13 +02:00
|
|
|
UNUSEDGENVAR, // No receivers for genvar
|
|
|
|
|
UNUSEDPARAM, // No receivers for parameters
|
|
|
|
|
UNUSEDSIGNAL, // No receivers for signals
|
2019-05-19 22:13:13 +02:00
|
|
|
USERERROR, // Elaboration time $error
|
|
|
|
|
USERFATAL, // Elaboration time $fatal
|
|
|
|
|
USERINFO, // Elaboration time $info
|
|
|
|
|
USERWARN, // Elaboration time $warning
|
|
|
|
|
VARHIDDEN, // Hiding variable
|
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
|
|
|
WAITCONST, // Wait condition is constant
|
2019-05-19 22:13:13 +02:00
|
|
|
WIDTH, // Width mismatch
|
2023-02-03 00:25:25 +01:00
|
|
|
WIDTHTRUNC, // Width mismatch- lhs < rhs
|
|
|
|
|
WIDTHEXPAND, // Width mismatch- lhs > rhs
|
|
|
|
|
WIDTHXZEXPAND, // Width mismatch- lhs > rhs xz filled
|
2019-05-19 22:13:13 +02:00
|
|
|
WIDTHCONCAT, // Unsized numbers/parameters in concatenations
|
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
|
|
|
ZERODLY, // #0 delay
|
2019-05-19 22:13:13 +02:00
|
|
|
_ENUM_MAX
|
|
|
|
|
// ***Add new elements below also***
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format on
|
2006-08-26 13:35:28 +02:00
|
|
|
enum en m_e;
|
2022-09-16 14:17:38 +02:00
|
|
|
V3ErrorCode()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{EC_MIN} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2022-09-23 11:57:01 +02:00
|
|
|
constexpr V3ErrorCode(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2018-08-25 15:52:45 +02:00
|
|
|
explicit V3ErrorCode(const char* msgp); // Matching code or ERROR
|
2022-09-16 14:17:38 +02:00
|
|
|
explicit V3ErrorCode(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2022-10-18 23:07:09 +02:00
|
|
|
constexpr operator en() const VL_MT_SAFE { return m_e; }
|
|
|
|
|
const char* ascii() const VL_MT_SAFE {
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format off
|
2020-05-29 03:04:36 +02:00
|
|
|
static const char* const names[] = {
|
2019-05-19 22:13:13 +02:00
|
|
|
// Leading spaces indicate it can't be disabled.
|
2021-04-18 16:16:18 +02:00
|
|
|
" MIN", " INFO", " FATAL", " FATALEXIT", " FATALSRC", " ERROR", " FIRST_NAMED",
|
2019-05-19 22:13:13 +02:00
|
|
|
// Boolean
|
2022-10-18 01:51:13 +02:00
|
|
|
" I_CELLDEFINE", " I_COVERAGE", " I_TRACING", " I_LINT", " I_UNUSED", " I_DEF_NETTYPE_WIRE", " I_TIMING",
|
2019-02-28 03:06:07 +01:00
|
|
|
// Errors
|
2022-11-19 02:58:24 +01:00
|
|
|
"PORTSHORT", "UNSUPPORTED", "TASKNSVAR", "NEEDTIMINGOPT", "NOTIMING",
|
2019-02-28 03:06:07 +01:00
|
|
|
// Warnings
|
2019-05-19 22:13:13 +02:00
|
|
|
" EC_FIRST_WARN",
|
2023-03-21 01:44:11 +01:00
|
|
|
"ALWCOMBORDER", "ASCRANGE", "ASSIGNDLY", "ASSIGNIN", "BADSTDPRAGMA",
|
2019-05-19 22:13:13 +02:00
|
|
|
"BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE",
|
2020-12-06 04:58:36 +01:00
|
|
|
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST", "CDCRSTLOGIC", "CLKDATA",
|
2023-04-06 03:27:37 +02:00
|
|
|
"CMPCONST", "COLONPLUS", "COMBDLY", "CONSTRAINTIGN", "CONTASSREG",
|
2022-11-19 02:58:24 +01:00
|
|
|
"DECLFILENAME", "DEFPARAM", "DEPRECATED",
|
|
|
|
|
"ENCAPSULATED", "ENDLABEL", "ENUMVALUE", "EOFNEWLINE", "GENCLK", "HIERBLOCK",
|
2019-03-10 19:57:01 +01:00
|
|
|
"IFDEPTH", "IGNOREDRETURN",
|
2023-01-05 23:42:05 +01:00
|
|
|
"IMPERFECTSCH", "IMPLICIT", "IMPLICITSTATIC", "IMPORTSTAR", "IMPURE",
|
2019-10-06 19:24:21 +02:00
|
|
|
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
|
2022-11-19 02:58:24 +01:00
|
|
|
"LATCH", "LITENDIAN", "MINTYPMAXDLY", "MODDUP",
|
2023-02-03 14:47:55 +01:00
|
|
|
"MULTIDRIVEN", "MULTITOP", "NOLATCH", "NULLPORT", "PINCONNECTEMPTY",
|
2021-04-02 00:17:42 +02:00
|
|
|
"PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PROCASSWIRE",
|
2022-11-19 02:58:24 +01:00
|
|
|
"PROFOUTOFDATE", "PROTECTED", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY",
|
2023-03-17 12:48:41 +01:00
|
|
|
"SELRANGE", "SHORTREAL", "SPLITVAR", "STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
2020-04-16 01:39:03 +02:00
|
|
|
"TICKCOUNT", "TIMESCALEMOD",
|
2019-12-15 03:39:47 +01:00
|
|
|
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
|
2022-10-18 01:51:13 +02:00
|
|
|
"UNPACKED", "UNSIGNED", "UNUSEDGENVAR", "UNUSEDPARAM", "UNUSEDSIGNAL",
|
2019-05-19 22:13:13 +02:00
|
|
|
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
|
2023-02-03 00:25:25 +01:00
|
|
|
"VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHTRUNC", "WIDTHEXPAND", "WIDTHXZEXPAND", "WIDTHCONCAT", "ZERODLY",
|
2019-05-19 22:13:13 +02:00
|
|
|
" MAX"
|
|
|
|
|
};
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format on
|
2019-05-19 22:13:13 +02:00
|
|
|
return names[m_e];
|
2009-07-22 20:38:20 +02:00
|
|
|
}
|
2008-08-05 19:41:53 +02:00
|
|
|
// Warnings that default to off
|
2022-10-18 23:07:09 +02:00
|
|
|
bool defaultsOff() const VL_MT_SAFE {
|
2020-06-07 17:58:53 +02:00
|
|
|
return (m_e == IMPERFECTSCH || m_e == I_CELLDEFINE || styleError());
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
// Warnings that warn about nasty side effects
|
2022-10-18 23:07:09 +02:00
|
|
|
bool dangerous() const VL_MT_SAFE { return (m_e == COMBDLY); }
|
2006-10-11 17:41:42 +02:00
|
|
|
// Warnings we'll present to the user as errors
|
|
|
|
|
// Later -Werror- options may make more of these.
|
2022-10-18 23:07:09 +02:00
|
|
|
bool pretendError() const VL_MT_SAFE {
|
2021-04-27 00:16:24 +02:00
|
|
|
return (m_e == ASSIGNIN || m_e == BADSTDPRAGMA || m_e == BLKANDNBLK || m_e == BLKLOOPINIT
|
2022-11-19 02:58:24 +01:00
|
|
|
|| m_e == CONTASSREG || m_e == ENCAPSULATED || m_e == ENDLABEL || m_e == ENUMVALUE
|
|
|
|
|
|| m_e == IMPURE || m_e == PINNOTFOUND || m_e == PKGNODECL
|
|
|
|
|
|| m_e == PROCASSWIRE // Says IEEE
|
2023-03-13 02:28:14 +01:00
|
|
|
);
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2009-07-22 20:38:20 +02:00
|
|
|
// Warnings to mention manual
|
2022-10-18 23:07:09 +02:00
|
|
|
bool mentionManual() const VL_MT_SAFE {
|
2023-03-13 02:28:14 +01:00
|
|
|
return (m_e == EC_FATALSRC || m_e == SYMRSVDWORD || m_e == ZERODLY || pretendError());
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2007-10-31 22:17:23 +01:00
|
|
|
// Warnings that are lint only
|
2022-10-18 23:07:09 +02:00
|
|
|
bool lintError() const VL_MT_SAFE {
|
2023-03-21 01:44:11 +01:00
|
|
|
return (m_e == ALWCOMBORDER || m_e == ASCRANGE || m_e == BSSPACE || m_e == CASEINCOMPLETE
|
2020-12-06 04:58:36 +01:00
|
|
|
|| m_e == CASEOVERLAP || m_e == CASEWITHX || m_e == CASEX || m_e == CASTCONST
|
2023-01-05 23:42:05 +01:00
|
|
|
|| m_e == CMPCONST || m_e == COLONPLUS || m_e == IMPLICIT || m_e == IMPLICITSTATIC
|
2023-03-21 01:44:11 +01:00
|
|
|
|| m_e == LATCH || m_e == PINMISSING || m_e == REALCVT || m_e == STATICVAR
|
|
|
|
|
|| m_e == UNSIGNED || m_e == WIDTH || m_e == WIDTHTRUNC || m_e == WIDTHEXPAND
|
|
|
|
|
|| m_e == WIDTHXZEXPAND);
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2010-12-25 21:13:56 +01:00
|
|
|
// Warnings that are style only
|
2022-10-18 23:07:09 +02:00
|
|
|
bool styleError() const VL_MT_SAFE {
|
2020-04-15 13:58:34 +02:00
|
|
|
return (m_e == ASSIGNDLY // More than style, but for backward compatibility
|
2021-03-15 02:23:48 +01:00
|
|
|
|| m_e == BLKSEQ || m_e == DEFPARAM || m_e == DECLFILENAME || m_e == EOFNEWLINE
|
|
|
|
|
|| m_e == IMPORTSTAR || m_e == INCABSPATH || m_e == PINCONNECTEMPTY
|
2022-10-18 01:51:13 +02:00
|
|
|
|| m_e == PINNOCONNECT || m_e == SYNCASYNCNET || m_e == UNDRIVEN
|
|
|
|
|
|| m_e == UNUSEDGENVAR || m_e == UNUSEDPARAM || m_e == UNUSEDSIGNAL
|
2021-03-15 02:23:48 +01:00
|
|
|
|| m_e == VARHIDDEN);
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2022-10-18 01:51:13 +02:00
|
|
|
// Warnings that are unused only
|
2022-10-18 23:07:09 +02:00
|
|
|
bool unusedError() const VL_MT_SAFE {
|
2022-10-18 01:51:13 +02:00
|
|
|
return (m_e == UNUSEDGENVAR || m_e == UNUSEDPARAM || m_e == UNUSEDSIGNAL);
|
|
|
|
|
}
|
2023-02-03 00:25:25 +01:00
|
|
|
|
2023-03-09 03:32:37 +01:00
|
|
|
V3ErrorCode renamedTo() const {
|
|
|
|
|
// Return a new error this error has been renamed to
|
2023-03-21 01:44:11 +01:00
|
|
|
if (m_e == LITENDIAN) return V3ErrorCode{ASCRANGE};
|
2023-03-09 03:32:37 +01:00
|
|
|
return V3ErrorCode{EC_MIN}; // Not renamed; see isRenamed()
|
|
|
|
|
}
|
|
|
|
|
bool isRenamed() const { return renamedTo() != V3ErrorCode{EC_MIN}; }
|
2023-02-03 00:25:25 +01:00
|
|
|
bool isUnder(V3ErrorCode other) {
|
|
|
|
|
// backwards compatibility inheritance-like warnings
|
|
|
|
|
if (m_e == other) { return true; }
|
|
|
|
|
if (other == V3ErrorCode::WIDTH) {
|
2023-03-19 00:28:48 +01:00
|
|
|
return (m_e == WIDTHEXPAND || m_e == WIDTHTRUNC || m_e == WIDTHXZEXPAND);
|
2023-02-03 00:25:25 +01:00
|
|
|
}
|
|
|
|
|
if (other == V3ErrorCode::I_UNUSED) {
|
|
|
|
|
return (m_e == UNUSEDGENVAR || m_e == UNUSEDPARAM || m_e == UNUSEDSIGNAL);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-18 01:52:01 +02:00
|
|
|
static bool unusedMsg(const char* msgp) { return 0 == VL_STRCASECMP(msgp, "UNUSED"); }
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
2022-09-23 11:57:01 +02:00
|
|
|
constexpr bool operator==(const V3ErrorCode& lhs, const V3ErrorCode& rhs) {
|
2020-02-02 16:34:29 +01:00
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
2022-09-23 11:57:01 +02:00
|
|
|
constexpr bool operator==(const V3ErrorCode& lhs, V3ErrorCode::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
constexpr bool operator==(V3ErrorCode::en lhs, const V3ErrorCode& rhs) { return lhs == rhs.m_e; }
|
2020-02-02 16:34:29 +01:00
|
|
|
inline std::ostream& operator<<(std::ostream& os, const V3ErrorCode& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2022-09-23 11:57:01 +02:00
|
|
|
// ######################################################################
|
2023-02-10 04:15:37 +01:00
|
|
|
class V3ErrorGuarded final {
|
|
|
|
|
// Should only be used by V3ErrorGuarded::m_mutex is already locked
|
|
|
|
|
// contains guarded members
|
|
|
|
|
public:
|
2021-03-13 00:10:45 +01:00
|
|
|
using MessagesSet = std::set<std::string>;
|
|
|
|
|
using ErrorExitCb = void (*)(void);
|
2012-05-22 03:31:52 +02:00
|
|
|
|
2020-04-15 13:58:34 +02:00
|
|
|
private:
|
2020-08-16 20:19:12 +02:00
|
|
|
static constexpr unsigned MAX_ERRORS = 50; // Fatal after this may errors
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2023-02-10 04:15:37 +01:00
|
|
|
bool m_describedWarnings VL_GUARDED_BY(m_mutex) = false; // Told user how to disable warns
|
|
|
|
|
// Tell user to see manual, 0=not yet, 1=doit, 2=disable
|
|
|
|
|
int m_tellManual VL_GUARDED_BY(m_mutex) = 0;
|
|
|
|
|
V3ErrorCode m_errorCode VL_GUARDED_BY(m_mutex)
|
|
|
|
|
= V3ErrorCode::EC_FATAL; // Error string being formed will abort
|
|
|
|
|
bool m_errorSuppressed VL_GUARDED_BY(m_mutex)
|
|
|
|
|
= false; // Error being formed should be suppressed
|
|
|
|
|
MessagesSet m_messages VL_GUARDED_BY(m_mutex); // What errors we've outputted
|
|
|
|
|
ErrorExitCb m_errorExitCb VL_GUARDED_BY(m_mutex)
|
|
|
|
|
= nullptr; // Callback when error occurs for dumping
|
|
|
|
|
bool m_errorContexted VL_GUARDED_BY(m_mutex) = false; // Error being formed got context
|
|
|
|
|
int m_warnCount VL_GUARDED_BY(m_mutex) = 0; // Warning count
|
|
|
|
|
int m_errCount VL_GUARDED_BY(m_mutex) = 0; // Error count
|
|
|
|
|
// Pretend this warning is an error
|
|
|
|
|
std::array<bool, V3ErrorCode::_ENUM_MAX> m_pretendError VL_GUARDED_BY(m_mutex);
|
|
|
|
|
bool m_describedWeb VL_GUARDED_BY(m_mutex) = false; // Told user to see web
|
|
|
|
|
// Told user specifics about this warning
|
|
|
|
|
std::array<bool, V3ErrorCode::_ENUM_MAX> m_describedEachWarn VL_GUARDED_BY(m_mutex);
|
|
|
|
|
int m_debugDefault = 0; // Option: --debugi Default debugging level
|
|
|
|
|
int m_errorLimit VL_GUARDED_BY(m_mutex)
|
|
|
|
|
= MAX_ERRORS; // Option: --error-limit Number of errors before exit
|
|
|
|
|
bool m_warnFatal VL_GUARDED_BY(m_mutex) = true; // Option: --warnFatal Warnings are fatal
|
|
|
|
|
std::ostringstream m_errorStr VL_GUARDED_BY(m_mutex); // Error string being formed
|
|
|
|
|
public:
|
2023-04-11 13:23:24 +02:00
|
|
|
V3RecursiveMutex m_mutex; // Make sure only single thread is in class
|
2023-02-10 04:15:37 +01:00
|
|
|
|
|
|
|
|
string msgPrefix() VL_REQUIRES(m_mutex); // returns %Error/%Warn
|
|
|
|
|
string warnMore() VL_REQUIRES(m_mutex);
|
|
|
|
|
void execErrorExitCb() VL_REQUIRES(m_mutex) {
|
|
|
|
|
if (m_errorExitCb) m_errorExitCb();
|
|
|
|
|
}
|
|
|
|
|
void errorExitCb(ErrorExitCb cb) VL_REQUIRES(m_mutex) { m_errorExitCb = cb; }
|
|
|
|
|
ErrorExitCb errorExitCb() VL_REQUIRES(m_mutex) { return m_errorExitCb; }
|
|
|
|
|
bool isError(V3ErrorCode code, bool supp) VL_REQUIRES(m_mutex);
|
|
|
|
|
void vlAbortOrExit() VL_REQUIRES(m_mutex);
|
|
|
|
|
void errorContexted(bool flag) VL_REQUIRES(m_mutex) { m_errorContexted = flag; }
|
|
|
|
|
void incWarnings() VL_REQUIRES(m_mutex) { m_warnCount++; }
|
|
|
|
|
void incErrors() VL_REQUIRES(m_mutex) {
|
|
|
|
|
m_errCount++;
|
|
|
|
|
if (errorCount() == errorLimit()) { // Not >= as would otherwise recurse
|
|
|
|
|
v3errorEnd(
|
|
|
|
|
(v3errorPrep(V3ErrorCode::EC_FATALEXIT),
|
|
|
|
|
(v3errorStr() << "Exiting due to too many errors encountered; --error-limit="
|
|
|
|
|
<< errorCount() << endl),
|
|
|
|
|
v3errorStr()));
|
|
|
|
|
assert(0); // LCOV_EXCL_LINE
|
|
|
|
|
VL_UNREACHABLE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int errorCount() VL_REQUIRES(m_mutex) { return m_errCount; }
|
|
|
|
|
bool pretendError(int errorCode) VL_REQUIRES(m_mutex) { return m_pretendError[errorCode]; }
|
|
|
|
|
void pretendError(V3ErrorCode code, bool flag) VL_REQUIRES(m_mutex) {
|
|
|
|
|
if (code == V3ErrorCode::WIDTH) {
|
|
|
|
|
m_pretendError[V3ErrorCode::WIDTHTRUNC] = flag;
|
|
|
|
|
m_pretendError[V3ErrorCode::WIDTHEXPAND] = flag;
|
|
|
|
|
m_pretendError[V3ErrorCode::WIDTHXZEXPAND] = flag;
|
|
|
|
|
}
|
|
|
|
|
m_pretendError[code] = flag;
|
|
|
|
|
}
|
|
|
|
|
void debugDefault(int level) VL_MT_UNSAFE { m_debugDefault = level; }
|
|
|
|
|
int debugDefault() VL_MT_SAFE { return m_debugDefault; }
|
|
|
|
|
void errorLimit(int level) VL_REQUIRES(m_mutex) { m_errorLimit = level; }
|
|
|
|
|
int errorLimit() VL_REQUIRES(m_mutex) { return m_errorLimit; }
|
|
|
|
|
void warnFatal(bool flag) VL_REQUIRES(m_mutex) { m_warnFatal = flag; }
|
|
|
|
|
bool warnFatal() VL_REQUIRES(m_mutex) { return m_warnFatal; }
|
|
|
|
|
void v3errorPrep(V3ErrorCode code) VL_REQUIRES(m_mutex) {
|
|
|
|
|
m_errorStr.str("");
|
|
|
|
|
m_errorCode = code;
|
|
|
|
|
m_errorContexted = false;
|
|
|
|
|
m_errorSuppressed = false;
|
|
|
|
|
}
|
|
|
|
|
std::ostringstream& v3errorStr() VL_REQUIRES(m_mutex) { return m_errorStr; }
|
|
|
|
|
V3ErrorCode errorCode() VL_REQUIRES(m_mutex) { return m_errorCode; }
|
|
|
|
|
bool errorContexted() VL_REQUIRES(m_mutex) { return m_errorContexted; }
|
|
|
|
|
int warnCount() VL_REQUIRES(m_mutex) { return m_warnCount; }
|
|
|
|
|
bool errorSuppressed() VL_REQUIRES(m_mutex) { return m_errorSuppressed; }
|
|
|
|
|
void errorSuppressed(bool flag) VL_REQUIRES(m_mutex) { m_errorSuppressed = flag; }
|
|
|
|
|
bool describedWeb() VL_REQUIRES(m_mutex) { return m_describedWeb; }
|
|
|
|
|
void describedWeb(bool flag) VL_REQUIRES(m_mutex) { m_describedWeb = flag; }
|
|
|
|
|
bool describedEachWarn(V3ErrorCode code) VL_REQUIRES(m_mutex) {
|
|
|
|
|
return m_describedEachWarn[code];
|
|
|
|
|
}
|
|
|
|
|
void describedEachWarn(V3ErrorCode code, bool flag) VL_REQUIRES(m_mutex) {
|
|
|
|
|
m_describedEachWarn[code] = flag;
|
|
|
|
|
}
|
|
|
|
|
bool describedWarnings() VL_REQUIRES(m_mutex) { return m_describedWarnings; }
|
|
|
|
|
void describedWarnings(bool flag) VL_REQUIRES(m_mutex) { m_describedWarnings = flag; }
|
|
|
|
|
int tellManual() VL_REQUIRES(m_mutex) { return m_tellManual; }
|
|
|
|
|
void tellManual(int level) VL_REQUIRES(m_mutex) { m_tellManual = level; }
|
|
|
|
|
void v3errorEnd(std::ostringstream& sstr, const string& extra = "") VL_REQUIRES(m_mutex);
|
|
|
|
|
void suppressThisWarning() VL_REQUIRES(m_mutex);
|
|
|
|
|
string warnContextNone() VL_REQUIRES(m_mutex) {
|
|
|
|
|
errorContexted(true);
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ######################################################################
|
|
|
|
|
class V3Error final {
|
|
|
|
|
// Base class for any object that wants debugging and error reporting
|
|
|
|
|
private:
|
|
|
|
|
// CONSTRUCTORS
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Error() {
|
|
|
|
|
std::cerr << ("Static class");
|
2020-06-05 14:00:22 +02:00
|
|
|
V3Error::vlAbort();
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2020-04-15 13:58:34 +02:00
|
|
|
public:
|
2023-02-10 04:15:37 +01:00
|
|
|
static V3ErrorGuarded& s() VL_MT_SAFE { // Singleton
|
|
|
|
|
static V3ErrorGuarded s_s;
|
|
|
|
|
return s_s;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
// ACCESSORS
|
2023-02-10 04:15:37 +01:00
|
|
|
static void debugDefault(int level) VL_MT_UNSAFE { s().debugDefault(level); }
|
|
|
|
|
static int debugDefault() VL_MT_SAFE { return s().debugDefault(); }
|
|
|
|
|
static void errorLimit(int level) VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().errorLimit(level);
|
|
|
|
|
}
|
|
|
|
|
static int errorLimit() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
return s().errorLimit();
|
|
|
|
|
}
|
|
|
|
|
static void warnFatal(bool flag) VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().warnFatal(flag);
|
|
|
|
|
}
|
|
|
|
|
static bool warnFatal() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
return s().warnFatal();
|
|
|
|
|
}
|
|
|
|
|
// returns %Error/%Warn
|
|
|
|
|
static string msgPrefix() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
return s().msgPrefix();
|
|
|
|
|
}
|
|
|
|
|
static int errorCount() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
return s().errorCount();
|
|
|
|
|
}
|
|
|
|
|
static bool pretendError(int errorCode) VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
return s().pretendError(errorCode);
|
|
|
|
|
}
|
|
|
|
|
static int warnCount() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
return s().warnCount();
|
|
|
|
|
}
|
|
|
|
|
static bool errorContexted() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
return s().errorContexted();
|
|
|
|
|
}
|
|
|
|
|
static void errorContexted(bool flag) VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().errorContexted(flag);
|
|
|
|
|
}
|
|
|
|
|
static void describedEachWarn(V3ErrorCode code, bool flag) VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().describedEachWarn(code, flag);
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
// METHODS
|
2023-02-10 04:15:37 +01:00
|
|
|
static void incErrors() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().incErrors();
|
|
|
|
|
}
|
|
|
|
|
static void incWarnings() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().incWarnings();
|
|
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
static void init();
|
2020-04-15 13:58:34 +02:00
|
|
|
static void abortIfErrors() {
|
|
|
|
|
if (errorCount()) abortIfWarnings();
|
|
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
static void abortIfWarnings();
|
2023-02-10 04:15:37 +01:00
|
|
|
// Suppress next %Warn if user has it off
|
|
|
|
|
static void suppressThisWarning() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().suppressThisWarning();
|
|
|
|
|
}
|
|
|
|
|
static void pretendError(V3ErrorCode code, bool flag) VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().pretendError(code, flag);
|
|
|
|
|
}
|
|
|
|
|
static string lineStr(const char* filename, int lineno) VL_PURE;
|
|
|
|
|
static V3ErrorCode errorCode() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
return s().errorCode();
|
|
|
|
|
}
|
|
|
|
|
static void errorExitCb(V3ErrorGuarded::ErrorExitCb cb) VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().errorExitCb(cb);
|
2023-02-03 00:25:25 +01:00
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2012-05-22 03:24:17 +02:00
|
|
|
// When printing an error/warning, print prefix for multiline message
|
2023-02-10 04:15:37 +01:00
|
|
|
static string warnMore() VL_REQUIRES(s().m_mutex) { return s().warnMore(); }
|
|
|
|
|
// This function should only be used when it is impossible to
|
|
|
|
|
// generate whole error message inside v3warn macros and it needs to be
|
|
|
|
|
// streamed directly to cerr.
|
|
|
|
|
// Use with caution as this function isn't MT_SAFE.
|
|
|
|
|
static string warnMoreStandalone() VL_EXCLUDES(s().m_mutex) VL_MT_UNSAFE {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
return s().warnMore();
|
|
|
|
|
}
|
|
|
|
|
// This function marks place in error message from which point message
|
|
|
|
|
// should be printed after information on the error code.
|
|
|
|
|
// The post-processing is done in v3errorEnd function.
|
|
|
|
|
static string warnAdditionalInfo() VL_MT_SAFE { return "__WARNADDITIONALINFO__"; }
|
2019-07-14 21:06:49 +02:00
|
|
|
/// When building an error, don't show context info
|
2020-04-15 13:58:34 +02:00
|
|
|
static string warnContextNone() {
|
|
|
|
|
V3Error::errorContexted(true);
|
|
|
|
|
return "";
|
|
|
|
|
}
|
2012-05-22 03:24:17 +02:00
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
// Internals for v3error()/v3fatal() macros only
|
|
|
|
|
// Error end takes the string stream to output, be careful to seek() as needed
|
2023-02-10 04:15:37 +01:00
|
|
|
static void v3errorPrep(V3ErrorCode code) VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().v3errorPrep(code);
|
|
|
|
|
}
|
|
|
|
|
static std::ostringstream& v3errorStr() VL_MT_SAFE_EXCLUDES(s().m_mutex) {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
return s().v3errorStr();
|
|
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
static void vlAbort();
|
2020-04-15 13:58:34 +02:00
|
|
|
// static, but often overridden in classes.
|
2023-02-10 04:15:37 +01:00
|
|
|
static void v3errorEnd(std::ostringstream& sstr, const string& extra = "")
|
|
|
|
|
VL_MT_SAFE_EXCLUDES(s().m_mutex) VL_MT_SAFE {
|
2023-04-11 13:23:24 +02:00
|
|
|
const V3RecursiveLockGuard guard{s().m_mutex};
|
2023-02-10 04:15:37 +01:00
|
|
|
s().v3errorEnd(sstr, extra);
|
|
|
|
|
}
|
|
|
|
|
// We can't call 's().v3errorEnd' directly in 'v3ErrorEnd'/'v3errorEndFatal',
|
|
|
|
|
// due to bug in GCC (tested on 11.3.0 version with --enable-m32)
|
|
|
|
|
// causing internal error when backtrace is printed.
|
|
|
|
|
// Instead use this wrapper.
|
|
|
|
|
static void v3errorEndGuardedCall(std::ostringstream& sstr, const string& extra = "")
|
|
|
|
|
VL_REQUIRES(s().m_mutex) VL_MT_SAFE {
|
|
|
|
|
s().v3errorEnd(sstr, extra);
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Global versions, so that if the class doesn't define a operator, we get the functions anyways.
|
2023-02-10 04:15:37 +01:00
|
|
|
inline void v3errorEnd(std::ostringstream& sstr) VL_REQUIRES(V3Error::s().m_mutex) VL_MT_SAFE {
|
|
|
|
|
V3Error::v3errorEndGuardedCall(sstr);
|
|
|
|
|
}
|
|
|
|
|
inline void v3errorEndFatal(std::ostringstream& sstr)
|
|
|
|
|
VL_REQUIRES(V3Error::s().m_mutex) VL_MT_SAFE {
|
|
|
|
|
V3Error::v3errorEndGuardedCall(sstr);
|
2020-05-16 13:53:27 +02:00
|
|
|
assert(0); // LCOV_EXCL_LINE
|
2022-10-02 22:35:45 +02:00
|
|
|
VL_UNREACHABLE;
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2023-02-10 04:15:37 +01:00
|
|
|
#ifndef V3ERROR_NO_GLOBAL_
|
|
|
|
|
#define V3ErrorLockAndCheckStopRequested \
|
|
|
|
|
V3Error::s().m_mutex.lockCheckStopRequest( \
|
|
|
|
|
[]() -> void { V3ThreadPool::s().waitIfStopRequested(); })
|
|
|
|
|
#else
|
|
|
|
|
#define V3ErrorLockAndCheckStopRequested V3Error::s().m_mutex.lock()
|
|
|
|
|
#endif
|
|
|
|
|
|
2014-11-22 17:48:39 +01:00
|
|
|
// Theses allow errors using << operators: v3error("foo"<<"bar");
|
2006-08-26 13:35:28 +02:00
|
|
|
// Careful, you can't put () around msg, as you would in most macro definitions
|
2020-01-25 02:10:44 +01:00
|
|
|
// Note the commas are the comma operator, not separating arguments. These are needed to ensure
|
|
|
|
|
// evaluation order as otherwise we couldn't ensure v3errorPrep is called first.
|
2023-02-10 04:15:37 +01:00
|
|
|
// Note: due to limitations of clang thread-safety analysis, we can't use
|
|
|
|
|
// lock guard here, instead we are locking the mutex as first operation in temporary,
|
|
|
|
|
// but we are unlocking the mutex after function using comma operator.
|
|
|
|
|
// This way macros should also work when they are in 'if' stmt without '{}'.
|
2020-04-15 13:58:34 +02:00
|
|
|
#define v3warnCode(code, msg) \
|
2023-02-10 04:15:37 +01:00
|
|
|
v3errorEnd((V3ErrorLockAndCheckStopRequested, V3Error::s().v3errorPrep(code), \
|
|
|
|
|
(V3Error::s().v3errorStr() << msg), V3Error::s().v3errorStr())), \
|
|
|
|
|
V3Error::s().m_mutex.unlock()
|
2020-04-15 13:58:34 +02:00
|
|
|
#define v3warnCodeFatal(code, msg) \
|
2023-02-10 04:15:37 +01:00
|
|
|
v3errorEndFatal((V3ErrorLockAndCheckStopRequested, V3Error::s().v3errorPrep(code), \
|
|
|
|
|
(V3Error::s().v3errorStr() << msg), V3Error::s().v3errorStr())), \
|
|
|
|
|
V3Error::s().m_mutex.unlock()
|
2020-04-15 13:58:34 +02:00
|
|
|
#define v3warn(code, msg) v3warnCode(V3ErrorCode::code, msg)
|
|
|
|
|
#define v3info(msg) v3warnCode(V3ErrorCode::EC_INFO, msg)
|
2017-07-07 02:25:59 +02:00
|
|
|
#define v3error(msg) v3warnCode(V3ErrorCode::EC_ERROR, msg)
|
|
|
|
|
#define v3fatal(msg) v3warnCodeFatal(V3ErrorCode::EC_FATAL, msg)
|
2020-03-15 13:09:51 +01:00
|
|
|
// Use this instead of fatal() if message gets suppressed with --quiet-exit
|
|
|
|
|
#define v3fatalExit(msg) v3warnCodeFatal(V3ErrorCode::EC_FATALEXIT, msg)
|
2006-08-26 13:35:28 +02:00
|
|
|
// Use this instead of fatal() to mention the source code line.
|
2020-04-15 13:58:34 +02:00
|
|
|
#define v3fatalSrc(msg) \
|
|
|
|
|
v3warnCodeFatal(V3ErrorCode::EC_FATALSRC, \
|
|
|
|
|
__FILE__ << ":" << std::dec << __LINE__ << ": " << msg)
|
2018-07-15 02:44:43 +02:00
|
|
|
// Use this when normal v3fatal is called in static method that overrides fileline.
|
|
|
|
|
#define v3fatalStatic(msg) \
|
2023-02-10 04:15:37 +01:00
|
|
|
(::v3errorEndFatal((V3ErrorLockAndCheckStopRequested, \
|
|
|
|
|
V3Error::s().v3errorPrep(V3ErrorCode::EC_FATAL), \
|
|
|
|
|
(V3Error::s().v3errorStr() << msg), V3Error::s().v3errorStr()))), \
|
|
|
|
|
V3Error::s().m_mutex.unlock()
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2019-11-10 02:35:12 +01:00
|
|
|
#define UINFO(level, stmsg) \
|
2020-05-30 19:46:12 +02:00
|
|
|
do { \
|
2020-04-15 13:58:34 +02:00
|
|
|
if (VL_UNCOVERABLE(debug() >= (level))) { \
|
|
|
|
|
cout << "- " << V3Error::lineStr(__FILE__, __LINE__) << stmsg; \
|
|
|
|
|
} \
|
2020-05-30 19:46:12 +02:00
|
|
|
} while (false)
|
2019-11-10 02:35:12 +01:00
|
|
|
#define UINFONL(level, stmsg) \
|
2020-05-30 19:46:12 +02:00
|
|
|
do { \
|
2020-04-15 13:58:34 +02:00
|
|
|
if (VL_UNCOVERABLE(debug() >= (level))) { cout << stmsg; } \
|
2020-05-30 19:46:12 +02:00
|
|
|
} while (false)
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2017-03-31 23:46:15 +02:00
|
|
|
#ifdef VL_DEBUG
|
2020-04-15 13:58:34 +02:00
|
|
|
#define UDEBUGONLY(stmts) \
|
2020-05-30 19:46:12 +02:00
|
|
|
do { stmts } while (false)
|
2017-03-31 23:46:15 +02:00
|
|
|
#else
|
2020-04-15 13:58:34 +02:00
|
|
|
#define UDEBUGONLY(stmts) \
|
2020-05-30 19:46:12 +02:00
|
|
|
do { \
|
2020-04-15 13:58:34 +02:00
|
|
|
if (false) { stmts } \
|
2020-05-30 19:46:12 +02:00
|
|
|
} while (false)
|
2017-03-31 23:46:15 +02:00
|
|
|
#endif
|
|
|
|
|
|
2019-07-06 18:57:50 +02:00
|
|
|
// Assertion without object, generally UOBJASSERT preferred
|
2020-04-15 13:58:34 +02:00
|
|
|
#define UASSERT(condition, stmsg) \
|
|
|
|
|
do { \
|
2021-02-22 03:25:21 +01:00
|
|
|
if (VL_UNCOVERABLE(!(condition))) v3fatalSrc(stmsg); \
|
2020-04-15 13:58:34 +02:00
|
|
|
} while (false)
|
2019-07-06 18:57:50 +02:00
|
|
|
// Assertion with object
|
2020-04-15 13:58:34 +02:00
|
|
|
#define UASSERT_OBJ(condition, obj, stmsg) \
|
|
|
|
|
do { \
|
2021-02-22 03:25:21 +01:00
|
|
|
if (VL_UNCOVERABLE(!(condition))) (obj)->v3fatalSrc(stmsg); \
|
2020-04-15 13:58:34 +02:00
|
|
|
} while (false)
|
2006-08-26 13:35:28 +02:00
|
|
|
// For use in V3Ast static functions only
|
2020-04-15 13:58:34 +02:00
|
|
|
#define UASSERT_STATIC(condition, stmsg) \
|
|
|
|
|
do { \
|
|
|
|
|
if (VL_UNCOVERABLE(!(condition))) { \
|
|
|
|
|
std::cerr << "Internal Error: " << __FILE__ << ":" << std::dec << __LINE__ << ":" \
|
|
|
|
|
<< (stmsg) << std::endl; \
|
2020-06-05 14:00:22 +02:00
|
|
|
V3Error::vlAbort(); \
|
2020-04-15 13:58:34 +02:00
|
|
|
} \
|
|
|
|
|
} while (false)
|
2018-07-14 23:44:39 +02:00
|
|
|
// Check self test values for expected value. Safe from side-effects.
|
|
|
|
|
// Type argument can be removed when go to C++11 (use auto).
|
2020-04-15 13:58:34 +02:00
|
|
|
#define UASSERT_SELFTEST(Type, got, exp) \
|
|
|
|
|
do { \
|
|
|
|
|
Type g = (got); \
|
|
|
|
|
Type e = (exp); \
|
|
|
|
|
UASSERT(g == e, "Self-test failed '" #got "==" #exp "'" \
|
|
|
|
|
" got=" \
|
|
|
|
|
<< g << " expected=" << e); \
|
|
|
|
|
} while (false)
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2019-07-06 18:57:50 +02:00
|
|
|
#define V3ERROR_NA \
|
2020-04-04 04:31:54 +02:00
|
|
|
do { \
|
|
|
|
|
v3error("Internal: Unexpected Call"); \
|
|
|
|
|
v3fatalSrc("Unexpected Call"); \
|
|
|
|
|
} while (false)
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2020-04-05 16:26:53 +02:00
|
|
|
/// Throw fatal and return a value. The return value will never really be
|
|
|
|
|
/// needed, but required to avoid compiler error.
|
|
|
|
|
#define V3ERROR_NA_RETURN(value) \
|
|
|
|
|
V3ERROR_NA; \
|
|
|
|
|
return value
|
|
|
|
|
|
2022-09-18 21:53:42 +02:00
|
|
|
// Helper macros for VL_DEFINE_DEBUG_FUNCTIONS
|
2022-12-22 18:19:09 +01:00
|
|
|
// Takes an optional "name" (as __VA_ARGS__)
|
|
|
|
|
#define VL_DEFINE_DEBUG(...) \
|
2023-03-17 00:48:56 +01:00
|
|
|
VL_ATTR_UNUSED static int debug##__VA_ARGS__() VL_MT_SAFE { \
|
2018-05-14 12:50:47 +02:00
|
|
|
static int level = -1; \
|
2021-07-10 13:03:51 +02:00
|
|
|
if (VL_UNLIKELY(level < 0)) { \
|
2022-12-22 18:19:09 +01:00
|
|
|
std::string tag{VL_STRINGIFY(__VA_ARGS__)}; \
|
2022-09-18 21:53:42 +02:00
|
|
|
tag[0] = std::tolower(tag[0]); \
|
|
|
|
|
const unsigned debugTag = v3Global.opt.debugLevel(tag); \
|
|
|
|
|
const unsigned debugSrc = v3Global.opt.debugSrcLevel(__FILE__); \
|
|
|
|
|
const unsigned debugLevel = debugTag >= debugSrc ? debugTag : debugSrc; \
|
|
|
|
|
if (!v3Global.opt.available()) return static_cast<int>(debugLevel); \
|
|
|
|
|
level = static_cast<int>(debugLevel); \
|
2021-07-10 13:03:51 +02:00
|
|
|
} \
|
2018-05-14 12:50:47 +02:00
|
|
|
return level; \
|
2022-09-18 21:53:42 +02:00
|
|
|
} \
|
|
|
|
|
static_assert(true, "")
|
|
|
|
|
|
2022-12-22 18:19:09 +01:00
|
|
|
// Takes an optional "name" (as __VA_ARGS__)
|
|
|
|
|
#define VL_DEFINE_DUMP(...) \
|
|
|
|
|
VL_ATTR_UNUSED static int dump##__VA_ARGS__() { \
|
2022-09-18 21:53:42 +02:00
|
|
|
static int level = -1; \
|
|
|
|
|
if (VL_UNLIKELY(level < 0)) { \
|
2022-12-22 18:19:09 +01:00
|
|
|
std::string tag{VL_STRINGIFY(__VA_ARGS__)}; \
|
2022-09-18 21:53:42 +02:00
|
|
|
tag[0] = std::tolower(tag[0]); \
|
|
|
|
|
const unsigned dumpTag = v3Global.opt.dumpLevel(tag); \
|
|
|
|
|
const unsigned dumpSrc = v3Global.opt.dumpSrcLevel(__FILE__); \
|
|
|
|
|
const unsigned dumpLevel = dumpTag >= dumpSrc ? dumpTag : dumpSrc; \
|
|
|
|
|
if (!v3Global.opt.available()) return static_cast<int>(dumpLevel); \
|
|
|
|
|
level = static_cast<int>(dumpLevel); \
|
|
|
|
|
} \
|
|
|
|
|
return level; \
|
|
|
|
|
} \
|
|
|
|
|
static_assert(true, "")
|
|
|
|
|
|
|
|
|
|
// Define debug*() and dump*() routines. This needs to be added to every compilation unit so that
|
|
|
|
|
// --debugi-<tag/srcfile> and --dumpi-<tag/srcfile> can be used to control debug prints and dumping
|
|
|
|
|
#define VL_DEFINE_DEBUG_FUNCTIONS \
|
|
|
|
|
VL_DEFINE_DEBUG(); /* Define 'int debug()' */ \
|
|
|
|
|
VL_DEFINE_DUMP(); /* Define 'int dump()' */ \
|
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
|
|
|
VL_DEFINE_DUMP(Dfg); /* Define 'int dumpDfg()' */ \
|
2022-09-18 21:53:42 +02:00
|
|
|
VL_DEFINE_DUMP(Graph); /* Define 'int dumpGraph()' */ \
|
|
|
|
|
VL_DEFINE_DUMP(Tree); /* Define 'int dumpTree()' */ \
|
|
|
|
|
static_assert(true, "")
|
2018-05-14 12:50:47 +02:00
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
#endif // Guard
|