blob: 26901cf1c99cf623b2d56f8a6c18fdb4837f08e6 [file] [log] [blame]
Eric Kunzee5e26762020-10-13 16:11:07 -07001
2// Copyright (c) 2020, ARM Limited.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#ifndef FUNC_DEBUG_H
17#define FUNC_DEBUG_H
18
19#include "debug_types.h"
20#include <assert.h>
21#include <cinttypes>
22#include <signal.h>
23#include <stdio.h>
24
25void func_print_backtrace(FILE* out, int sig = SIGABRT);
26
27void func_enable_signal_handlers();
28
29// Debug content container
30#define WARNING_BUFFER_SIZE 16
31#define WARNING_BUFFER_ENTRY_LENGTH 1024
32
33// STRINGIFY2 is needed expand expression passed to STRINGIFY
34#define STRINGIFY2(s) #s
35#define STRINGIFY(s) STRINGIFY2(s)
36
37// If TRACED_LOG is defined, add file:line to log messages
38#if defined(TRACED_LOG)
39#define WHERE "@" __FILE__ ":" STRINGIFY(__LINE__)
40#else
41#define WHERE
42#endif
43
44#if defined(COLORIZED_LOG)
45#define COL(col, fmt) "\x1b[3" col "m" fmt "\x1b[0m"
46#define COL_FATAL(fmt) COL("1;41", fmt)
47#define COL_WARN(fmt) COL("1;43", fmt)
48#define COL_INFO(fmt) COL("2", fmt)
49#define COL_IFACE(fmt) fmt
50#define COL_LOW(fmt) COL("35", fmt)
51#define COL_MED(fmt) COL("2;33", fmt)
52#define COL_HIGH(fmt) COL("2;32", fmt)
53#else
54#define COL_FATAL(fmt) fmt
55#define COL_WARN(fmt) fmt
56#define COL_INFO(fmt) fmt
57#define COL_IFACE(fmt) fmt
58#define COL_LOW(fmt) fmt
59#define COL_MED(fmt) fmt
60#define COL_HIGH(fmt) fmt
61#endif
62
63struct func_debug_t
64{
65 uint32_t func_debug_verbosity; // What verbosity level is set? (bitmask)
66 uint64_t func_debug_mask; // Which units have debugging enabled? (bitmask)
67 uint64_t func_debug_inst_mask; // Which instances have debugging enabled (bitmask)
68 uint64_t inst_id; // The instance id for multiple model instances
69 uint32_t func_suppress_arch_error_mask; // Which architecture error should be suppressed? (bitmask)
70 FILE* func_debug_file; // Output file
71 uint32_t record_warnings;
72 char* warning_buffer[WARNING_BUFFER_SIZE];
73 uint32_t warning_buffer_head; // next unread message
74 uint32_t warning_buffer_tail; // next message to write
75 uint32_t is_gzip;
76 bool is_output_unbuffered; // should log files be opened with unbuffered I/O.
77};
78
79#ifndef ASSERT
80#define ASSERT(COND) \
81 if (!(COND)) \
82 { \
83 fprintf(stderr, COL_FATAL("ASSERTION AT %s:%d %s(): (%s)\n"), __FILE__, __LINE__, __func__, #COND); \
84 func_print_backtrace(stderr); \
85 assert(COND); \
86 }
87#endif
88
89#ifndef ASSERT_MSG
90#define ASSERT_MSG(COND, fmt, ...) \
91 if (!(COND)) \
92 { \
93 fprintf(stderr, COL_FATAL("ASSERTION AT %s:%d %s(): (%s)\n"), __FILE__, __LINE__, __func__, #COND); \
94 fprintf(stderr, COL_FATAL(fmt) "\n", ##__VA_ARGS__); \
95 func_print_backtrace(stderr); \
96 assert(COND); \
97 }
98#endif
99
Kevin Chengacb550f2021-06-29 15:32:19 -0700100#ifndef REQUIRE
101#define REQUIRE(COND, fmt, ...) \
Eric Kunzee5e26762020-10-13 16:11:07 -0700102 if (!(COND)) \
103 { \
Kevin Chengacb550f2021-06-29 15:32:19 -0700104 fprintf(g_func_debug.func_debug_file, COL_FATAL("REQUIRE() fails AT %s:%d %s(): (%s)\n"), __FILE__, __LINE__, \
105 __func__, #COND); \
106 fprintf(g_func_debug.func_debug_file, COL_FATAL(fmt) "\n", ##__VA_ARGS__); \
107 this->parent_sgt->setGraphStatus(GraphStatus::TOSA_UNPREDICTABLE); \
108 }
109#endif
110
111#ifndef ERROR_IF
112#define ERROR_IF(COND, fmt, ...) \
113 if ((COND)) \
114 { \
115 if (this->parent_sgt->getGraphStatus() != GraphStatus::TOSA_UNPREDICTABLE) \
116 { \
117 this->parent_sgt->setGraphStatus(GraphStatus::TOSA_ERROR); \
118 } \
119 fprintf(g_func_debug.func_debug_file, COL_FATAL("ERROR_IF() fails AT %s:%d %s(): (%s)\n"), __FILE__, __LINE__, \
Eric Kunzee5e26762020-10-13 16:11:07 -0700120 __func__, #COND); \
121 fprintf(g_func_debug.func_debug_file, COL_FATAL(fmt) "\n", ##__VA_ARGS__); \
122 this->dumpNode(g_func_debug.func_debug_file); \
123 func_print_backtrace(g_func_debug.func_debug_file); \
Kevin Chengacb550f2021-06-29 15:32:19 -0700124 return 1; \
Eric Kunzee5e26762020-10-13 16:11:07 -0700125 }
126#endif
127
128// Assertion specific to allocating memory
129#ifndef ASSERT_MEM
130#define ASSERT_MEM(OBJ) \
131 if (!(OBJ)) \
132 { \
133 fprintf(stderr, COL_FATAL("ASSERTION AT %s:%d %s(): (" #OBJ "): out of memory\n"), __FILE__, __LINE__, \
134 __func__); \
135 func_print_backtrace(stderr); \
136 assert(OBJ); \
137 }
138#endif
139
140#ifndef FATAL_ERROR
141#define FATAL_ERROR(fmt, ...) \
142 fprintf(stderr, COL_FATAL("FATAL ERROR AT %s:%d %s():\n"), __FILE__, __LINE__, __func__); \
143 fprintf(stderr, COL_FATAL(fmt) "\n", ##__VA_ARGS__); \
144 func_print_backtrace(stderr); \
145 abort();
146#endif
147
Eric Kunzee5e26762020-10-13 16:11:07 -0700148#ifndef SIMPLE_FATAL_ERROR
149#define SIMPLE_FATAL_ERROR(fmt, ...) \
150 fprintf(stderr, COL_FATAL(fmt) "\n", ##__VA_ARGS__); \
151 exit(1);
152#endif
153
154void func_debug_warning(
155 func_debug_t* func_debug, const char* file, const char* func, const int line, const char* fmt, ...);
156#ifndef WARNING
157#define WARNING(...) func_debug_warning(&g_func_debug, __FILE__, __func__, __LINE__, __VA_ARGS__)
158#endif
159
160#ifndef WARNING_STDERR
161#define WARNING_STDERR(fmt, ...) \
162 fprintf(stderr, COL_WARN("WARNING AT %s:%d %s():\n"), __FILE__, __LINE__, __func__); \
163 fprintf(stderr, COL_WARN(fmt) "\n", ##__VA_ARGS__);
164#endif
165
166int func_debug_set_captured_warnings(func_debug_t* func_debug, uint32_t capture);
167
168int func_debug_has_captured_warning(func_debug_t* func_debug);
169
170int func_debug_get_captured_warning(func_debug_t* func_debug, char* buf_ptr, const uint32_t buf_len);
171
172// Is this debug verbosity and unit level enabled?
173// Provide compiler hints that this is unlikely
174// Two versions, depending on whether DEBUG_INSTANCE_EXPR is defined in a file or not
175//
176// For .cpp files whose units have discrete instance IDs, define DEBUG_INSTANCE_EXPR to evalute
177// to the instance ID variable. The use of this define in header files is discouraged.
178
179#ifdef DEBUG_INSTANCE_EXPR
180// Expression for whether the debugging verbosity + debugging unit is enabled for free-form printouts
181#ifdef DEBUG_INSTANCE_EXPR_2
182#define DEBUG_ENABLED(VERB, LEVEL) \
183 (__builtin_expect((g_func_debug.func_debug_mask == DEBUG_ALL || g_func_debug.func_debug_mask & (DEBUG_##LEVEL)) && \
184 (g_func_debug.func_debug_inst_mask & (uint64_t(1) << (DEBUG_INSTANCE_EXPR))) && \
185 (g_func_debug.func_debug_verbosity & (VERB)), \
186 0))
187// Debug printing macro
188#define DEBUG(VERB, LEVEL, FMT, ...) \
189 if (DEBUG_ENABLED(VERB, LEVEL)) \
190 { \
191 fprintf(g_func_debug.func_debug_file, "[%d:" #LEVEL "_%02d_%02d" WHERE "]: " FMT "\n", \
192 (int)g_func_debug.inst_id, (int)(DEBUG_INSTANCE_EXPR), (int)(DEBUG_INSTANCE_EXPR_2), ##__VA_ARGS__); \
193 }
194
195// Prints just the debugging prefix for properly marking free-form printouts
196#define DEBUG_PREFIX(LEVEL) \
197 fprintf(g_func_debug.func_debug_file, "[%d" #LEVEL "_%02d_%02d" WHERE "]: ", (int)g_func_debug.inst_id, \
198 (int)(DEBUG_INSTANCE_EXPR), (int)(DEBUG_INSTANCE_EXPR_2))
199
200#else // !DEBUG_INSTANCE_EXPR_2
201
202#define DEBUG_ENABLED(VERB, LEVEL) \
203 (__builtin_expect((g_func_debug.func_debug_mask == DEBUG_ALL || g_func_debug.func_debug_mask & (DEBUG_##LEVEL)) && \
204 (g_func_debug.func_debug_inst_mask & (uint64_t(1) << (DEBUG_INSTANCE_EXPR))) && \
205 (g_func_debug.func_debug_verbosity & (VERB)), \
206 0))
207// Debug printing macro
208#define DEBUG(VERB, LEVEL, FMT, ...) \
209 if (DEBUG_ENABLED(VERB, LEVEL)) \
210 { \
211 fprintf(g_func_debug.func_debug_file, "[%d:" #LEVEL "_%02d" WHERE "]: " FMT "\n", (int)g_func_debug.inst_id, \
212 (int)(DEBUG_INSTANCE_EXPR), ##__VA_ARGS__); \
213 }
214
215// Prints just the debugging prefix for properly marking free-form printouts
216#define DEBUG_PREFIX(LEVEL) \
217 fprintf(g_func_debug.func_debug_file, "[%d:" #LEVEL "_%02d" WHERE "]: ", (int)g_func_debug.inst_id, \
218 (int)(DEBUG_INSTANCE_EXPR))
219
220#endif // DEBUG_INSTANCE_EXPR_2
221
222#else // !DEBUG_INSTANCE_EXPR
223
224// Expression for whether the debugging verbosity + debugging unit is enabled for free-form printouts
225#define DEBUG_ENABLED(VERB, LEVEL) \
226 (__builtin_expect((g_func_debug.func_debug_mask == DEBUG_ALL || g_func_debug.func_debug_mask & (DEBUG_##LEVEL)) && \
227 (g_func_debug.func_debug_verbosity & (VERB)), \
228 0))
229// Debug printing macro
230#define DEBUG(VERB, LEVEL, FMT, ...) \
231 if (DEBUG_ENABLED(VERB, LEVEL)) \
232 { \
233 fprintf(g_func_debug.func_debug_file, "[%d:" #LEVEL WHERE "]: " FMT "\n", (int)g_func_debug.inst_id, \
234 ##__VA_ARGS__); \
235 }
236
237// Prints just the debugging prefix for properly marking free-form printouts
238#define DEBUG_PREFIX(LEVEL) fprintf(g_func_debug.func_debug_file, "[" #LEVEL WHERE "]: ")
239
240#endif
241
242// Macros for different verbosity levels
243#define DEBUG_INFO(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_INFO, LEVEL, COL_INFO(FMT), ##__VA_ARGS__)
244#define DEBUG_IFACE(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_IFACE, LEVEL, COL_IFACE(FMT), ##__VA_ARGS__)
245#define DEBUG_LOW(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_LOW, LEVEL, COL_LOW(FMT), ##__VA_ARGS__)
246#define DEBUG_MED(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_MED, LEVEL, COL_MED(FMT), ##__VA_ARGS__)
247#define DEBUG_HIGH(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_HIGH, LEVEL, COL_HIGH(FMT), ##__VA_ARGS__)
248
249int func_init_debug(func_debug_t*, uint64_t inst_id);
250int func_fini_debug(func_debug_t*);
251int func_debug_set_file(func_debug_t*, const char* filename);
252void func_debug_set_mask(func_debug_t*, const char* str);
253void func_debug_set_mask(func_debug_t*, const uint64_t mask);
254void func_debug_print_masks(FILE* out);
255void func_debug_set_verbosity(func_debug_t*, const char* str);
256void func_debug_set_verbosity(func_debug_t*, const uint32_t verb);
257void func_debug_set_suppress_arch_error_mask(func_debug_t*, const uint32_t suppress);
258void func_debug_set_inst_mask(func_debug_t*, const char* mask);
259void func_debug_set_inst_mask(func_debug_t*, const uint64_t mask);
260void func_debug_set_output_unbuffered(func_debug_t*, const bool is_unbuffered);
261
262#endif