/*
+ * Copyright (c) 2014 ARM Limited
+ * All rights reserved
+ *
* Copyright (c) 2001-2006 The Regents of The University of Michigan
* All rights reserved.
*
*
* Authors: Nathan Binkert
* Steve Reinhardt
+ * Andrew Bardsley
*/
#ifndef __BASE_TRACE_HH__
#define __BASE_TRACE_HH__
#include <string>
-#include <vector>
#include "base/cprintf.hh"
+#include "base/debug.hh"
#include "base/match.hh"
-#include "base/traceflags.hh"
-#include "sim/host.hh"
-#include "sim/root.hh"
+#include "base/types.hh"
+#include "sim/core.hh"
namespace Trace {
-std::ostream &output();
-void setOutput(const std::string &filename);
+/** Debug logging base class. Handles formatting and outputting
+ * time/name/message messages */
+class Logger
+{
+ protected:
+ /** Name match for objects to ignore */
+ ObjectMatch ignore;
+
+ public:
+ /** Log a single message */
+ template <typename ...Args>
+ void dprintf(Tick when, const std::string &name, const char *fmt,
+ const Args &...args)
+ {
+ if (!name.empty() && ignore.match(name))
+ return;
+
+ std::ostringstream line;
+ ccprintf(line, fmt, args...);
+ logMessage(when, name, line.str());
+ }
+
+ /** Dump a block of data of length len */
+ virtual void dump(Tick when, const std::string &name,
+ const void *d, int len);
+
+ /** Log formatted message */
+ virtual void logMessage(Tick when, const std::string &name,
+ const std::string &message) = 0;
+
+ /** Return an ostream that can be used to send messages to
+ * the 'same place' as formatted logMessage messages. This
+ * can be implemented to use a logger's underlying ostream,
+ * to provide an ostream which formats the output in some
+ * way, or just set to one of std::cout, std::cerr */
+ virtual std::ostream &getOstream() = 0;
+
+ /** Set objects to ignore */
+ void setIgnore(ObjectMatch &ignore_) { ignore = ignore_; }
+
+ virtual ~Logger() { }
+};
+
+/** Logging wrapper for ostreams with the format:
+ * <when>: <name>: <message-body> */
+class OstreamLogger : public Logger
+{
+ protected:
+ std::ostream &stream;
+
+ public:
+ OstreamLogger(std::ostream &stream_) : stream(stream_)
+ { }
-extern bool enabled;
-typedef std::vector<bool> FlagVec;
-extern FlagVec flags;
-inline bool IsOn(int t) { return flags[t]; }
-bool changeFlag(const char *str, bool value);
-void dumpStatus();
+ void logMessage(Tick when, const std::string &name,
+ const std::string &message) override;
-extern ObjectMatch ignore;
-extern const std::string DefaultName;
+ std::ostream &getOstream() override { return stream; }
+};
-void dprintf(Tick when, const std::string &name, const char *format,
- CPRINTF_DECLARATION);
-void dump(Tick when, const std::string &name, const void *data, int len);
+/** Get the current global debug logger. This takes ownership of the given
+ * logger which should be allocated using 'new' */
+Logger *getDebugLogger();
+
+/** Get the ostream from the current global logger */
+std::ostream &output();
-/* namespace Trace */ }
+/** Delete the current global logger and assign a new one */
+void setDebugLogger(Logger *logger);
+
+/** Enable/disable debug logging */
+void enable();
+void disable();
+
+} // namespace Trace
// This silly little class allows us to wrap a string in a functor
// object so that we can give a name() that DPRINTF will like
const std::string &operator()() const { return str; }
};
-inline const std::string &name() { return Trace::DefaultName; }
+// Return the global context name "global". This function gets called when
+// the DPRINTF macros are used in a context without a visible name() function
+const std::string &name();
+
+// Interface for things with names. (cf. SimObject but without other
+// functionality). This is useful when using DPRINTF
+class Named
+{
+ protected:
+ const std::string _name;
+
+ public:
+ Named(const std::string &name_) : _name(name_) { }
+
+ public:
+ const std::string &name() const { return _name; }
+};
//
// DPRINTF is a debugging trace facility that allows one to
#if TRACING_ON
-#define DTRACE(x) (Trace::IsOn(Trace::x) && Trace::enabled)
+#define DTRACE(x) (Debug::x)
+
+#define DDUMP(x, data, count) do { \
+ using namespace Debug; \
+ if (DTRACE(x)) \
+ Trace::getDebugLogger()->dump(curTick(), name(), data, count); \
+} while (0)
-#define DDUMP(x, data, count) do { \
- if (DTRACE(x)) \
- Trace::dump(curTick, name(), data, count); \
+#define DPRINTF(x, ...) do { \
+ using namespace Debug; \
+ if (DTRACE(x)) { \
+ Trace::getDebugLogger()->dprintf(curTick(), name(), \
+ __VA_ARGS__); \
+ } \
} while (0)
-#define DPRINTF(x, ...) do { \
- if (DTRACE(x)) \
- Trace::dprintf(curTick, name(), __VA_ARGS__); \
+#define DPRINTFS(x, s, ...) do { \
+ using namespace Debug; \
+ if (DTRACE(x)) { \
+ Trace::getDebugLogger()->dprintf(curTick(), s->name(), \
+ __VA_ARGS__); \
+ } \
} while (0)
-#define DPRINTFR(x, ...) do { \
- if (DTRACE(x)) \
- Trace::dprintf((Tick)-1, std::string(), __VA_ARGS__); \
+#define DPRINTFR(x, ...) do { \
+ using namespace Debug; \
+ if (DTRACE(x)) { \
+ Trace::getDebugLogger()->dprintf((Tick)-1, std::string(), \
+ __VA_ARGS__); \
+ } \
} while (0)
-#define DDUMPN(data, count) do { \
- Trace::dump(curTick, name(), data, count); \
+#define DDUMPN(data, count) do { \
+ Trace::getDebugLogger()->dump(curTick(), name(), data, count); \
} while (0)
-#define DPRINTFN(...) do { \
- Trace::dprintf(curTick, name(), __VA_ARGS__); \
+#define DPRINTFN(...) do { \
+ Trace::getDebugLogger()->dprintf(curTick(), name(), __VA_ARGS__); \
} while (0)
-#define DPRINTFNR(...) do { \
- Trace::dprintf((Tick)-1, string(), __VA_ARGS__); \
+#define DPRINTFNR(...) do { \
+ Trace::getDebugLogger()->dprintf((Tick)-1, string(), __VA_ARGS__); \
} while (0)
#else // !TRACING_ON
#define DTRACE(x) (false)
#define DDUMP(x, data, count) do {} while (0)
#define DPRINTF(x, ...) do {} while (0)
+#define DPRINTFS(x, ...) do {} while (0)
#define DPRINTFR(...) do {} while (0)
#define DDUMPN(data, count) do {} while (0)
#define DPRINTFN(...) do {} while (0)
#define DPRINTFNR(...) do {} while (0)
-#endif // TRACING_ON
+#endif // TRACING_ON
#endif // __BASE_TRACE_HH__