2 * Copyright 2018 Google, Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "base/logging.hh"
36 #include "systemc/core/process.hh"
37 #include "systemc/core/scheduler.hh"
38 #include "systemc/ext/core/sc_main.hh"
39 #include "systemc/ext/utils/sc_report_handler.hh"
47 std::unique_ptr
<std::string
> logFileName
;
48 std::unique_ptr
<std::ofstream
> logFile
;
52 explicit ReportCatInfo(sc_actions actions
) :
53 actions(actions
), count(0), limit(-1)
55 ReportCatInfo() : ReportCatInfo(SC_UNSPECIFIED
) {}
58 checkLimit(sc_actions
&actions
)
60 if (limit
== 0 || count
< limit
)
72 const char *severityNames
[] = {
74 [SC_WARNING
] = "Warning",
79 ReportCatInfo catForSeverity
[SC_MAX_SEVERITY
] =
81 [SC_INFO
] = ReportCatInfo(SC_DEFAULT_INFO_ACTIONS
),
82 [SC_WARNING
] = ReportCatInfo(SC_DEFAULT_WARNING_ACTIONS
),
83 [SC_ERROR
] = ReportCatInfo(SC_DEFAULT_ERROR_ACTIONS
),
84 [SC_FATAL
] = ReportCatInfo(SC_DEFAULT_FATAL_ACTIONS
)
87 std::map
<std::string
, ReportCatInfo
> catForMsgType
;
88 std::map
<std::pair
<std::string
, sc_severity
>, ReportCatInfo
>
89 catForSeverityAndMsgType
;
91 int verbosityLevel
= SC_MEDIUM
;
93 sc_actions suppressedActions
= SC_UNSPECIFIED
;
94 sc_actions forcedActions
= SC_UNSPECIFIED
;
95 sc_actions catchActions
= SC_UNSPECIFIED
;
97 sc_report_handler_proc reportHandlerProc
= &sc_report_handler::default_handler
;
99 sc_actions maxAction
= SC_ABORT
;
101 std::unique_ptr
<sc_report
> globalReportCache
;
103 } // anonymous namespace
106 sc_report_handler::report(sc_severity severity
, const char *msg_type
,
107 const char *msg
, const char *file
, int line
)
109 report(severity
, msg_type
, msg
, SC_MEDIUM
, file
, line
);
113 sc_report_handler::report(sc_severity severity
, const char *msg_type
,
114 const char *msg
, int verbosity
, const char *file
,
117 if (severity
== SC_INFO
&& verbosity
> verbosityLevel
)
120 ReportCatInfo
&sevInfo
= catForSeverity
[severity
];
121 ReportCatInfo
&msgInfo
= catForMsgType
[msg_type
];
122 ReportCatInfo
&sevMsgInfo
= catForSeverityAndMsgType
[
123 std::make_pair(std::string(msg_type
), severity
)];
129 sc_actions actions
= SC_UNSPECIFIED
;
130 if (sevMsgInfo
.actions
!= SC_UNSPECIFIED
)
131 actions
= sevMsgInfo
.actions
;
132 else if (msgInfo
.actions
!= SC_UNSPECIFIED
)
133 actions
= msgInfo
.actions
;
134 else if (sevInfo
.actions
!= SC_UNSPECIFIED
)
135 actions
= sevInfo
.actions
;
137 actions
&= ~suppressedActions
;
138 actions
|= forcedActions
;
140 if (sevMsgInfo
.checkLimit(actions
) && msgInfo
.checkLimit(actions
))
141 sevInfo
.checkLimit(actions
);
143 ::sc_gem5::Process
*current
= ::sc_gem5::scheduler
.current();
144 sc_report
report(severity
, msg_type
, msg
, verbosity
, file
, line
,
145 sc_time::from_value(::sc_gem5::scheduler
.getCurTick()),
146 current
? current
->name() : nullptr, -1);
148 if (actions
& SC_CACHE_REPORT
) {
150 current
->lastReport(&report
);
153 std::unique_ptr
<sc_report
>(new sc_report(report
));
157 reportHandlerProc(report
, actions
);
161 sc_report_handler::report(sc_severity
, int id
, const char *msg
,
162 const char *file
, int line
)
164 warn("%s:%d %s\n", file
, line
, msg
);
165 warn("%s not implemented.\n", __PRETTY_FUNCTION__
);
169 sc_report_handler::set_actions(sc_severity severity
, sc_actions actions
)
171 ReportCatInfo
&info
= catForSeverity
[severity
];
172 sc_actions previous
= info
.actions
;
173 info
.actions
= actions
;
178 sc_report_handler::set_actions(const char *msg_type
, sc_actions actions
)
180 ReportCatInfo
&info
= catForMsgType
[msg_type
];
181 sc_actions previous
= info
.actions
;
182 info
.actions
= actions
;
187 sc_report_handler::set_actions(
188 const char *msg_type
, sc_severity severity
, sc_actions actions
)
190 ReportCatInfo
&info
= catForSeverityAndMsgType
[
191 std::make_pair(std::string(msg_type
), severity
)];
192 sc_actions previous
= info
.actions
;
193 info
.actions
= actions
;
198 sc_report_handler::stop_after(sc_severity severity
, int limit
)
200 ReportCatInfo
&info
= catForSeverity
[severity
];
201 int previous
= info
.limit
;
207 sc_report_handler::stop_after(const char *msg_type
, int limit
)
209 ReportCatInfo
&info
= catForMsgType
[msg_type
];
210 int previous
= info
.limit
;
216 sc_report_handler::stop_after(
217 const char *msg_type
, sc_severity severity
, int limit
)
219 ReportCatInfo
&info
= catForSeverityAndMsgType
[
220 std::make_pair(std::string(msg_type
), severity
)];
221 int previous
= info
.limit
;
227 sc_report_handler::get_count(sc_severity severity
)
229 return catForSeverity
[severity
].count
;
233 sc_report_handler::get_count(const char *msg_type
)
235 return catForMsgType
[msg_type
].count
;
239 sc_report_handler::get_count(const char *msg_type
, sc_severity severity
)
241 return catForSeverityAndMsgType
[
242 std::make_pair(std::string(msg_type
), severity
)].count
;
246 sc_report_handler::set_verbosity_level(int vl
)
248 int previous
= verbosityLevel
;
254 sc_report_handler::get_verbosity_level()
256 return verbosityLevel
;
261 sc_report_handler::suppress(sc_actions actions
)
263 sc_actions previous
= suppressedActions
;
264 suppressedActions
= actions
;
269 sc_report_handler::suppress()
271 return suppress(SC_UNSPECIFIED
);
275 sc_report_handler::force(sc_actions actions
)
277 sc_actions previous
= forcedActions
;
278 forcedActions
= actions
;
283 sc_report_handler::force()
285 return force(SC_UNSPECIFIED
);
290 sc_report_handler::set_catch_actions(sc_actions actions
)
292 sc_actions previous
= catchActions
;
293 catchActions
= actions
;
298 sc_report_handler::get_catch_actions()
305 sc_report_handler::set_handler(sc_report_handler_proc proc
)
307 reportHandlerProc
= proc
;
311 sc_report_handler::default_handler(
312 const sc_report
&report
, const sc_actions
&actions
)
314 if (actions
& SC_DISPLAY
)
315 cprintf("\n%s\n", sc_report_compose_message(report
));
317 if ((actions
& SC_LOG
) && logFile
) {
318 ccprintf(*logFile
, "%s: %s\n", report
.get_time().to_string(),
319 sc_report_compose_message(report
));
321 if (actions
& SC_STOP
) {
322 sc_stop_here(report
.get_msg_type(), report
.get_severity());
325 if (actions
& SC_INTERRUPT
)
326 sc_interrupt_here(report
.get_msg_type(), report
.get_severity());
327 if (actions
& SC_ABORT
)
329 if (actions
& SC_THROW
) {
330 ::sc_gem5::Process
*current
= ::sc_gem5::scheduler
.current();
332 current
->isUnwinding(false);
338 sc_report_handler::get_new_action_id()
340 maxAction
= maxAction
<< 1;
345 sc_report_handler::get_cached_report()
347 ::sc_gem5::Process
*current
= ::sc_gem5::scheduler
.current();
349 return current
->lastReport();
350 return globalReportCache
.get();
354 sc_report_handler::clear_cached_report()
356 ::sc_gem5::Process
*current
= ::sc_gem5::scheduler
.current();
358 current
->lastReport(nullptr);
360 globalReportCache
= nullptr;
365 sc_report_handler::set_log_file_name(const char *new_name
)
369 logFileName
= nullptr;
374 logFileName
= std::unique_ptr
<std::string
>(new std::string(new_name
));
375 logFile
= std::unique_ptr
<std::ofstream
>(new std::ofstream(new_name
));
381 sc_report_handler::get_log_file_name()
386 return logFileName
->c_str();
390 sc_interrupt_here(const char *msg_type
, sc_severity
)
392 // Purposefully empty, for setting breakpoints supposedly.
396 sc_stop_here(const char *msg_type
, sc_severity
)
398 // Purposefully empty, for setting breakpoints supposedly.
402 sc_report_compose_message(const sc_report
&report
)
404 std::ostringstream str
;
406 const char *sevName
= severityNames
[report
.get_severity()];
407 int id
= report
.get_id();
409 str
<< sevName
<< ": ";
411 ccprintf(str
, "(%c%d) ", sevName
[0], id
);
413 str
<< report
.get_msg_type();
415 const char *msg
= report
.get_msg();
419 if (report
.get_severity() > SC_INFO
) {
420 ccprintf(str
, "\nIn file: %s:%d", report
.get_file_name(),
421 report
.get_line_number());
423 ::sc_gem5::Process
*current
= ::sc_gem5::scheduler
.current();
424 const char *name
= report
.get_process_name();
425 if (current
&& sc_is_running() && name
) {
426 ccprintf(str
, "\nIn process: %s @ %s", name
,
427 report
.get_time().to_string());
435 sc_report_close_default_log()
439 logFileName
= nullptr;
445 } // namespace sc_core