output: Make panic/fatal/warn more flexible so we can add some new ones.
The major thrust of this change is to limit the amount of code duplication surrounding the code for these functions. This code also adds two new message types called info and hack. Info is meant to be less harsh than warn so people don't get confused and start thinking that the simulator is broken. Hack is a way for people to add runtime messages indicating that the simulator just executed a code "hack" that should probably be fixed. The benefit of knowing about these code hacks is that it will let people know what sorts of inaccuracies or potential bugs might be entering their experiments. Finally, I've added some flags to turn on and off these message types so command line options can change them.
This commit is contained in:
parent
b25e56b32a
commit
afb279b1bb
4 changed files with 120 additions and 96 deletions
|
@ -43,42 +43,24 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void
|
bool want_warn = true;
|
||||||
__panic(const char *func, const char *file, int line, const char *fmt,
|
bool want_info = true;
|
||||||
CPRINTF_DEFINITION)
|
bool want_hack = true;
|
||||||
{
|
|
||||||
string format = "panic: ";
|
|
||||||
format += fmt;
|
|
||||||
switch (format[format.size() - 1]) {
|
|
||||||
case '\n':
|
|
||||||
case '\r':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
format += "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
format += " @ cycle %d\n[%s:%s, line %d]\n";
|
bool warn_verbose = false;
|
||||||
|
bool info_verbose = false;
|
||||||
CPrintfArgsList args(VARARGS_ALLARGS);
|
bool hack_verbose = false;
|
||||||
|
|
||||||
args.push_back(curTick);
|
|
||||||
args.push_back(func);
|
|
||||||
args.push_back(file);
|
|
||||||
args.push_back(line);
|
|
||||||
|
|
||||||
ccprintf(cerr, format.c_str(), args);
|
|
||||||
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
__fatal(const char *func, const char *file, int line, const char *fmt,
|
__exit_message(const char *prefix, int code,
|
||||||
CPRINTF_DEFINITION)
|
const char *func, const char *file, int line,
|
||||||
|
const char *fmt, CPRINTF_DEFINITION)
|
||||||
{
|
{
|
||||||
CPrintfArgsList args(VARARGS_ALLARGS);
|
CPrintfArgsList args(VARARGS_ALLARGS);
|
||||||
string format = "fatal: ";
|
|
||||||
format += fmt;
|
|
||||||
|
|
||||||
|
string format = prefix;
|
||||||
|
format += ": ";
|
||||||
|
format += fmt;
|
||||||
switch (format[format.size() - 1]) {
|
switch (format[format.size() - 1]) {
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
|
@ -98,16 +80,22 @@ __fatal(const char *func, const char *file, int line, const char *fmt,
|
||||||
|
|
||||||
ccprintf(cerr, format.c_str(), args);
|
ccprintf(cerr, format.c_str(), args);
|
||||||
|
|
||||||
exit(1);
|
if (code < 0)
|
||||||
|
abort();
|
||||||
|
else
|
||||||
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
__warn(const char *func, const char *file, int line, const char *fmt,
|
__base_message(std::ostream &stream, const char *prefix, bool verbose,
|
||||||
CPRINTF_DEFINITION)
|
const char *func, const char *file, int line,
|
||||||
|
const char *fmt, CPRINTF_DEFINITION)
|
||||||
{
|
{
|
||||||
string format = "warn: ";
|
CPrintfArgsList args(VARARGS_ALLARGS);
|
||||||
format += fmt;
|
|
||||||
|
|
||||||
|
string format = prefix;
|
||||||
|
format += ": ";
|
||||||
|
format += fmt;
|
||||||
switch (format[format.size() - 1]) {
|
switch (format[format.size() - 1]) {
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
|
@ -116,18 +104,13 @@ __warn(const char *func, const char *file, int line, const char *fmt,
|
||||||
format += "\n";
|
format += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VERBOSE_WARN
|
if (verbose) {
|
||||||
format += " @ cycle %d\n[%s:%s, line %d]\n";
|
format += " @ cycle %d\n[%s:%s, line %d]\n";
|
||||||
#endif
|
args.push_back(curTick);
|
||||||
|
args.push_back(func);
|
||||||
|
args.push_back(file);
|
||||||
|
args.push_back(line);
|
||||||
|
}
|
||||||
|
|
||||||
CPrintfArgsList args(VARARGS_ALLARGS);
|
ccprintf(stream, format.c_str(), args);
|
||||||
|
|
||||||
#ifdef VERBOSE_WARN
|
|
||||||
args.push_back(curTick);
|
|
||||||
args.push_back(func);
|
|
||||||
args.push_back(file);
|
|
||||||
args.push_back(line);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ccprintf(cerr, format.c_str(), args);
|
|
||||||
}
|
}
|
||||||
|
|
130
src/base/misc.hh
130
src/base/misc.hh
|
@ -40,6 +40,30 @@
|
||||||
#define __FUNCTION__ "how to fix me?"
|
#define __FUNCTION__ "how to fix me?"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// General exit message, these functions will never return and will
|
||||||
|
// either abort() if code is < 0 or exit with the code if >= 0
|
||||||
|
void __exit_message(const char *prefix, int code,
|
||||||
|
const char *func, const char *file, int line,
|
||||||
|
const char *format, CPRINTF_DECLARATION) M5_ATTR_NORETURN;
|
||||||
|
|
||||||
|
void __exit_message(const char *prefix, int code,
|
||||||
|
const char *func, const char *file, int line,
|
||||||
|
const std::string &format, CPRINTF_DECLARATION) M5_ATTR_NORETURN;
|
||||||
|
|
||||||
|
inline void
|
||||||
|
__exit_message(const char *prefix, int code,
|
||||||
|
const char *func, const char *file, int line,
|
||||||
|
const std::string& format, CPRINTF_DEFINITION)
|
||||||
|
{
|
||||||
|
__exit_message(prefix, code, func, file, line, format.c_str(),
|
||||||
|
VARARGS_ALLARGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
M5_PRAGMA_NORETURN(__exit_message)
|
||||||
|
#define exit_message(prefix, code, ...) \
|
||||||
|
__exit_message(prefix, code, __FUNCTION__, __FILE__, __LINE__, \
|
||||||
|
__VA_ARGS__)
|
||||||
|
|
||||||
//
|
//
|
||||||
// This implements a cprintf based panic() function. panic() should
|
// This implements a cprintf based panic() function. panic() should
|
||||||
// be called when something happens that should never ever happen
|
// be called when something happens that should never ever happen
|
||||||
|
@ -47,20 +71,7 @@
|
||||||
// calls abort which can dump core or enter the debugger.
|
// calls abort which can dump core or enter the debugger.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
void __panic(const char *func, const char *file, int line, const char *format,
|
#define panic(...) exit_message("panic", -1, __VA_ARGS__)
|
||||||
CPRINTF_DECLARATION) M5_ATTR_NORETURN;
|
|
||||||
void __panic(const char *func, const char *file, int line,
|
|
||||||
const std::string &format, CPRINTF_DECLARATION)
|
|
||||||
M5_ATTR_NORETURN;
|
|
||||||
|
|
||||||
inline void
|
|
||||||
__panic(const char *func, const char *file, int line,
|
|
||||||
const std::string &format, CPRINTF_DEFINITION)
|
|
||||||
{
|
|
||||||
__panic(func, file, line, format.c_str(), VARARGS_ALLARGS);
|
|
||||||
}
|
|
||||||
M5_PRAGMA_NORETURN(__panic)
|
|
||||||
#define panic(...) __panic(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// This implements a cprintf based fatal() function. fatal() should
|
// This implements a cprintf based fatal() function. fatal() should
|
||||||
|
@ -70,45 +81,70 @@ M5_PRAGMA_NORETURN(__panic)
|
||||||
// "normal" exit with an error code, as opposed to abort() like
|
// "normal" exit with an error code, as opposed to abort() like
|
||||||
// panic() does.
|
// panic() does.
|
||||||
//
|
//
|
||||||
void __fatal(const char *func, const char *file, int line, const char *format,
|
#define fatal(...) exit_message("fatal", 1, __VA_ARGS__)
|
||||||
CPRINTF_DECLARATION) M5_ATTR_NORETURN;
|
|
||||||
void __fatal(const char *func, const char *file, int line,
|
void
|
||||||
const std::string &format, CPRINTF_DECLARATION)
|
__base_message(std::ostream &stream, const char *prefix, bool verbose,
|
||||||
M5_ATTR_NORETURN;
|
const char *func, const char *file, int line,
|
||||||
|
const char *format, CPRINTF_DECLARATION);
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
__fatal(const char *func, const char *file, int line,
|
__base_message(std::ostream &stream, const char *prefix, bool verbose,
|
||||||
const std::string &format, CPRINTF_DEFINITION)
|
const char *func, const char *file, int line,
|
||||||
|
const std::string &format, CPRINTF_DECLARATION)
|
||||||
{
|
{
|
||||||
__fatal(func, file, line, format.c_str(), VARARGS_ALLARGS);
|
__base_message(stream, prefix, verbose, func, file, line, format.c_str(),
|
||||||
|
VARARGS_ALLARGS);
|
||||||
}
|
}
|
||||||
M5_PRAGMA_NORETURN(__fatal)
|
|
||||||
#define fatal(...) __fatal(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
|
|
||||||
|
|
||||||
//
|
#define base_message(stream, prefix, verbose, ...) \
|
||||||
// This implements a cprintf based warn
|
__base_message(stream, prefix, verbose, __FUNCTION__, __FILE__, __LINE__, \
|
||||||
//
|
__VA_ARGS__)
|
||||||
void __warn(const char *func, const char *file, int line, const char *format,
|
|
||||||
CPRINTF_DECLARATION);
|
|
||||||
inline void
|
|
||||||
__warn(const char *func, const char *file, int line, const std::string &format,
|
|
||||||
CPRINTF_DECLARATION)
|
|
||||||
{
|
|
||||||
__warn(func, file, line, format, VARARGS_ALLARGS);
|
|
||||||
}
|
|
||||||
#define warn(...) __warn(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
|
|
||||||
|
|
||||||
// Only print the warning message the first time it is seen. This
|
// Only print the message the first time this expression is
|
||||||
// doesn't check the warning string itself, it just only lets one
|
// encountered. i.e. This doesn't check the string itself and
|
||||||
// warning come from the statement. So, even if the arguments change
|
// prevent duplicate strings, this prevents the statement from
|
||||||
// and that would have resulted in a different warning message,
|
// happening more than once. So, even if the arguments change and that
|
||||||
// subsequent messages would still be supressed.
|
// would have resulted in a different message thoes messages would be
|
||||||
#define warn_once(...) do { \
|
// supressed.
|
||||||
static bool once = false; \
|
#define base_message_once(...) do { \
|
||||||
if (!once) { \
|
static bool once = false; \
|
||||||
warn(__VA_ARGS__); \
|
if (!once) { \
|
||||||
once = true; \
|
base_message(__VA_ARGS__); \
|
||||||
} \
|
once = true; \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define cond_message(cond, ...) do { \
|
||||||
|
if (cond) \
|
||||||
|
base_message(__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define cond_message_once(cond, ...) do { \
|
||||||
|
static bool once = false; \
|
||||||
|
if (!once && cond) { \
|
||||||
|
base_message(__VA_ARGS__); \
|
||||||
|
once = true; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
extern bool want_warn, warn_verbose;
|
||||||
|
extern bool want_info, info_verbose;
|
||||||
|
extern bool want_hack, hack_verbose;
|
||||||
|
|
||||||
|
#define warn(...) \
|
||||||
|
cond_message(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
|
||||||
|
#define info(...) \
|
||||||
|
cond_message(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
|
||||||
|
#define hack(...) \
|
||||||
|
cond_message(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define warn_once(...) \
|
||||||
|
cond_message_once(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
|
||||||
|
#define info_once(...) \
|
||||||
|
cond_message_once(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
|
||||||
|
#define hack_once(...) \
|
||||||
|
cond_message_once(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)
|
||||||
|
|
||||||
#endif // __BASE_MISC_HH__
|
#endif // __BASE_MISC_HH__
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
%{
|
%{
|
||||||
#include "python/swig/pyobject.hh"
|
#include "python/swig/pyobject.hh"
|
||||||
|
|
||||||
|
#include "base/misc.hh"
|
||||||
#include "base/socket.hh"
|
#include "base/socket.hh"
|
||||||
#include "sim/core.hh"
|
#include "sim/core.hh"
|
||||||
#include "sim/host.hh"
|
#include "sim/host.hh"
|
||||||
|
@ -76,6 +77,10 @@ void unserializeAll(const std::string &cpt_dir);
|
||||||
void initAll();
|
void initAll();
|
||||||
void regAllStats();
|
void regAllStats();
|
||||||
|
|
||||||
|
bool want_warn, warn_verbose;
|
||||||
|
bool want_info, info_verbose;
|
||||||
|
bool want_hack, hack_verbose;
|
||||||
|
|
||||||
%wrapper %{
|
%wrapper %{
|
||||||
// fix up module name to reflect the fact that it's inside the m5 package
|
// fix up module name to reflect the fact that it's inside the m5 package
|
||||||
#undef SWIG_name
|
#undef SWIG_name
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
SimLoopExitEvent *
|
SimLoopExitEvent *
|
||||||
simulate(Tick num_cycles)
|
simulate(Tick num_cycles)
|
||||||
{
|
{
|
||||||
warn("Entering event queue @ %d. Starting simulation...\n", curTick);
|
info("Entering event queue @ %d. Starting simulation...\n", curTick);
|
||||||
|
|
||||||
if (num_cycles < 0)
|
if (num_cycles < 0)
|
||||||
fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles);
|
fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles);
|
||||||
|
|
Loading…
Reference in a new issue