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 --- 32 unchanged lines hidden (view full) --- 41 * Dave Greene 42 * Andreas Sandberg 43 */ 44 45#ifndef __BASE_LOGGING_HH__ 46#define __BASE_LOGGING_HH__ 47 48#include <cassert> |
49#include <sstream> |
50#include <utility> 51 52#include "base/compiler.hh" 53#include "base/cprintf.hh" 54 |
55class Logger 56{ 57 public: |
58 59 // Get a Logger for the specified type of message. 60 static Logger &getPanic(); 61 static Logger &getFatal(); 62 static Logger &getWarn(); 63 static Logger &getInfo(); 64 static Logger &getHack(); 65 |
66 enum LogLevel { |
67 PANIC, FATAL, WARN, INFO, HACK, |
68 NUM_LOG_LEVELS, 69 }; 70 |
71 static void 72 setLevel(LogLevel ll) 73 { 74 getPanic().enabled = (ll >= PANIC); 75 getFatal().enabled = (ll >= FATAL); 76 getWarn().enabled = (ll >= WARN); 77 getInfo().enabled = (ll >= INFO); 78 getHack().enabled = (ll >= HACK); 79 } |
80 |
81 struct Loc 82 { 83 Loc(const char *file, int line) : file(file), line(line) {} 84 const char *file; 85 int line; 86 }; |
87 |
88 Logger(const char *prefix) : enabled(true), prefix(prefix) 89 { 90 assert(prefix); 91 } 92 |
93 virtual ~Logger() {}; 94 |
95 void 96 print(const Loc &loc, const std::string &str) |
97 { |
98 std::stringstream ss; 99 ss << prefix << str; 100 if (str.length() && str.back() != '\n' && str.back() != '\r') 101 ss << std::endl; |
102 if (!enabled) 103 return; |
104 log(loc, ss.str()); 105 } |
106 |
107 template<typename ...Args> void 108 print(const Loc &loc, const char *format, const Args &...args) 109 { 110 std::stringstream ss; 111 ccprintf(ss, format, args...); 112 print(loc, ss.str()); |
113 } 114 115 template<typename ...Args> void |
116 print(const Loc &loc, const std::string &format, const Args &...args) |
117 { |
118 print(loc, format.c_str(), args...); |
119 } 120 |
121 // This helper is necessary since noreturn isn't inherited by virtual 122 // functions, and gcc will get mad if a function calls panic and then 123 // doesn't return. 124 void exit_helper() M5_ATTR_NORETURN { exit(); ::abort(); } |
125 |
126 protected: |
127 bool enabled; |
128 |
129 virtual void log(const Loc &loc, std::string s) = 0; 130 virtual void exit() { /* Fall through to the abort in exit_helper. */ } 131 |
132 const char *prefix; 133}; 134 |
135 136#define base_message(logger, ...) \ 137 logger.print(::Logger::Loc(__FILE__, __LINE__), __VA_ARGS__) 138 139/* 140 * Only print the message the first time this expression is 141 * encountered. i.e. This doesn't check the string itself and 142 * prevent duplicate strings, this prevents the statement from 143 * happening more than once. So, even if the arguments change and that 144 * would have resulted in a different message thoes messages would be 145 * supressed. 146 */ 147#define base_message_once(...) do { \ 148 static bool once = false; \ 149 if (!once) { \ 150 base_message(__VA_ARGS__); \ 151 once = true; \ 152 } \ |
153 } while (0) 154 |
155#define exit_message(logger, ...) \ 156 do { \ 157 base_message(logger, __VA_ARGS__); \ 158 logger.exit_helper(); \ 159 } while (0) |
160 |
161/** 162 * This implements a cprintf based panic() function. panic() should 163 * be called when something happens that should never ever happen 164 * regardless of what the user does (i.e., an acutal m5 bug). panic() 165 * might call abort which can dump core or enter the debugger. 166 */ 167#define panic(...) exit_message(::Logger::getPanic(), __VA_ARGS__) |
168 169/** |
170 * This implements a cprintf based fatal() function. fatal() should 171 * be called when the simulation cannot continue due to some condition 172 * that is the user's fault (bad configuration, invalid arguments, 173 * etc.) and not a simulator bug. fatal() might call exit, unlike panic(). 174 */ 175#define fatal(...) exit_message(::Logger::getFatal(), __VA_ARGS__) 176 177/** |
178 * Conditional panic macro that checks the supplied condition and only panics 179 * if the condition is true and allows the programmer to specify diagnostic 180 * printout. Useful to replace if + panic, or if + print + assert, etc. 181 * 182 * @param cond Condition that is checked; if true -> panic 183 * @param ... Printf-based format string with arguments, extends printout. 184 */ 185#define panic_if(cond, ...) \ --- 18 unchanged lines hidden (view full) --- 204 do { \ 205 if ((cond)) { \ 206 fatal("fatal condition " # cond " occurred: %s", \ 207 csprintf(__VA_ARGS__)); \ 208 } \ 209 } while (0) 210 211 |
212#define warn(...) base_message(::Logger::getWarn(), __VA_ARGS__) 213#define inform(...) base_message(::Logger::getInfo(), __VA_ARGS__) 214#define hack(...) base_message(::Logger::getHack(), __VA_ARGS__) |
215 |
216#define warn_once(...) base_message_once(::Logger::getWarn(), __VA_ARGS__) 217#define inform_once(...) base_message_once(::Logger::getInfo(), __VA_ARGS__) 218#define hack_once(...) base_message_once(::Logger::getHack(), __VA_ARGS__) |
219 |
220/** 221 * Conditional warning macro that checks the supplied condition and 222 * only prints a warning if the condition is true. Useful to replace 223 * if + warn. 224 * 225 * @param cond Condition that is checked; if true -> warn 226 * @param ... Printf-based format string with arguments, extends printout. 227 */ --- 25 unchanged lines hidden --- |