logging.hh revision 12334
1/* 2 * Copyright (c) 2014, 2017 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2002-2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Nathan Binkert 41 * Dave Greene 42 * Andreas Sandberg 43 */ 44 45#ifndef __BASE_LOGGING_HH__ 46#define __BASE_LOGGING_HH__ 47 48#include <cassert> 49#include <cstdlib> 50#include <iostream> 51#include <utility> 52 53#include "base/compiler.hh" 54#include "base/cprintf.hh" 55 56#if defined(__SUNPRO_CC) 57#define __FUNCTION__ "how to fix me?" 58#endif 59 60class Logger 61{ 62 public: 63 enum LogLevel { 64 PANIC = 0, 65 FATAL, 66 WARN, 67 INFO, 68 HACK, 69 NUM_LOG_LEVELS, 70 }; 71 72 /** 73 * Set the active log level. 74 * 75 * All levels that are lower or equal to the selected log level 76 * will be activated. 77 * 78 * @param ll Maximum log level to print 79 */ 80 static void setLevel(LogLevel ll); 81 82 /** 83 * Get a Logger corresponding to a specific log level 84 * 85 * @param ll Log level to access 86 * @return Reference to the requested logger 87 */ 88 static Logger &get(LogLevel ll); 89 90 public: 91 Logger(std::ostream &stream, const char *prefix); 92 virtual ~Logger() {}; 93 94 template<typename ...Args> void 95 print(const char *func, const char *file, int line, 96 const char *format, const Args &...args) 97 { 98 if (!enabled) 99 return; 100 101 if (prefix) 102 stream << prefix << ": "; 103 ccprintf(stream, format, args...); 104 105 printEpilogue(func, file, line, format); 106 } 107 108 template<typename ...Args> void 109 print(const char *func, const char *file, int line, 110 const std::string &format, const Args &...args) 111 { 112 print(func, file, line, format.c_str(), args...); 113 } 114 115 protected: 116 virtual void printEpilogue(const char *func, const char *file, int line, 117 const char *format); 118 119 public: 120 bool enabled; 121 bool verbose; 122 123 protected: 124 std::ostream &stream; 125 const char *prefix; 126}; 127 128#define exit_message(logger, code, ...) \ 129 do { \ 130 logger.print(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ 131 if (code < 0) \ 132 ::abort(); \ 133 else \ 134 ::exit(code); \ 135 } while (0) 136 137// 138// This implements a cprintf based panic() function. panic() should 139// be called when something happens that should never ever happen 140// regardless of what the user does (i.e., an acutal m5 bug). panic() 141// calls abort which can dump core or enter the debugger. 142// 143// 144#define panic(...) exit_message(::Logger::get(::Logger::PANIC), -1, \ 145 __VA_ARGS__) 146 147// 148// This implements a cprintf based fatal() function. fatal() should 149// be called when the simulation cannot continue due to some condition 150// that is the user's fault (bad configuration, invalid arguments, 151// etc.) and not a simulator bug. fatal() calls abort() like 152// panic() does. 153// 154#define fatal(...) exit_message(::Logger::get(::Logger::FATAL), 1, \ 155 __VA_ARGS__) 156 157/** 158 * Conditional panic macro that checks the supplied condition and only panics 159 * if the condition is true and allows the programmer to specify diagnostic 160 * printout. Useful to replace if + panic, or if + print + assert, etc. 161 * 162 * @param cond Condition that is checked; if true -> panic 163 * @param ... Printf-based format string with arguments, extends printout. 164 */ 165#define panic_if(cond, ...) \ 166 do { \ 167 if ((cond)) { \ 168 panic("panic condition " # cond " occurred: %s", \ 169 csprintf(__VA_ARGS__)); \ 170 } \ 171 } while (0) 172 173 174/** 175 * Conditional fatal macro that checks the supplied condition and only causes a 176 * fatal error if the condition is true and allows the programmer to specify 177 * diagnostic printout. Useful to replace if + fatal, or if + print + assert, 178 * etc. 179 * 180 * @param cond Condition that is checked; if true -> fatal 181 * @param ... Printf-based format string with arguments, extends printout. 182 */ 183#define fatal_if(cond, ...) \ 184 do { \ 185 if ((cond)) { \ 186 fatal("fatal condition " # cond " occurred: %s", \ 187 csprintf(__VA_ARGS__)); \ 188 } \ 189 } while (0) 190 191 192#define base_message(logger, ...) \ 193 logger.print(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) 194 195// Only print the message the first time this expression is 196// encountered. i.e. This doesn't check the string itself and 197// prevent duplicate strings, this prevents the statement from 198// happening more than once. So, even if the arguments change and that 199// would have resulted in a different message thoes messages would be 200// supressed. 201#define base_message_once(...) do { \ 202 static bool once = false; \ 203 if (!once) { \ 204 base_message(__VA_ARGS__); \ 205 once = true; \ 206 } \ 207 } while (0) 208 209 210#define warn(...) \ 211 base_message(::Logger::get(::Logger::WARN), __VA_ARGS__) 212#define inform(...) \ 213 base_message(::Logger::get(::Logger::INFO), __VA_ARGS__) 214#define hack(...) \ 215 base_message(::Logger::get(::Logger::HACK), __VA_ARGS__) 216 217#define warn_once(...) \ 218 base_message_once(::Logger::get(::Logger::WARN), __VA_ARGS__) 219#define inform_once(...) \ 220 base_message_once(::Logger::get(::Logger::INFO), __VA_ARGS__) 221#define hack_once(...) \ 222 base_message_once(::Logger::get(::Logger::HACK), __VA_ARGS__) 223 224/** 225 * Conditional warning macro that checks the supplied condition and 226 * only prints a warning if the condition is true. Useful to replace 227 * if + warn. 228 * 229 * @param cond Condition that is checked; if true -> warn 230 * @param ... Printf-based format string with arguments, extends printout. 231 */ 232#define warn_if(cond, ...) \ 233 do { \ 234 if ((cond)) \ 235 warn(__VA_ARGS__); \ 236 } while (0) 237 238/** 239 * The chatty assert macro will function like a normal assert, but will allow 240 * the specification of additional, helpful material to aid debugging why the 241 * assertion actually failed. Like the normal assertion, the chatty_assert 242 * will not be active in fast builds. 243 * 244 * @param cond Condition that is checked; if false -> assert 245 * @param ... Printf-based format string with arguments, extends printout. 246 */ 247#ifdef NDEBUG 248#define chatty_assert(cond, ...) 249#else //!NDEBUG 250#define chatty_assert(cond, ...) \ 251 do { \ 252 if (!(cond)) \ 253 panic("assert(" # cond ") failed: %s", csprintf(__VA_ARGS__)); \ 254 } while (0) 255#endif // NDEBUG 256#endif // __BASE_LOGGING_HH__ 257