/*
 * Copyright (c) 2014 ARM Limited
 * All rights reserved
 *
 * Copyright (c) 2001-2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Steve Reinhardt
 *          Andrew Bardsley
 */

#ifndef __BASE_TRACE_HH__
#define __BASE_TRACE_HH__

#include <string>

#include "base/cprintf.hh"
#include "base/debug.hh"
#include "base/match.hh"
#include "base/types.hh"
#include "sim/core.hh"

namespace Trace {

/** 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_)
    { }

    void logMessage(Tick when, const std::string &name,
                    const std::string &message) M5_ATTR_OVERRIDE;

    std::ostream &getOstream() M5_ATTR_OVERRIDE { return stream; }
};

/** 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();

/** Delete the current global logger and assign a new one */
void setDebugLogger(Logger *logger);

/** Enable debug logging */
extern bool enabled;

} // 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
struct StringWrap
{
    std::string str;
    StringWrap(const std::string &s) : str(s) {}
    const std::string &operator()() const { return str; }
};

// 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
// selectively enable tracing statements.  To use DPRINTF, there must
// be a function or functor called name() that returns a const
// std::string & in the current scope.
//
// If you desire that the automatic printing not occur, use DPRINTFR
// (R for raw)
//

#if TRACING_ON

#define DTRACE(x) ((Debug::x) && Trace::enabled)

#define DDUMP(x, data, count) do {                                        \
    using namespace Debug;                                                \
    if (DTRACE(x))                                                        \
        Trace::getDebugLogger()->dump(curTick(), name(), data, count);    \
} while (0)

#define DPRINTF(x, ...) do {                                              \
    using namespace Debug;                                                \
    if (DTRACE(x)) {                                                      \
        Trace::getDebugLogger()->dprintf(curTick(), name(),               \
            __VA_ARGS__);                                                 \
    }                                                                     \
} while (0)

#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 {                                             \
    using namespace Debug;                                                \
    if (DTRACE(x)) {                                                      \
        Trace::getDebugLogger()->dprintf((Tick)-1, std::string(),         \
            __VA_ARGS__);                                                 \
    }                                                                     \
} while (0)

#define DDUMPN(data, count) do {                                          \
    Trace::getDebugLogger()->dump(curTick(), name(), data, count);        \
} while (0)

#define DPRINTFN(...) do {                                                \
    Trace::getDebugLogger()->dprintf(curTick(), name(), __VA_ARGS__);     \
} while (0)

#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 // __BASE_TRACE_HH__
