logging.hh revision 12375
111663Stushar@ece.gatech.edu/* 211663Stushar@ece.gatech.edu * Copyright (c) 2014, 2017 ARM Limited 311663Stushar@ece.gatech.edu * All rights reserved 411663Stushar@ece.gatech.edu * 511663Stushar@ece.gatech.edu * The license below extends only to copyright in the software and shall 611663Stushar@ece.gatech.edu * not be construed as granting a license to any other intellectual 711663Stushar@ece.gatech.edu * property including but not limited to intellectual property relating 811663Stushar@ece.gatech.edu * to a hardware implementation of the functionality of the software 911663Stushar@ece.gatech.edu * licensed hereunder. You may use the software subject to the license 1011663Stushar@ece.gatech.edu * terms below provided that you ensure that this notice is replicated 1111663Stushar@ece.gatech.edu * unmodified and in its entirety in all distributions of the software, 1211663Stushar@ece.gatech.edu * modified or unmodified, in source code or in binary form. 1311663Stushar@ece.gatech.edu * 1411663Stushar@ece.gatech.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 1511663Stushar@ece.gatech.edu * All rights reserved. 1611663Stushar@ece.gatech.edu * 1711663Stushar@ece.gatech.edu * Redistribution and use in source and binary forms, with or without 1811663Stushar@ece.gatech.edu * modification, are permitted provided that the following conditions are 1911663Stushar@ece.gatech.edu * met: redistributions of source code must retain the above copyright 2011663Stushar@ece.gatech.edu * notice, this list of conditions and the following disclaimer; 2111663Stushar@ece.gatech.edu * redistributions in binary form must reproduce the above copyright 2211663Stushar@ece.gatech.edu * notice, this list of conditions and the following disclaimer in the 2311663Stushar@ece.gatech.edu * documentation and/or other materials provided with the distribution; 2411663Stushar@ece.gatech.edu * neither the name of the copyright holders nor the names of its 2511663Stushar@ece.gatech.edu * contributors may be used to endorse or promote products derived from 2611663Stushar@ece.gatech.edu * this software without specific prior written permission. 2711663Stushar@ece.gatech.edu * 2811663Stushar@ece.gatech.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2911663Stushar@ece.gatech.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3011663Stushar@ece.gatech.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3111663Stushar@ece.gatech.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3211663Stushar@ece.gatech.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3311663Stushar@ece.gatech.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3411663Stushar@ece.gatech.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3511663Stushar@ece.gatech.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3611663Stushar@ece.gatech.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3711663Stushar@ece.gatech.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3811663Stushar@ece.gatech.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3911663Stushar@ece.gatech.edu * 4011663Stushar@ece.gatech.edu * Authors: Nathan Binkert 4111663Stushar@ece.gatech.edu * Dave Greene 4211663Stushar@ece.gatech.edu * Andreas Sandberg 4311663Stushar@ece.gatech.edu */ 4411663Stushar@ece.gatech.edu 4511663Stushar@ece.gatech.edu#ifndef __BASE_LOGGING_HH__ 4611663Stushar@ece.gatech.edu#define __BASE_LOGGING_HH__ 4711663Stushar@ece.gatech.edu 4811663Stushar@ece.gatech.edu#include <cassert> 4911663Stushar@ece.gatech.edu#include <sstream> 5011663Stushar@ece.gatech.edu#include <utility> 5111663Stushar@ece.gatech.edu 5211663Stushar@ece.gatech.edu#include "base/compiler.hh" 5311663Stushar@ece.gatech.edu#include "base/cprintf.hh" 5411663Stushar@ece.gatech.edu 5511663Stushar@ece.gatech.educlass Logger 5611666Stushar@ece.gatech.edu{ 5711666Stushar@ece.gatech.edu public: 5811666Stushar@ece.gatech.edu 5911666Stushar@ece.gatech.edu // Get a Logger for the specified type of message. 6011666Stushar@ece.gatech.edu static Logger &getPanic(); 6111666Stushar@ece.gatech.edu static Logger &getFatal(); 6211663Stushar@ece.gatech.edu static Logger &getWarn(); 6311663Stushar@ece.gatech.edu static Logger &getInfo(); 6411663Stushar@ece.gatech.edu static Logger &getHack(); 6511666Stushar@ece.gatech.edu 6611663Stushar@ece.gatech.edu enum LogLevel { 6711663Stushar@ece.gatech.edu PANIC, FATAL, WARN, INFO, HACK, 6811663Stushar@ece.gatech.edu NUM_LOG_LEVELS, 6911663Stushar@ece.gatech.edu }; 7011666Stushar@ece.gatech.edu 7111666Stushar@ece.gatech.edu static void 7211663Stushar@ece.gatech.edu setLevel(LogLevel ll) 7311663Stushar@ece.gatech.edu { 7411663Stushar@ece.gatech.edu getPanic().enabled = (ll >= PANIC); 7511663Stushar@ece.gatech.edu getFatal().enabled = (ll >= FATAL); 7611663Stushar@ece.gatech.edu getWarn().enabled = (ll >= WARN); 7711663Stushar@ece.gatech.edu getInfo().enabled = (ll >= INFO); 7811663Stushar@ece.gatech.edu getHack().enabled = (ll >= HACK); 7911663Stushar@ece.gatech.edu } 8011663Stushar@ece.gatech.edu 8113731Sandreas.sandberg@arm.com struct Loc 8211663Stushar@ece.gatech.edu { 8311663Stushar@ece.gatech.edu Loc(const char *file, int line) : file(file), line(line) {} 8411663Stushar@ece.gatech.edu const char *file; 8511663Stushar@ece.gatech.edu int line; 8611663Stushar@ece.gatech.edu }; 8711663Stushar@ece.gatech.edu 8811663Stushar@ece.gatech.edu Logger(const char *prefix) : enabled(true), prefix(prefix) 8911663Stushar@ece.gatech.edu { 9011663Stushar@ece.gatech.edu assert(prefix); 9111663Stushar@ece.gatech.edu } 9211663Stushar@ece.gatech.edu 9311666Stushar@ece.gatech.edu virtual ~Logger() {}; 9411666Stushar@ece.gatech.edu 9511663Stushar@ece.gatech.edu void 9611663Stushar@ece.gatech.edu print(const Loc &loc, const std::string &str) 9711663Stushar@ece.gatech.edu { 9811663Stushar@ece.gatech.edu std::stringstream ss; 9911663Stushar@ece.gatech.edu ss << prefix << str; 10011663Stushar@ece.gatech.edu if (str.length() && str.back() != '\n' && str.back() != '\r') 10111663Stushar@ece.gatech.edu ss << std::endl; 10211663Stushar@ece.gatech.edu if (!enabled) 10311666Stushar@ece.gatech.edu return; 10411666Stushar@ece.gatech.edu log(loc, ss.str()); 10511663Stushar@ece.gatech.edu } 10611663Stushar@ece.gatech.edu 10711663Stushar@ece.gatech.edu template<typename ...Args> void 10811663Stushar@ece.gatech.edu print(const Loc &loc, const char *format, const Args &...args) 10911663Stushar@ece.gatech.edu { 11011663Stushar@ece.gatech.edu std::stringstream ss; 11111663Stushar@ece.gatech.edu ccprintf(ss, format, args...); 11211663Stushar@ece.gatech.edu print(loc, ss.str()); 11313731Sandreas.sandberg@arm.com } 11413731Sandreas.sandberg@arm.com 11511663Stushar@ece.gatech.edu template<typename ...Args> void 11611663Stushar@ece.gatech.edu print(const Loc &loc, const std::string &format, const Args &...args) 11711663Stushar@ece.gatech.edu { 11811663Stushar@ece.gatech.edu print(loc, format.c_str(), args...); 11911663Stushar@ece.gatech.edu } 12011663Stushar@ece.gatech.edu 12111664Stushar@ece.gatech.edu // This helper is necessary since noreturn isn't inherited by virtual 12211664Stushar@ece.gatech.edu // functions, and gcc will get mad if a function calls panic and then 12311666Stushar@ece.gatech.edu // doesn't return. 12411663Stushar@ece.gatech.edu void exit_helper() M5_ATTR_NORETURN { exit(); ::abort(); } 12511663Stushar@ece.gatech.edu 12611663Stushar@ece.gatech.edu protected: 12711663Stushar@ece.gatech.edu bool enabled; 12813731Sandreas.sandberg@arm.com 12913731Sandreas.sandberg@arm.com virtual void log(const Loc &loc, std::string s) = 0; 13011663Stushar@ece.gatech.edu virtual void exit() { /* Fall through to the abort in exit_helper. */ } 13111663Stushar@ece.gatech.edu 13211663Stushar@ece.gatech.edu const char *prefix; 13311663Stushar@ece.gatech.edu}; 13411663Stushar@ece.gatech.edu 13511663Stushar@ece.gatech.edu 13611664Stushar@ece.gatech.edu#define base_message(logger, ...) \ 13711664Stushar@ece.gatech.edu logger.print(::Logger::Loc(__FILE__, __LINE__), __VA_ARGS__) 13811666Stushar@ece.gatech.edu 13911663Stushar@ece.gatech.edu/* 14011663Stushar@ece.gatech.edu * Only print the message the first time this expression is 14111663Stushar@ece.gatech.edu * encountered. i.e. This doesn't check the string itself and 14211663Stushar@ece.gatech.edu * prevent duplicate strings, this prevents the statement from 14313731Sandreas.sandberg@arm.com * happening more than once. So, even if the arguments change and that 14413731Sandreas.sandberg@arm.com * would have resulted in a different message thoes messages would be 14511663Stushar@ece.gatech.edu * supressed. 14611663Stushar@ece.gatech.edu */ 14711663Stushar@ece.gatech.edu#define base_message_once(...) do { \ 14811663Stushar@ece.gatech.edu static bool once = false; \ 14911663Stushar@ece.gatech.edu if (!once) { \ 15011663Stushar@ece.gatech.edu base_message(__VA_ARGS__); \ 15111664Stushar@ece.gatech.edu once = true; \ 15211664Stushar@ece.gatech.edu } \ 15311666Stushar@ece.gatech.edu } while (0) 15411663Stushar@ece.gatech.edu 15511663Stushar@ece.gatech.edu#define exit_message(logger, ...) \ 15611663Stushar@ece.gatech.edu do { \ 15711663Stushar@ece.gatech.edu base_message(logger, __VA_ARGS__); \ 15813731Sandreas.sandberg@arm.com logger.exit_helper(); \ 15913731Sandreas.sandberg@arm.com } while (0) 16011663Stushar@ece.gatech.edu 16111663Stushar@ece.gatech.edu/** 16211663Stushar@ece.gatech.edu * This implements a cprintf based panic() function. panic() should 16311663Stushar@ece.gatech.edu * be called when something happens that should never ever happen 16411663Stushar@ece.gatech.edu * regardless of what the user does (i.e., an acutal m5 bug). panic() 16511663Stushar@ece.gatech.edu * might call abort which can dump core or enter the debugger. 16611664Stushar@ece.gatech.edu */ 16711664Stushar@ece.gatech.edu#define panic(...) exit_message(::Logger::getPanic(), __VA_ARGS__) 16811666Stushar@ece.gatech.edu 16911663Stushar@ece.gatech.edu/** 17011663Stushar@ece.gatech.edu * This implements a cprintf based fatal() function. fatal() should 17111663Stushar@ece.gatech.edu * be called when the simulation cannot continue due to some condition 17211663Stushar@ece.gatech.edu * that is the user's fault (bad configuration, invalid arguments, 17311663Stushar@ece.gatech.edu * 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, ...) \ 186 do { \ 187 if ((cond)) { \ 188 panic("panic condition " # cond " occurred: %s", \ 189 csprintf(__VA_ARGS__)); \ 190 } \ 191 } while (0) 192 193 194/** 195 * Conditional fatal macro that checks the supplied condition and only causes a 196 * fatal error if the condition is true and allows the programmer to specify 197 * diagnostic printout. Useful to replace if + fatal, or if + print + assert, 198 * etc. 199 * 200 * @param cond Condition that is checked; if true -> fatal 201 * @param ... Printf-based format string with arguments, extends printout. 202 */ 203#define fatal_if(cond, ...) \ 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 */ 228#define warn_if(cond, ...) \ 229 do { \ 230 if ((cond)) \ 231 warn(__VA_ARGS__); \ 232 } while (0) 233 234/** 235 * The chatty assert macro will function like a normal assert, but will allow 236 * the specification of additional, helpful material to aid debugging why the 237 * assertion actually failed. Like the normal assertion, the chatty_assert 238 * will not be active in fast builds. 239 * 240 * @param cond Condition that is checked; if false -> assert 241 * @param ... Printf-based format string with arguments, extends printout. 242 */ 243#ifdef NDEBUG 244#define chatty_assert(cond, ...) 245#else //!NDEBUG 246#define chatty_assert(cond, ...) \ 247 do { \ 248 if (!(cond)) \ 249 panic("assert(" # cond ") failed: %s", csprintf(__VA_ARGS__)); \ 250 } while (0) 251#endif // NDEBUG 252#endif // __BASE_LOGGING_HH__ 253