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