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