blob: 556faf20fcc3ec20dc530c035e60377f68524e0c [file] [log] [blame]
Eric Kunzee5e26762020-10-13 16:11:07 -07001
Jerry Gea793f462023-04-11 00:05:02 +00002// Copyright (c) 2020-2023, ARM Limited.
Eric Kunzee5e26762020-10-13 16:11:07 -07003//
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>
Matthew Sloyanba5fad32022-09-26 13:31:43 +010024#include <string>
Eric Kunze286f8342022-06-22 11:30:23 -070025#include <vector>
Eric Kunzee5e26762020-10-13 16:11:07 -070026
27void func_print_backtrace(FILE* out, int sig = SIGABRT);
28
29void func_enable_signal_handlers();
30
Eric Kunzee5e26762020-10-13 16:11:07 -070031// STRINGIFY2 is needed expand expression passed to STRINGIFY
32#define STRINGIFY2(s) #s
33#define STRINGIFY(s) STRINGIFY2(s)
34
35// If TRACED_LOG is defined, add file:line to log messages
36#if defined(TRACED_LOG)
37#define WHERE "@" __FILE__ ":" STRINGIFY(__LINE__)
38#else
39#define WHERE
40#endif
41
42#if defined(COLORIZED_LOG)
43#define COL(col, fmt) "\x1b[3" col "m" fmt "\x1b[0m"
44#define COL_FATAL(fmt) COL("1;41", fmt)
45#define COL_WARN(fmt) COL("1;43", fmt)
46#define COL_INFO(fmt) COL("2", fmt)
47#define COL_IFACE(fmt) fmt
48#define COL_LOW(fmt) COL("35", fmt)
49#define COL_MED(fmt) COL("2;33", fmt)
50#define COL_HIGH(fmt) COL("2;32", fmt)
51#else
52#define COL_FATAL(fmt) fmt
53#define COL_WARN(fmt) fmt
54#define COL_INFO(fmt) fmt
55#define COL_IFACE(fmt) fmt
56#define COL_LOW(fmt) fmt
57#define COL_MED(fmt) fmt
58#define COL_HIGH(fmt) fmt
59#endif
60
61struct func_debug_t
62{
Jerry Ge9c9c8da2023-07-19 23:08:16 +000063 uint32_t func_debug_verbosity = 0; // What verbosity level is set? (bitmask)
64 uint64_t func_debug_mask = 0; // Which units have debugging enabled? (bitmask)
65 uint64_t func_debug_inst_mask = 0; // Which instances have debugging enabled (bitmask)
66 uint64_t inst_id = 0; // The instance id for multiple model instances
67 FILE* func_debug_file = stderr; // Output file
68 bool is_output_unbuffered = false; // should log files be opened with unbuffered I/O.
Eric Kunze286f8342022-06-22 11:30:23 -070069
70 int init_debug(uint64_t inst_id);
71 int fini_debug();
72 int set_file(const std::string& filename);
73 void set_mask(const std::string& str);
74 void set_mask(const uint64_t mask);
75 void print_masks(FILE* out);
76 void set_verbosity(const std::string& str);
77 void set_verbosity(const uint32_t verb);
78 void set_inst_mask(const char* mask);
79 void set_inst_mask(const uint64_t mask);
80 void set_output_unbuffered(const bool is_unbuffered);
81 std::string get_debug_mask_help_string();
82 std::string get_debug_verbosity_help_string();
Eric Kunzee5e26762020-10-13 16:11:07 -070083};
84
85#ifndef ASSERT
86#define ASSERT(COND) \
87 if (!(COND)) \
88 { \
89 fprintf(stderr, COL_FATAL("ASSERTION AT %s:%d %s(): (%s)\n"), __FILE__, __LINE__, __func__, #COND); \
90 func_print_backtrace(stderr); \
91 assert(COND); \
92 }
93#endif
94
95#ifndef ASSERT_MSG
96#define ASSERT_MSG(COND, fmt, ...) \
97 if (!(COND)) \
98 { \
99 fprintf(stderr, COL_FATAL("ASSERTION AT %s:%d %s(): (%s)\n"), __FILE__, __LINE__, __func__, #COND); \
100 fprintf(stderr, COL_FATAL(fmt) "\n", ##__VA_ARGS__); \
101 func_print_backtrace(stderr); \
102 assert(COND); \
103 }
104#endif
105
Kevin Chengacb550f2021-06-29 15:32:19 -0700106#ifndef REQUIRE
107#define REQUIRE(COND, fmt, ...) \
Eric Kunzee5e26762020-10-13 16:11:07 -0700108 if (!(COND)) \
109 { \
Kevin Chengacb550f2021-06-29 15:32:19 -0700110 fprintf(g_func_debug.func_debug_file, COL_FATAL("REQUIRE() fails AT %s:%d %s(): (%s)\n"), __FILE__, __LINE__, \
111 __func__, #COND); \
112 fprintf(g_func_debug.func_debug_file, COL_FATAL(fmt) "\n", ##__VA_ARGS__); \
113 this->parent_sgt->setGraphStatus(GraphStatus::TOSA_UNPREDICTABLE); \
114 }
115#endif
116
Jerry Gea793f462023-04-11 00:05:02 +0000117#ifndef LEVEL_CHECK
Jerry Ge9c9c8da2023-07-19 23:08:16 +0000118#define LEVEL_CHECK(COND, fmt, ...) \
119 if (g_func_config.tosa_level != func_config_t::NONE && (!(COND))) \
120 { \
121 fprintf(g_func_debug.func_debug_file, COL_FATAL("LEVEL_CHECK() fails AT %s:%d %s(): (%s)\n"), __FILE__, \
122 __LINE__, __func__, #COND); \
123 fprintf(g_func_debug.func_debug_file, COL_FATAL(fmt) "\n", ##__VA_ARGS__); \
124 this->parent_sgt->setGraphStatus(GraphStatus::TOSA_UNPREDICTABLE); \
Jerry Gea793f462023-04-11 00:05:02 +0000125 }
126#endif
127
Kevin Chengacb550f2021-06-29 15:32:19 -0700128#ifndef ERROR_IF
129#define ERROR_IF(COND, fmt, ...) \
130 if ((COND)) \
131 { \
132 if (this->parent_sgt->getGraphStatus() != GraphStatus::TOSA_UNPREDICTABLE) \
133 { \
134 this->parent_sgt->setGraphStatus(GraphStatus::TOSA_ERROR); \
135 } \
136 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 -0700137 __func__, #COND); \
138 fprintf(g_func_debug.func_debug_file, COL_FATAL(fmt) "\n", ##__VA_ARGS__); \
139 this->dumpNode(g_func_debug.func_debug_file); \
140 func_print_backtrace(g_func_debug.func_debug_file); \
Kevin Chengacb550f2021-06-29 15:32:19 -0700141 return 1; \
Eric Kunzee5e26762020-10-13 16:11:07 -0700142 }
143#endif
144
145// Assertion specific to allocating memory
146#ifndef ASSERT_MEM
147#define ASSERT_MEM(OBJ) \
148 if (!(OBJ)) \
149 { \
150 fprintf(stderr, COL_FATAL("ASSERTION AT %s:%d %s(): (" #OBJ "): out of memory\n"), __FILE__, __LINE__, \
151 __func__); \
152 func_print_backtrace(stderr); \
153 assert(OBJ); \
154 }
155#endif
156
157#ifndef FATAL_ERROR
158#define FATAL_ERROR(fmt, ...) \
159 fprintf(stderr, COL_FATAL("FATAL ERROR AT %s:%d %s():\n"), __FILE__, __LINE__, __func__); \
160 fprintf(stderr, COL_FATAL(fmt) "\n", ##__VA_ARGS__); \
161 func_print_backtrace(stderr); \
162 abort();
163#endif
164
Eric Kunzee5e26762020-10-13 16:11:07 -0700165void func_debug_warning(
166 func_debug_t* func_debug, const char* file, const char* func, const int line, const char* fmt, ...);
167#ifndef WARNING
168#define WARNING(...) func_debug_warning(&g_func_debug, __FILE__, __func__, __LINE__, __VA_ARGS__)
169#endif
170
171#ifndef WARNING_STDERR
172#define WARNING_STDERR(fmt, ...) \
173 fprintf(stderr, COL_WARN("WARNING AT %s:%d %s():\n"), __FILE__, __LINE__, __func__); \
174 fprintf(stderr, COL_WARN(fmt) "\n", ##__VA_ARGS__);
175#endif
176
Eric Kunzee5e26762020-10-13 16:11:07 -0700177// Is this debug verbosity and unit level enabled?
178// Provide compiler hints that this is unlikely
179// Two versions, depending on whether DEBUG_INSTANCE_EXPR is defined in a file or not
180//
181// For .cpp files whose units have discrete instance IDs, define DEBUG_INSTANCE_EXPR to evalute
182// to the instance ID variable. The use of this define in header files is discouraged.
183
184#ifdef DEBUG_INSTANCE_EXPR
185// Expression for whether the debugging verbosity + debugging unit is enabled for free-form printouts
186#ifdef DEBUG_INSTANCE_EXPR_2
187#define DEBUG_ENABLED(VERB, LEVEL) \
188 (__builtin_expect((g_func_debug.func_debug_mask == DEBUG_ALL || g_func_debug.func_debug_mask & (DEBUG_##LEVEL)) && \
189 (g_func_debug.func_debug_inst_mask & (uint64_t(1) << (DEBUG_INSTANCE_EXPR))) && \
190 (g_func_debug.func_debug_verbosity & (VERB)), \
191 0))
192// Debug printing macro
193#define DEBUG(VERB, LEVEL, FMT, ...) \
194 if (DEBUG_ENABLED(VERB, LEVEL)) \
195 { \
196 fprintf(g_func_debug.func_debug_file, "[%d:" #LEVEL "_%02d_%02d" WHERE "]: " FMT "\n", \
197 (int)g_func_debug.inst_id, (int)(DEBUG_INSTANCE_EXPR), (int)(DEBUG_INSTANCE_EXPR_2), ##__VA_ARGS__); \
198 }
199
200// Prints just the debugging prefix for properly marking free-form printouts
201#define DEBUG_PREFIX(LEVEL) \
202 fprintf(g_func_debug.func_debug_file, "[%d" #LEVEL "_%02d_%02d" WHERE "]: ", (int)g_func_debug.inst_id, \
203 (int)(DEBUG_INSTANCE_EXPR), (int)(DEBUG_INSTANCE_EXPR_2))
204
205#else // !DEBUG_INSTANCE_EXPR_2
206
207#define DEBUG_ENABLED(VERB, LEVEL) \
208 (__builtin_expect((g_func_debug.func_debug_mask == DEBUG_ALL || g_func_debug.func_debug_mask & (DEBUG_##LEVEL)) && \
209 (g_func_debug.func_debug_inst_mask & (uint64_t(1) << (DEBUG_INSTANCE_EXPR))) && \
210 (g_func_debug.func_debug_verbosity & (VERB)), \
211 0))
212// Debug printing macro
213#define DEBUG(VERB, LEVEL, FMT, ...) \
214 if (DEBUG_ENABLED(VERB, LEVEL)) \
215 { \
216 fprintf(g_func_debug.func_debug_file, "[%d:" #LEVEL "_%02d" WHERE "]: " FMT "\n", (int)g_func_debug.inst_id, \
217 (int)(DEBUG_INSTANCE_EXPR), ##__VA_ARGS__); \
218 }
219
220// Prints just the debugging prefix for properly marking free-form printouts
221#define DEBUG_PREFIX(LEVEL) \
222 fprintf(g_func_debug.func_debug_file, "[%d:" #LEVEL "_%02d" WHERE "]: ", (int)g_func_debug.inst_id, \
223 (int)(DEBUG_INSTANCE_EXPR))
224
225#endif // DEBUG_INSTANCE_EXPR_2
226
227#else // !DEBUG_INSTANCE_EXPR
228
229// Expression for whether the debugging verbosity + debugging unit is enabled for free-form printouts
230#define DEBUG_ENABLED(VERB, LEVEL) \
231 (__builtin_expect((g_func_debug.func_debug_mask == DEBUG_ALL || g_func_debug.func_debug_mask & (DEBUG_##LEVEL)) && \
232 (g_func_debug.func_debug_verbosity & (VERB)), \
233 0))
234// Debug printing macro
235#define DEBUG(VERB, LEVEL, FMT, ...) \
236 if (DEBUG_ENABLED(VERB, LEVEL)) \
237 { \
238 fprintf(g_func_debug.func_debug_file, "[%d:" #LEVEL WHERE "]: " FMT "\n", (int)g_func_debug.inst_id, \
239 ##__VA_ARGS__); \
240 }
241
242// Prints just the debugging prefix for properly marking free-form printouts
243#define DEBUG_PREFIX(LEVEL) fprintf(g_func_debug.func_debug_file, "[" #LEVEL WHERE "]: ")
244
245#endif
246
247// Macros for different verbosity levels
248#define DEBUG_INFO(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_INFO, LEVEL, COL_INFO(FMT), ##__VA_ARGS__)
249#define DEBUG_IFACE(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_IFACE, LEVEL, COL_IFACE(FMT), ##__VA_ARGS__)
250#define DEBUG_LOW(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_LOW, LEVEL, COL_LOW(FMT), ##__VA_ARGS__)
251#define DEBUG_MED(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_MED, LEVEL, COL_MED(FMT), ##__VA_ARGS__)
252#define DEBUG_HIGH(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_HIGH, LEVEL, COL_HIGH(FMT), ##__VA_ARGS__)
253
Eric Kunzee5e26762020-10-13 16:11:07 -0700254#endif