From 1088f0c4ac3999fc3c363cc51daef4cfb360a2bd Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 30 Nov 2017 17:36:53 -0800 Subject: misc: Rename misc.(hh|cc) to logging.(hh|cc) These files aren't a collection of miscellaneous stuff, they're the definition of the Logger interface, and a few utility macros for calling into that interface (panic, warn, etc.). Change-Id: I84267ac3f45896a83c0ef027f8f19c5e9a5667d1 Reviewed-on: https://gem5-review.googlesource.com/6226 Reviewed-by: Brandon Potter Maintainer: Gabe Black --- src/base/logging.hh | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 src/base/logging.hh (limited to 'src/base/logging.hh') diff --git a/src/base/logging.hh b/src/base/logging.hh new file mode 100644 index 000000000..b0a9b0c1b --- /dev/null +++ b/src/base/logging.hh @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2014, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Dave Greene + * Andreas Sandberg + */ + +#ifndef __BASE_LOGGING_HH__ +#define __BASE_LOGGING_HH__ + +#include +#include +#include +#include + +#include "base/compiler.hh" +#include "base/cprintf.hh" + +#if defined(__SUNPRO_CC) +#define __FUNCTION__ "how to fix me?" +#endif + +class Logger +{ + public: + enum LogLevel { + PANIC = 0, + FATAL, + WARN, + INFO, + HACK, + NUM_LOG_LEVELS, + }; + + /** + * Set the active log level. + * + * All levels that are lower or equal to the selected log level + * will be activated. + * + * @param ll Maximum log level to print + */ + static void setLevel(LogLevel ll); + + /** + * Get a Logger corresponding to a specific log level + * + * @param ll Log level to access + * @return Reference to the requested logger + */ + static Logger &get(LogLevel ll); + + public: + Logger(std::ostream &stream, const char *prefix); + virtual ~Logger() {}; + + template void + print(const char *func, const char *file, int line, + const char *format, const Args &...args) + { + if (!enabled) + return; + + if (prefix) + stream << prefix << ": "; + ccprintf(stream, format, args...); + + printEpilogue(func, file, line, format); + } + + template void + print(const char *func, const char *file, int line, + const std::string &format, const Args &...args) + { + print(func, file, line, format.c_str(), args...); + } + + protected: + virtual void printEpilogue(const char *func, const char *file, int line, + const char *format); + + public: + bool enabled; + bool verbose; + + protected: + std::ostream &stream; + const char *prefix; +}; + +#define exit_message(logger, code, ...) \ + do { \ + logger.print(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ + if (code < 0) \ + ::abort(); \ + else \ + ::exit(code); \ + } while (0) + +// +// This implements a cprintf based panic() function. panic() should +// be called when something happens that should never ever happen +// regardless of what the user does (i.e., an acutal m5 bug). panic() +// calls abort which can dump core or enter the debugger. +// +// +#define panic(...) exit_message(::Logger::get(::Logger::PANIC), -1, \ + __VA_ARGS__) + +// +// This implements a cprintf based fatal() function. fatal() should +// be called when the simulation cannot continue due to some condition +// that is the user's fault (bad configuration, invalid arguments, +// etc.) and not a simulator bug. fatal() calls abort() like +// panic() does. +// +#define fatal(...) exit_message(::Logger::get(::Logger::FATAL), 1, \ + __VA_ARGS__) + +/** + * Conditional panic macro that checks the supplied condition and only panics + * if the condition is true and allows the programmer to specify diagnostic + * printout. Useful to replace if + panic, or if + print + assert, etc. + * + * @param cond Condition that is checked; if true -> panic + * @param ... Printf-based format string with arguments, extends printout. + */ +#define panic_if(cond, ...) \ + do { \ + if ((cond)) { \ + panic("panic condition " # cond " occurred: %s", \ + csprintf(__VA_ARGS__)); \ + } \ + } while (0) + + +/** + * Conditional fatal macro that checks the supplied condition and only causes a + * fatal error if the condition is true and allows the programmer to specify + * diagnostic printout. Useful to replace if + fatal, or if + print + assert, + * etc. + * + * @param cond Condition that is checked; if true -> fatal + * @param ... Printf-based format string with arguments, extends printout. + */ +#define fatal_if(cond, ...) \ + do { \ + if ((cond)) { \ + fatal("fatal condition " # cond " occurred: %s", \ + csprintf(__VA_ARGS__)); \ + } \ + } while (0) + + +#define base_message(logger, ...) \ + logger.print(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) + +// Only print the message the first time this expression is +// encountered. i.e. This doesn't check the string itself and +// prevent duplicate strings, this prevents the statement from +// happening more than once. So, even if the arguments change and that +// would have resulted in a different message thoes messages would be +// supressed. +#define base_message_once(...) do { \ + static bool once = false; \ + if (!once) { \ + base_message(__VA_ARGS__); \ + once = true; \ + } \ + } while (0) + + +#define warn(...) \ + base_message(::Logger::get(::Logger::WARN), __VA_ARGS__) +#define inform(...) \ + base_message(::Logger::get(::Logger::INFO), __VA_ARGS__) +#define hack(...) \ + base_message(::Logger::get(::Logger::HACK), __VA_ARGS__) + +#define warn_once(...) \ + base_message_once(::Logger::get(::Logger::WARN), __VA_ARGS__) +#define inform_once(...) \ + base_message_once(::Logger::get(::Logger::INFO), __VA_ARGS__) +#define hack_once(...) \ + base_message_once(::Logger::get(::Logger::HACK), __VA_ARGS__) + +/** + * Conditional warning macro that checks the supplied condition and + * only prints a warning if the condition is true. Useful to replace + * if + warn. + * + * @param cond Condition that is checked; if true -> warn + * @param ... Printf-based format string with arguments, extends printout. + */ +#define warn_if(cond, ...) \ + do { \ + if ((cond)) \ + warn(__VA_ARGS__); \ + } while (0) + +/** + * The chatty assert macro will function like a normal assert, but will allow + * the specification of additional, helpful material to aid debugging why the + * assertion actually failed. Like the normal assertion, the chatty_assert + * will not be active in fast builds. + * + * @param cond Condition that is checked; if false -> assert + * @param ... Printf-based format string with arguments, extends printout. + */ +#ifdef NDEBUG +#define chatty_assert(cond, ...) +#else //!NDEBUG +#define chatty_assert(cond, ...) \ + do { \ + if (!(cond)) \ + panic("assert(" # cond ") failed: %s", csprintf(__VA_ARGS__)); \ + } while (0) +#endif // NDEBUG +#endif // __BASE_LOGGING_HH__ -- cgit v1.2.3