/*
 * Copyright (c) 2001-2005 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.
 */

#ifndef __EXETRACE_HH__
#define __EXETRACE_HH__

#include <fstream>
#include <vector>

#include "sim/host.hh"
#include "cpu/inst_seq.hh"	// for InstSeqNum
#include "base/trace.hh"
#include "cpu/exec_context.hh"
#include "cpu/static_inst.hh"

class BaseCPU;


namespace Trace {

class InstRecord : public Record
{
  protected:
    typedef TheISA::IntRegFile IntRegFile;

    // The following fields are initialized by the constructor and
    // thus guaranteed to be valid.
    BaseCPU *cpu;
    // need to make this ref-counted so it doesn't go away before we
    // dump the record
    StaticInstPtr staticInst;
    Addr PC;
    bool misspeculating;
    unsigned thread;

    // The remaining fields are only valid for particular instruction
    // types (e.g, addresses for memory ops) or when particular
    // options are enabled (e.g., tracing full register contents).
    // Each data field has an associated valid flag to indicate
    // whether the data field is valid.
    Addr addr;
    bool addr_valid;

    union {
        uint64_t as_int;
        double as_double;
    } data;
    enum {
        DataInvalid = 0,
        DataInt8 = 1,	// set to equal number of bytes
        DataInt16 = 2,
        DataInt32 = 4,
        DataInt64 = 8,
        DataDouble = 3
    } data_status;

    InstSeqNum fetch_seq;
    bool fetch_seq_valid;

    InstSeqNum cp_seq;
    bool cp_seq_valid;

    struct iRegFile {
        IntRegFile regs;
    };
    iRegFile *iregs;
    bool regs_valid;

  public:
    InstRecord(Tick _cycle, BaseCPU *_cpu,
               const StaticInstPtr &_staticInst,
               Addr _pc, bool spec, int _thread)
        : Record(_cycle), cpu(_cpu), staticInst(_staticInst), PC(_pc),
          misspeculating(spec), thread(_thread)
    {
        data_status = DataInvalid;
        addr_valid = false;
        regs_valid = false;

        fetch_seq_valid = false;
        cp_seq_valid = false;
    }

    virtual ~InstRecord() { }

    virtual void dump(std::ostream &outs);

    void setAddr(Addr a) { addr = a; addr_valid = true; }

    void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; }
    void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; }
    void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; }
    void setData(uint8_t d) { data.as_int = d; data_status = DataInt8; }

    void setData(int64_t d) { setData((uint64_t)d); }
    void setData(int32_t d) { setData((uint32_t)d); }
    void setData(int16_t d) { setData((uint16_t)d); }
    void setData(int8_t d)  { setData((uint8_t)d); }

    void setData(double d) { data.as_double = d; data_status = DataDouble; }

    void setFetchSeq(InstSeqNum seq)
    { fetch_seq = seq; fetch_seq_valid = true; }

    void setCPSeq(InstSeqNum seq)
    { cp_seq = seq; cp_seq_valid = true; }

    void setRegs(const IntRegFile &regs);

    void finalize() { theLog.append(this); }

    enum InstExecFlagBits {
        TRACE_MISSPEC = 0,
        PRINT_CYCLE,
        PRINT_OP_CLASS,
        PRINT_THREAD_NUM,
        PRINT_RESULT_DATA,
        PRINT_EFF_ADDR,
        PRINT_INT_REGS,
        PRINT_FETCH_SEQ,
        PRINT_CP_SEQ,
        INTEL_FORMAT,
        NUM_BITS
    };

    static std::vector<bool> flags;
    static std::string trace_system;

    static void setParams();

    static bool traceMisspec() { return flags[TRACE_MISSPEC]; }
};


inline void
InstRecord::setRegs(const IntRegFile &regs)
{
    if (!iregs)
      iregs = new iRegFile;

    memcpy(&iregs->regs, &regs, sizeof(IntRegFile));
    regs_valid = true;
}

inline
InstRecord *
getInstRecord(Tick cycle, ExecContext *xc, BaseCPU *cpu,
              const StaticInstPtr staticInst,
              Addr pc, int thread = 0)
{
    if (DTRACE(InstExec) &&
        (InstRecord::traceMisspec() || !xc->misspeculating())) {
        return new InstRecord(cycle, cpu, staticInst, pc,
                              xc->misspeculating(), thread);
    }

    return NULL;
}


}

#endif // __EXETRACE_HH__
