1 // -*- mode: C++; c-file-style: "cc-mode" -*-
2 //*************************************************************************
3 // DESCRIPTION: Verilator: Error handling
4 //
5 // Code available from: https://verilator.org
6 //
7 //*************************************************************************
8 //
9 // Copyright 2003-2021 by Wilson Snyder. This program is free software; you
10 // can redistribute it and/or modify it under the terms of either the GNU
11 // Lesser General Public License Version 3 or the Perl Artistic License
12 // Version 2.0.
13 // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
14 //
15 //*************************************************************************
16 
17 #ifndef VERILATOR_V3ERROR_H_
18 #define VERILATOR_V3ERROR_H_
19 
20 #include "config_build.h"
21 #include "verilatedos.h"
22 
23 // Limited V3 headers here - this is a base class for Vlc etc
24 #include "V3String.h"
25 
26 #include <array>
27 #include <bitset>
28 #include <cassert>
29 #include <deque>
30 #include <map>
31 #include <set>
32 #include <sstream>
33 
34 //######################################################################
35 
36 class V3ErrorCode final {
37 public:
38     // clang-format off
39     enum en: uint8_t  {
40         EC_MIN=0,       // Keep first
41         //
42         EC_INFO,        // General information out
43         EC_FATAL,       // Kill the program
44         EC_FATALEXIT,   // Kill the program, suppress with --quiet-exit
45         EC_FATALSRC,    // Kill the program, for internal source errors
46         EC_ERROR,       // General error out, can't suppress
47         EC_FIRST_NAMED,  // Just a code so the program knows where to start info/errors
48         // Boolean information we track per-line, but aren't errors
49         I_CELLDEFINE,   // Inside cell define from `celldefine/`endcelldefine
50         I_COVERAGE,     // Coverage is on/off from /*verilator coverage_on/off*/
51         I_TRACING,      // Tracing is on/off from /*verilator tracing_on/off*/
52         I_LINT,         // All lint messages
53         I_DEF_NETTYPE_WIRE,  // `default_nettype is WIRE (false=NONE)
54         // Error codes:
55         E_DETECTARRAY,  // Error: Unsupported: Can't detect changes on arrayed variable
56         E_ENCAPSULATED, // Error: local/protected violation
57         E_PORTSHORT,    // Error: Output port is connected to a constant, electrical short
58         E_UNSUPPORTED,  // Error: Unsupported (generally)
59         E_TASKNSVAR,    // Error: Task I/O not simple
60         //
61         // Warning codes:
62         EC_FIRST_WARN,  // Just a code so the program knows where to start warnings
63         //
64         ALWCOMBORDER,   // Always_comb with unordered statements
65         ASSIGNDLY,      // Assignment delays
66         ASSIGNIN,       // Assigning to input
67         BADSTDPRAGMA,   // Any error related to pragmas
68         BLKANDNBLK,     // Blocked and non-blocking assignments to same variable
69         BLKLOOPINIT,    // Delayed assignment to array inside for loops
70         BLKSEQ,         // Blocking assignments in sequential block
71         BSSPACE,        // Backslash space
72         CASEINCOMPLETE, // Case statement has missing values
73         CASEOVERLAP,    // Case statements overlap
74         CASEWITHX,      // Case with X values
75         CASEX,          // Casex
76         CASTCONST,      // Cast is constant
77         CDCRSTLOGIC,    // Logic in async reset path
78         CLKDATA,        // Clock used as data
79         CMPCONST,       // Comparison is constant due to limited range
80         COLONPLUS,      // :+ instead of +:
81         COMBDLY,        // Combinatorial delayed assignment
82         CONTASSREG,     // Continuous assignment on reg
83         DEFPARAM,       // Style: Defparam
84         DECLFILENAME,   // Declaration doesn't match filename
85         DEPRECATED,     // Feature will be deprecated
86         ENDLABEL,       // End lable name mismatch
87         EOFNEWLINE,     // End-of-file missing newline
88         GENCLK,         // Generated Clock
89         HIERBLOCK,      // Ignored hierarchical block setting
90         IFDEPTH,        // If statements too deep
91         IGNOREDRETURN,  // Ignoring return value (function as task)
92         IMPERFECTSCH,   // Imperfect schedule (disabled by default)
93         IMPLICIT,       // Implicit wire
94         IMPORTSTAR,     // Import::* in $unit
95         IMPURE,         // Impure function not being inlined
96         INCABSPATH,     // Include has absolute path
97         INFINITELOOP,   // Infinite loop
98         INITIALDLY,     // Initial delayed statement
99         INSECURE,       // Insecure options
100         LATCH,          // Latch detected outside of always_latch block
101         LITENDIAN,      // Little bit endian vector
102         MODDUP,         // Duplicate module
103         MULTIDRIVEN,    // Driven from multiple blocks
104         MULTITOP,       // Multiple top level modules
105         NOLATCH,        // No latch detected in always_latch block
106         NULLPORT,       // Null port detected in module definition
107         PINCONNECTEMPTY,// Cell pin connected by name with empty reference
108         PINMISSING,     // Cell pin not specified
109         PINNOCONNECT,   // Cell pin not connected
110         PINNOTFOUND,    // instance port name not found in it's module
111         PKGNODECL,      // Error: Package/class needs to be predeclared
112         PROCASSWIRE,    // Procedural assignment on wire
113         PROFOUTOFDATE,  // Profile data out of date
114         PROTECTED,      // detected `pragma protected
115         RANDC,          // Unsupported: 'randc' converted to 'rand'
116         REALCVT,        // Real conversion
117         REDEFMACRO,     // Redefining existing define macro
118         SELRANGE,       // Selection index out of range
119         SHORTREAL,      // Shortreal not supported
120         SPLITVAR,       // Cannot split the variable
121         STMTDLY,        // Delayed statement
122         SYMRSVDWORD,    // Symbol is Reserved Word
123         SYNCASYNCNET,   // Mixed sync + async reset
124         TICKCOUNT,      // Too large tick count
125         TIMESCALEMOD,   // Need timescale for module
126         UNDRIVEN,       // No drivers
127         UNOPT,          // Unoptimizable block
128         UNOPTFLAT,      // Unoptimizable block after flattening
129         UNOPTTHREADS,   // Thread partitioner unable to fill all requested threads
130         UNPACKED,       // Unsupported unpacked
131         UNSIGNED,       // Comparison is constant due to unsigned arithmetic
132         UNUSED,         // No receivers
133         USERERROR,      // Elaboration time $error
134         USERFATAL,      // Elaboration time $fatal
135         USERINFO,       // Elaboration time $info
136         USERWARN,       // Elaboration time $warning
137         VARHIDDEN,      // Hiding variable
138         WIDTH,          // Width mismatch
139         WIDTHCONCAT,    // Unsized numbers/parameters in concatenations
140         _ENUM_MAX
141         // ***Add new elements below also***
142     };
143     // clang-format on
144     enum en m_e;
V3ErrorCode()145     inline V3ErrorCode()
146         : m_e{EC_MIN} {}
147     // cppcheck-suppress noExplicitConstructor
V3ErrorCode(en _e)148     inline V3ErrorCode(en _e)
149         : m_e{_e} {}
150     explicit V3ErrorCode(const char* msgp);  // Matching code or ERROR
V3ErrorCode(int _e)151     explicit inline V3ErrorCode(int _e)
152         : m_e(static_cast<en>(_e)) {}  // Need () or GCC 4.8 false warning
en()153     operator en() const { return m_e; }
ascii()154     const char* ascii() const {
155         // clang-format off
156         static const char* const names[] = {
157             // Leading spaces indicate it can't be disabled.
158             " MIN", " INFO", " FATAL", " FATALEXIT", " FATALSRC", " ERROR", " FIRST_NAMED",
159             // Boolean
160             " I_CELLDEFINE", " I_COVERAGE", " I_TRACING", " I_LINT", " I_DEF_NETTYPE_WIRE",
161             // Errors
162             "DETECTARRAY", "ENCAPSULATED", "PORTSHORT", "UNSUPPORTED", "TASKNSVAR",
163             // Warnings
164             " EC_FIRST_WARN",
165             "ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN", "BADSTDPRAGMA",
166             "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE",
167             "CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST", "CDCRSTLOGIC", "CLKDATA",
168             "CMPCONST", "COLONPLUS", "COMBDLY", "CONTASSREG",
169             "DEFPARAM", "DECLFILENAME", "DEPRECATED",
170             "ENDLABEL", "EOFNEWLINE", "GENCLK", "HIERBLOCK",
171             "IFDEPTH", "IGNOREDRETURN",
172             "IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE",
173             "INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
174             "LATCH", "LITENDIAN", "MODDUP",
175             "MULTIDRIVEN", "MULTITOP","NOLATCH", "NULLPORT", "PINCONNECTEMPTY",
176             "PINMISSING", "PINNOCONNECT",  "PINNOTFOUND", "PKGNODECL", "PROCASSWIRE",
177             "PROFOUTOFDATE", "PROTECTED", "RANDC", "REALCVT", "REDEFMACRO",
178             "SELRANGE", "SHORTREAL", "SPLITVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
179             "TICKCOUNT", "TIMESCALEMOD",
180             "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
181             "UNPACKED", "UNSIGNED", "UNUSED",
182             "USERERROR", "USERFATAL", "USERINFO", "USERWARN",
183             "VARHIDDEN", "WIDTH", "WIDTHCONCAT",
184             " MAX"
185         };
186         // clang-format on
187         return names[m_e];
188     }
189     // Warnings that default to off
defaultsOff()190     bool defaultsOff() const {
191         return (m_e == IMPERFECTSCH || m_e == I_CELLDEFINE || styleError());
192     }
193     // Warnings that warn about nasty side effects
dangerous()194     bool dangerous() const { return (m_e == COMBDLY); }
195     // Warnings we'll present to the user as errors
196     // Later -Werror- options may make more of these.
pretendError()197     bool pretendError() const {
198         return (m_e == ASSIGNIN || m_e == BADSTDPRAGMA || m_e == BLKANDNBLK || m_e == BLKLOOPINIT
199                 || m_e == CONTASSREG || m_e == IMPURE || m_e == PINNOTFOUND || m_e == PKGNODECL
200                 || m_e == PROCASSWIRE);  // Says IEEE
201     }
202     // Warnings to mention manual
mentionManual()203     bool mentionManual() const {
204         return (m_e == EC_FATALSRC || m_e == SYMRSVDWORD || pretendError());
205     }
206     // Warnings that are lint only
lintError()207     bool lintError() const {
208         return (m_e == ALWCOMBORDER || m_e == BSSPACE || m_e == CASEINCOMPLETE
209                 || m_e == CASEOVERLAP || m_e == CASEWITHX || m_e == CASEX || m_e == CASTCONST
210                 || m_e == CMPCONST || m_e == COLONPLUS || m_e == ENDLABEL || m_e == IMPLICIT
211                 || m_e == LATCH || m_e == LITENDIAN || m_e == PINMISSING || m_e == REALCVT
212                 || m_e == UNSIGNED || m_e == WIDTH);
213     }
214     // Warnings that are style only
styleError()215     bool styleError() const {
216         return (m_e == ASSIGNDLY  // More than style, but for backward compatibility
217                 || m_e == BLKSEQ || m_e == DEFPARAM || m_e == DECLFILENAME || m_e == EOFNEWLINE
218                 || m_e == IMPORTSTAR || m_e == INCABSPATH || m_e == PINCONNECTEMPTY
219                 || m_e == PINNOCONNECT || m_e == SYNCASYNCNET || m_e == UNDRIVEN || m_e == UNUSED
220                 || m_e == VARHIDDEN);
221     }
222 };
223 inline bool operator==(const V3ErrorCode& lhs, const V3ErrorCode& rhs) {
224     return lhs.m_e == rhs.m_e;
225 }
226 inline bool operator==(const V3ErrorCode& lhs, V3ErrorCode::en rhs) { return lhs.m_e == rhs; }
227 inline bool operator==(V3ErrorCode::en lhs, const V3ErrorCode& rhs) { return lhs == rhs.m_e; }
228 inline std::ostream& operator<<(std::ostream& os, const V3ErrorCode& rhs) {
229     return os << rhs.ascii();
230 }
231 
232 //######################################################################
233 
234 class V3Error final {
235     // Base class for any object that wants debugging and error reporting
236 
237     using MessagesSet = std::set<std::string>;
238     using ErrorExitCb = void (*)(void);
239 
240 private:
241     static bool s_describedWarnings;  // Told user how to disable warns
242     static bool s_describedWeb;  // Told user to see web
243     static std::array<bool, V3ErrorCode::_ENUM_MAX>
244         s_describedEachWarn;  // Told user specifics about this warning
245     static std::array<bool, V3ErrorCode::_ENUM_MAX>
246         s_pretendError;  // Pretend this warning is an error
247     static int s_debugDefault;  // Option: --debugi Default debugging level
248     static int s_errorLimit;  // Option: --error-limit Number of errors before exit
249     static bool s_warnFatal;  // Option: --warnFatal Warnings are fatal
250     static int s_errCount;  // Error count
251     static int s_warnCount;  // Warning count
252     static int s_tellManual;  // Tell user to see manual, 0=not yet, 1=doit, 2=disable
253     static std::ostringstream s_errorStr;  // Error string being formed
254     static V3ErrorCode s_errorCode;  // Error string being formed will abort
255     static bool s_errorContexted;  // Error being formed got context
256     static bool s_errorSuppressed;  // Error being formed should be suppressed
257     static MessagesSet s_messages;  // What errors we've outputted
258     static ErrorExitCb s_errorExitCb;  // Callback when error occurs for dumping
259 
260     static constexpr unsigned MAX_ERRORS = 50;  // Fatal after this may errors
261 
V3Error()262     V3Error() {
263         std::cerr << ("Static class");
264         V3Error::vlAbort();
265     }
266 
267 public:
268     // CONSTRUCTORS
269     // ACCESSORS
debugDefault(int level)270     static void debugDefault(int level) { s_debugDefault = level; }
debugDefault()271     static int debugDefault() { return s_debugDefault; }
errorLimit(int level)272     static void errorLimit(int level) { s_errorLimit = level; }
errorLimit()273     static int errorLimit() { return s_errorLimit; }
warnFatal(bool flag)274     static void warnFatal(bool flag) { s_warnFatal = flag; }
warnFatal()275     static bool warnFatal() { return s_warnFatal; }
276     static string msgPrefix();  // returns %Error/%Warn
errorCount()277     static int errorCount() { return s_errCount; }
warnCount()278     static int warnCount() { return s_warnCount; }
errorContexted()279     static bool errorContexted() { return s_errorContexted; }
errorContexted(bool flag)280     static void errorContexted(bool flag) { s_errorContexted = flag; }
281     // METHODS
282     static void incErrors();
incWarnings()283     static void incWarnings() { s_warnCount++; }
284     static void init();
abortIfErrors()285     static void abortIfErrors() {
286         if (errorCount()) abortIfWarnings();
287     }
288     static void abortIfWarnings();
289     static void suppressThisWarning();  // Suppress next %Warn if user has it off
pretendError(V3ErrorCode code,bool flag)290     static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code] = flag; }
291     static bool isError(V3ErrorCode code, bool supp);
292     static string lineStr(const char* filename, int lineno);
errorCode()293     static V3ErrorCode errorCode() { return s_errorCode; }
errorExitCb(ErrorExitCb cb)294     static void errorExitCb(ErrorExitCb cb) { s_errorExitCb = cb; }
295 
296     // When printing an error/warning, print prefix for multiline message
297     static string warnMore();
298     /// When building an error, don't show context info
warnContextNone()299     static string warnContextNone() {
300         V3Error::errorContexted(true);
301         return "";
302     }
303 
304     // Internals for v3error()/v3fatal() macros only
305     // Error end takes the string stream to output, be careful to seek() as needed
v3errorPrep(V3ErrorCode code)306     static void v3errorPrep(V3ErrorCode code) {
307         s_errorStr.str("");
308         s_errorCode = code;
309         s_errorContexted = false;
310         s_errorSuppressed = false;
311     }
v3errorStr()312     static std::ostringstream& v3errorStr() { return s_errorStr; }
313     static void vlAbortOrExit();
314     static void vlAbort();
315     // static, but often overridden in classes.
316     static void v3errorEnd(std::ostringstream& sstr, const string& locationStr = "");
317 };
318 
319 // Global versions, so that if the class doesn't define a operator, we get the functions anyways.
debug()320 inline int debug() { return V3Error::debugDefault(); }
v3errorEnd(std::ostringstream & sstr)321 inline void v3errorEnd(std::ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
v3errorEndFatal(std::ostringstream & sstr)322 inline void v3errorEndFatal(std::ostringstream& sstr) {
323     V3Error::v3errorEnd(sstr);
324     assert(0);  // LCOV_EXCL_LINE
325     VL_UNREACHABLE
326 }
327 
328 // Theses allow errors using << operators: v3error("foo"<<"bar");
329 // Careful, you can't put () around msg, as you would in most macro definitions
330 // Note the commas are the comma operator, not separating arguments. These are needed to ensure
331 // evaluation order as otherwise we couldn't ensure v3errorPrep is called first.
332 #define v3warnCode(code, msg) \
333     v3errorEnd((V3Error::v3errorPrep(code), (V3Error::v3errorStr() << msg), V3Error::v3errorStr()))
334 #define v3warnCodeFatal(code, msg) \
335     v3errorEndFatal( \
336         (V3Error::v3errorPrep(code), (V3Error::v3errorStr() << msg), V3Error::v3errorStr()))
337 #define v3warn(code, msg) v3warnCode(V3ErrorCode::code, msg)
338 #define v3info(msg) v3warnCode(V3ErrorCode::EC_INFO, msg)
339 #define v3error(msg) v3warnCode(V3ErrorCode::EC_ERROR, msg)
340 #define v3fatal(msg) v3warnCodeFatal(V3ErrorCode::EC_FATAL, msg)
341 // Use this instead of fatal() if message gets suppressed with --quiet-exit
342 #define v3fatalExit(msg) v3warnCodeFatal(V3ErrorCode::EC_FATALEXIT, msg)
343 // Use this instead of fatal() to mention the source code line.
344 #define v3fatalSrc(msg) \
345     v3warnCodeFatal(V3ErrorCode::EC_FATALSRC, \
346                     __FILE__ << ":" << std::dec << __LINE__ << ": " << msg)
347 // Use this when normal v3fatal is called in static method that overrides fileline.
348 #define v3fatalStatic(msg) \
349     (::v3errorEndFatal((V3Error::v3errorPrep(V3ErrorCode::EC_FATAL), \
350                         (V3Error::v3errorStr() << msg), V3Error::v3errorStr())))
351 
352 #define UINFO(level, stmsg) \
353     do { \
354         if (VL_UNCOVERABLE(debug() >= (level))) { \
355             cout << "- " << V3Error::lineStr(__FILE__, __LINE__) << stmsg; \
356         } \
357     } while (false)
358 #define UINFONL(level, stmsg) \
359     do { \
360         if (VL_UNCOVERABLE(debug() >= (level))) { cout << stmsg; } \
361     } while (false)
362 
363 #ifdef VL_DEBUG
364 #define UDEBUGONLY(stmts) \
365     do { stmts } while (false)
366 #else
367 #define UDEBUGONLY(stmts) \
368     do { \
369         if (false) { stmts } \
370     } while (false)
371 #endif
372 
373 // Assertion without object, generally UOBJASSERT preferred
374 #define UASSERT(condition, stmsg) \
375     do { \
376         if (VL_UNCOVERABLE(!(condition))) v3fatalSrc(stmsg); \
377     } while (false)
378 // Assertion with object
379 #define UASSERT_OBJ(condition, obj, stmsg) \
380     do { \
381         if (VL_UNCOVERABLE(!(condition))) (obj)->v3fatalSrc(stmsg); \
382     } while (false)
383 // For use in V3Ast static functions only
384 #define UASSERT_STATIC(condition, stmsg) \
385     do { \
386         if (VL_UNCOVERABLE(!(condition))) { \
387             std::cerr << "Internal Error: " << __FILE__ << ":" << std::dec << __LINE__ << ":" \
388                       << (stmsg) << std::endl; \
389             V3Error::vlAbort(); \
390         } \
391     } while (false)
392 // Check self test values for expected value.  Safe from side-effects.
393 // Type argument can be removed when go to C++11 (use auto).
394 #define UASSERT_SELFTEST(Type, got, exp) \
395     do { \
396         Type g = (got); \
397         Type e = (exp); \
398         UASSERT(g == e, "Self-test failed '" #got "==" #exp "'" \
399                         " got=" \
400                             << g << " expected=" << e); \
401     } while (false)
402 
403 #define V3ERROR_NA \
404     do { \
405         v3error("Internal: Unexpected Call"); \
406         v3fatalSrc("Unexpected Call"); \
407     } while (false)
408 
409 /// Throw fatal and return a value. The return value will never really be
410 /// needed, but required to avoid compiler error.
411 #define V3ERROR_NA_RETURN(value) \
412     V3ERROR_NA; \
413     return value
414 
415 /// Declare a convenience debug() routine that may be added to any class in
416 /// Verilator so that --debugi-<srcfile> will work to control UINFOs in
417 /// that class:
418 #define VL_DEBUG_FUNC \
419     static int debug() { \
420         static int level = -1; \
421         if (VL_UNLIKELY(level < 0)) { \
422             const int debugSrcLevel = v3Global.opt.debugSrcLevel(__FILE__); \
423             if (!v3Global.opt.available()) return debugSrcLevel; \
424             level = debugSrcLevel; \
425         } \
426         return level; \
427     }
428 
429 //----------------------------------------------------------------------
430 
431 #endif  // Guard
432