trace.hh revision 10475
12SN/A/* 210292SAndreas.Sandberg@ARM.com * Copyright (c) 2014 ARM Limited 310292SAndreas.Sandberg@ARM.com * All rights reserved 410292SAndreas.Sandberg@ARM.com * 54039Sbinkertn@umich.edu * Copyright (c) 2001-2006 The Regents of The University of Michigan 62SN/A * All rights reserved. 72SN/A * 82SN/A * Redistribution and use in source and binary forms, with or without 92SN/A * modification, are permitted provided that the following conditions are 102SN/A * met: redistributions of source code must retain the above copyright 112SN/A * notice, this list of conditions and the following disclaimer; 122SN/A * redistributions in binary form must reproduce the above copyright 132SN/A * notice, this list of conditions and the following disclaimer in the 142SN/A * documentation and/or other materials provided with the distribution; 152SN/A * neither the name of the copyright holders nor the names of its 162SN/A * contributors may be used to endorse or promote products derived from 172SN/A * this software without specific prior written permission. 182SN/A * 192SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 202SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 212SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 222SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 232SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 242SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 252SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 262SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 272SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 282SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 302665Ssaidi@eecs.umich.edu * 312665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 322665Ssaidi@eecs.umich.edu * Steve Reinhardt 3310475SAndrew.Bardsley@arm.com * Andrew Bardsley 342SN/A */ 352SN/A 361354SN/A#ifndef __BASE_TRACE_HH__ 371354SN/A#define __BASE_TRACE_HH__ 382SN/A 394046Sbinkertn@umich.edu#include <string> 402SN/A 4156SN/A#include "base/cprintf.hh" 428232Snate@binkert.org#include "base/debug.hh" 431031SN/A#include "base/match.hh" 446214Snate@binkert.org#include "base/types.hh" 454167Sbinkertn@umich.edu#include "sim/core.hh" 462SN/A 472SN/Anamespace Trace { 482SN/A 4910475SAndrew.Bardsley@arm.com/** Debug logging base class. Handles formatting and outputting 5010475SAndrew.Bardsley@arm.com * time/name/message messages */ 5110475SAndrew.Bardsley@arm.comclass Logger 5210475SAndrew.Bardsley@arm.com{ 5310475SAndrew.Bardsley@arm.com protected: 5410475SAndrew.Bardsley@arm.com /** Name match for objects to ignore */ 5510475SAndrew.Bardsley@arm.com ObjectMatch ignore; 568232Snate@binkert.org 5710475SAndrew.Bardsley@arm.com public: 5810475SAndrew.Bardsley@arm.com /** Log a single message */ 5910475SAndrew.Bardsley@arm.com template <typename ...Args> 6010475SAndrew.Bardsley@arm.com void dprintf(Tick when, const std::string &name, const char *fmt, 6110475SAndrew.Bardsley@arm.com const Args &...args) 6210475SAndrew.Bardsley@arm.com { 6310475SAndrew.Bardsley@arm.com if (!name.empty() && ignore.match(name)) 6410475SAndrew.Bardsley@arm.com return; 6510475SAndrew.Bardsley@arm.com 6610475SAndrew.Bardsley@arm.com std::ostringstream line; 6710475SAndrew.Bardsley@arm.com ccprintf(line, fmt, args...); 6810475SAndrew.Bardsley@arm.com logMessage(when, name, line.str()); 6910475SAndrew.Bardsley@arm.com } 7010475SAndrew.Bardsley@arm.com 7110475SAndrew.Bardsley@arm.com /** Dump a block of data of length len */ 7210475SAndrew.Bardsley@arm.com virtual void dump(Tick when, const std::string &name, 7310475SAndrew.Bardsley@arm.com const void *d, int len); 7410475SAndrew.Bardsley@arm.com 7510475SAndrew.Bardsley@arm.com /** Log formatted message */ 7610475SAndrew.Bardsley@arm.com virtual void logMessage(Tick when, const std::string &name, 7710475SAndrew.Bardsley@arm.com const std::string &message) = 0; 7810475SAndrew.Bardsley@arm.com 7910475SAndrew.Bardsley@arm.com /** Return an ostream that can be used to send messages to 8010475SAndrew.Bardsley@arm.com * the 'same place' as formatted logMessage messages. This 8110475SAndrew.Bardsley@arm.com * can be implemented to use a logger's underlying ostream, 8210475SAndrew.Bardsley@arm.com * to provide an ostream which formats the output in some 8310475SAndrew.Bardsley@arm.com * way, or just set to one of std::cout, std::cerr */ 8410475SAndrew.Bardsley@arm.com virtual std::ostream &getOstream() = 0; 8510475SAndrew.Bardsley@arm.com 8610475SAndrew.Bardsley@arm.com /** Set objects to ignore */ 8710475SAndrew.Bardsley@arm.com void setIgnore(ObjectMatch &ignore_) { ignore = ignore_; } 8810475SAndrew.Bardsley@arm.com 8910475SAndrew.Bardsley@arm.com virtual ~Logger() { } 9010475SAndrew.Bardsley@arm.com}; 9110475SAndrew.Bardsley@arm.com 9210475SAndrew.Bardsley@arm.com/** Logging wrapper for ostreams with the format: 9310475SAndrew.Bardsley@arm.com * <when>: <name>: <message-body> */ 9410475SAndrew.Bardsley@arm.comclass OstreamLogger : public Logger 9510475SAndrew.Bardsley@arm.com{ 9610475SAndrew.Bardsley@arm.com protected: 9710475SAndrew.Bardsley@arm.com std::ostream &stream; 9810475SAndrew.Bardsley@arm.com 9910475SAndrew.Bardsley@arm.com public: 10010475SAndrew.Bardsley@arm.com OstreamLogger(std::ostream &stream_) : stream(stream_) 10110475SAndrew.Bardsley@arm.com { } 10210475SAndrew.Bardsley@arm.com 10310475SAndrew.Bardsley@arm.com void logMessage(Tick when, const std::string &name, 10410475SAndrew.Bardsley@arm.com const std::string &message) M5_ATTR_OVERRIDE; 10510475SAndrew.Bardsley@arm.com 10610475SAndrew.Bardsley@arm.com std::ostream &getOstream() M5_ATTR_OVERRIDE { return stream; } 10710475SAndrew.Bardsley@arm.com}; 10810475SAndrew.Bardsley@arm.com 10910475SAndrew.Bardsley@arm.com/** Get the current global debug logger. This takes ownership of the given 11010475SAndrew.Bardsley@arm.com * logger which should be allocated using 'new' */ 11110475SAndrew.Bardsley@arm.comLogger *getDebugLogger(); 11210475SAndrew.Bardsley@arm.com 11310475SAndrew.Bardsley@arm.com/** Get the ostream from the current global logger */ 1144046Sbinkertn@umich.edustd::ostream &output(); 1152SN/A 11610475SAndrew.Bardsley@arm.com/** Delete the current global logger and assign a new one */ 11710475SAndrew.Bardsley@arm.comvoid setDebugLogger(Logger *logger); 11810475SAndrew.Bardsley@arm.com 11910475SAndrew.Bardsley@arm.com/** Enable debug logging */ 1204046Sbinkertn@umich.eduextern bool enabled; 1212SN/A 1227811Ssteve.reinhardt@amd.com} // namespace Trace 1234039Sbinkertn@umich.edu 1241070SN/A// This silly little class allows us to wrap a string in a functor 1251070SN/A// object so that we can give a name() that DPRINTF will like 1261070SN/Astruct StringWrap 1271070SN/A{ 1281070SN/A std::string str; 1291070SN/A StringWrap(const std::string &s) : str(s) {} 1301070SN/A const std::string &operator()() const { return str; } 1311070SN/A}; 1321070SN/A 13310475SAndrew.Bardsley@arm.com// Return the global context name "global". This function gets called when 13410475SAndrew.Bardsley@arm.com// the DPRINTF macros are used in a context without a visible name() function 13510475SAndrew.Bardsley@arm.comconst std::string &name(); 1362SN/A 13710259SAndrew.Bardsley@arm.com// Interface for things with names. (cf. SimObject but without other 13810259SAndrew.Bardsley@arm.com// functionality). This is useful when using DPRINTF 13910259SAndrew.Bardsley@arm.comclass Named 14010259SAndrew.Bardsley@arm.com{ 14110259SAndrew.Bardsley@arm.com protected: 14210259SAndrew.Bardsley@arm.com const std::string _name; 14310259SAndrew.Bardsley@arm.com 14410259SAndrew.Bardsley@arm.com public: 14510259SAndrew.Bardsley@arm.com Named(const std::string &name_) : _name(name_) { } 14610259SAndrew.Bardsley@arm.com 14710259SAndrew.Bardsley@arm.com public: 14810259SAndrew.Bardsley@arm.com const std::string &name() const { return _name; } 14910259SAndrew.Bardsley@arm.com}; 15010259SAndrew.Bardsley@arm.com 1512SN/A// 1522SN/A// DPRINTF is a debugging trace facility that allows one to 1532SN/A// selectively enable tracing statements. To use DPRINTF, there must 1542SN/A// be a function or functor called name() that returns a const 1552SN/A// std::string & in the current scope. 1562SN/A// 1572SN/A// If you desire that the automatic printing not occur, use DPRINTFR 1582SN/A// (R for raw) 1592SN/A// 1602SN/A 1612SN/A#if TRACING_ON 1622SN/A 1638232Snate@binkert.org#define DTRACE(x) ((Debug::x) && Trace::enabled) 1642SN/A 16510475SAndrew.Bardsley@arm.com#define DDUMP(x, data, count) do { \ 16610475SAndrew.Bardsley@arm.com using namespace Debug; \ 16710475SAndrew.Bardsley@arm.com if (DTRACE(x)) \ 16810475SAndrew.Bardsley@arm.com Trace::getDebugLogger()->dump(curTick(), name(), data, count); \ 1692SN/A} while (0) 1702SN/A 17110475SAndrew.Bardsley@arm.com#define DPRINTF(x, ...) do { \ 17210475SAndrew.Bardsley@arm.com using namespace Debug; \ 17310475SAndrew.Bardsley@arm.com if (DTRACE(x)) { \ 17410475SAndrew.Bardsley@arm.com Trace::getDebugLogger()->dprintf(curTick(), name(), \ 17510475SAndrew.Bardsley@arm.com __VA_ARGS__); \ 17610475SAndrew.Bardsley@arm.com } \ 1772SN/A} while (0) 1782SN/A 17910475SAndrew.Bardsley@arm.com#define DPRINTFS(x, s, ...) do { \ 18010475SAndrew.Bardsley@arm.com using namespace Debug; \ 18110475SAndrew.Bardsley@arm.com if (DTRACE(x)) { \ 18210475SAndrew.Bardsley@arm.com Trace::getDebugLogger()->dprintf(curTick(), s->name(), \ 18310475SAndrew.Bardsley@arm.com __VA_ARGS__); \ 18410475SAndrew.Bardsley@arm.com } \ 1855806Ssaidi@eecs.umich.edu} while (0) 1865806Ssaidi@eecs.umich.edu 18710475SAndrew.Bardsley@arm.com#define DPRINTFR(x, ...) do { \ 18810475SAndrew.Bardsley@arm.com using namespace Debug; \ 18910475SAndrew.Bardsley@arm.com if (DTRACE(x)) { \ 19010475SAndrew.Bardsley@arm.com Trace::getDebugLogger()->dprintf((Tick)-1, std::string(), \ 19110475SAndrew.Bardsley@arm.com __VA_ARGS__); \ 19210475SAndrew.Bardsley@arm.com } \ 1932SN/A} while (0) 1942SN/A 19510475SAndrew.Bardsley@arm.com#define DDUMPN(data, count) do { \ 19610475SAndrew.Bardsley@arm.com Trace::getDebugLogger()->dump(curTick(), name(), data, count); \ 1974046Sbinkertn@umich.edu} while (0) 1984046Sbinkertn@umich.edu 19910475SAndrew.Bardsley@arm.com#define DPRINTFN(...) do { \ 20010475SAndrew.Bardsley@arm.com Trace::getDebugLogger()->dprintf(curTick(), name(), __VA_ARGS__); \ 2012SN/A} while (0) 2022SN/A 20310475SAndrew.Bardsley@arm.com#define DPRINTFNR(...) do { \ 20410475SAndrew.Bardsley@arm.com Trace::getDebugLogger()->dprintf((Tick)-1, string(), __VA_ARGS__); \ 205507SN/A} while (0) 206507SN/A 2072SN/A#else // !TRACING_ON 2082SN/A 2092SN/A#define DTRACE(x) (false) 2104046Sbinkertn@umich.edu#define DDUMP(x, data, count) do {} while (0) 2114041Sbinkertn@umich.edu#define DPRINTF(x, ...) do {} while (0) 2125806Ssaidi@eecs.umich.edu#define DPRINTFS(x, ...) do {} while (0) 2134041Sbinkertn@umich.edu#define DPRINTFR(...) do {} while (0) 2144046Sbinkertn@umich.edu#define DDUMPN(data, count) do {} while (0) 2154041Sbinkertn@umich.edu#define DPRINTFN(...) do {} while (0) 2164041Sbinkertn@umich.edu#define DPRINTFNR(...) do {} while (0) 2172SN/A 2185543Ssaidi@eecs.umich.edu#endif // TRACING_ON 2192SN/A 2201354SN/A#endif // __BASE_TRACE_HH__ 221