-
Notifications
You must be signed in to change notification settings - Fork 6
/
report.hpp
218 lines (174 loc) · 7.54 KB
/
report.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#ifndef REPORT_HPP
#define REPORT_HPP
/** @file report.hpp
@brief Reporting macro extensions
This is a simplified version of my reporting extensions.
The basic idea is to simplify syntax when reporting on messages more
complex than a basic string. Also, simplifies specification of the
message type (aka message identifier). See instructions for usage.
There are three macros, several requirements, one limitation, and
some instructions below. Read on...
Macros
------
1. REPORT(type,stream) -- trivially improves SC_REPORT_(INFO,WARNING,ERROR,FATAL)
2. INFO(level,stream) -- improves on SC_REPORT_INFO_VERB
3. DEBUG(stream) -- allows sc_object specific debugging
Requirements
------------
1. Assumes SystemC
2. Define MSGID string anytime these macros are used.
3. If using the DEBUG macro, then commandline.hpp must be available
4. To disable the DEBUG macro, define NDEBUG
Limitations
-----------
If your streaming expression (see instructions) contains commas, then
you must surround that element with parentheses due to limitations of
pre-processor macros.
Instructions
------------
### Step 1
Include this at the top of any file where the macros are used.
```c++
#include "report.cpp"
```
### Step 2
Define the message type with a file local variable, MSGID as follows:
In modules, channels, classes or structs:
```c++
inline static constexpr char const * const MSGID
{ "/COMPANY/PROJECT/MODULE" };
```
Or files without a class:
```c++
namespace {
constexpr char const * const MSGID
{ "/COMPANY/PROJECT/MODULE" };
}
```
### Step 3
Insert the macros where you would normally use SC_REPORT_* macros. Here are
some simple examples:
REPORT( WARNING, "Possible problem detected" );
INFO( NONE, "Version " << version );
DEBUG( "Sending packet " << packet );
### Step 4 (for DEBUG macro)
Make sure you have set the verbosity level to SC_DEBUG. You might consider
using the Commandline::has_opt("-debug") to conditionallly set this.
At run-time, add command-line arguments to specify the instances you want to
debug:
% run.x -debug=observer -debug=splitter # debugs only for specified elements
% run.x -debugall # turns on all DEBUG messages
See `ABOUT_REPORT.md` for more information.
********************************************************************************
*/
#include "systemc.hpp"
#include <string>
#include <sstream>
#include <iomanip>
struct Report {
#if __cplusplus >= 201703L
inline // Obliviates the need for report.cpp
#endif
static std::ostringstream mout;
};
#define STREAM_HEX std::hex << std::showbase
#define STREAM_DEC std::dec << std::noshowbase << std::setfill(' ')
#ifdef __SYNTHESIS__
#define REPORT(type,stream)
#define ASSERT(expr,stream)
#define SC_ALWAYS SC_NONE
#define SC_NEVER (1<<14)
#define SC_HYPER 1024
#define DEVID (std::string("(")+name()+")").c_str()
#define NOINFO(level,stream)
#define INFO(level,stream)
#define DEBUG(level,stream)
#define MESSAGE(stream)
#define MEND(level)
#define RULER(c)
#define TODO(stream)
#define NOT_YET_IMPLEMENTED()
#define DELETE_THIS_LINE(lno,message)
#else
// For type: WARNING, ERROR, FATAL (use INFO() for INFO level messages)
#define REPORT(type,stream) \
do { \
Report::mout << STREAM_DEC << stream << std::ends; \
auto str = Report::mout.str(); Report::mout.str(""); \
SC_REPORT_##type( MSGID, str.c_str() ); \
} while (0)
// Use the following to (A) add more information in the event of failure, and
// and (B) control sc_assert behavior (i.e. not unconditional abort on failure).
#ifndef NDEBUG
#define ASSERT(expr,stream) do {\
if(!(expr)) REPORT(FATAL, "Assertion failed: " << # expr << ". " << stream );\
} while (0)
#else
#define ASSERT(expr,stream)
#endif
#define SC_ALWAYS SC_NONE
#define SC_NEVER 16*KB
#define SC_HYPER 1024
#define DEVID ((std::string("(")+name()+")").c_str())
#define NOINFO(level,stream)
// For level: NONE, LOW, MEDIUM, HIGH, DEBUG
#define INFO(level,stream) \
do { \
if( sc_core::sc_report_handler::get_verbosity_level() \
>= (sc_core::SC_##level) ) { \
Report::mout << STREAM_DEC << stream; \
auto now = sc_core::sc_time_stamp(); \
if( now > sc_core::SC_ZERO_TIME \
or sc_core::sc_get_status() >= sc_core::SC_START_OF_SIMULATION ) { \
Report::mout << STREAM_DEC << " at " << now; \
} \
Report::mout << std::ends; \
if( (sc_core::SC_##level) >= sc_core::SC_DEBUG ) { \
std::string id{"DEBUG("}; \
id+=__FILE__ ; id+=":"; id+=std::to_string(__LINE__)+")"; \
size_t p0=id.find("/"),p1=id.find_last_of("/"); \
if(p1!=std::string::npos) id.erase(p0,p1-p0+1); \
auto str = Report::mout.str(); Report::mout.str(""); \
SC_REPORT_INFO_VERB( id.c_str(), str.c_str(), (sc_core::SC_##level) ); \
} else { \
auto str = Report::mout.str(); Report::mout.str(""); \
SC_REPORT_INFO_VERB( MSGID, str.c_str(), (sc_core::SC_##level) ); \
} \
} \
} while (0)
#ifdef NDEBUG
#define DEBUG()
#else
#include "commandline.hpp"
#define DEBUG(stream) do { \
if( sc_core::sc_report_handler::get_verbosity_level() >= sc_core::SC_DEBUG \
and ( Commandline::has_opt("-debugall") \
or Commandline::has_opt("-debug="s + basename() ) ) ) { \
INFO(DEBUG,stream); \
} \
} while(0)
#endif
#define MESSAGE(stream) do { Report::mout << stream; } while(0)
#define MEND(level) do { \
if( sc_core::sc_report_handler::get_verbosity_level() >= (sc_core::SC_##level) ) {\
Report::mout << std::ends; \
std::string str = Report::mout.str(); Report::mout.str(""); \
SC_REPORT_INFO_VERB( MSGID, str.c_str(), (sc_core::SC_##level)); \
} \
Report::mout.str( "" ); \
} while (0)
#define RULER(c) MESSAGE( std::string( 80, c ) << "\n" )
#define TODO(stream) REPORT( WARNING, "TODO: " << stream )
#define NOT_YET_IMPLEMENTED() REPORT( WARNING, __PRETTY_FUNCTION__ << " is not yet implemented." )
//
struct DELETE_THIS
{
DELETE_THIS( char const * const filename, int lineno, char const * const message )
{
::sc_core::sc_report_handler::report( \
::sc_core::SC_WARNING, "Code incomplete", message, filename, lineno );
}
};
#define DELETE_THIS_LINE(lno,message) const DELETE_THIS lno{ __FILE__, __LINE__, #message }
#endif/*__SYNTHESIS__*/
#endif/*REPORT_HPP*/