/*
 * Copyright (c) 2005-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: Kevin Lim
 */

#ifndef __CPU_OZONE_DYN_INST_HH__
#define __CPU_OZONE_DYN_INST_HH__

#include "arch/isa_traits.hh"
#include "arch/types.hh"
#include "config/full_system.hh"
#include "config/the_isa.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
#include "cpu/ozone/cpu.hh"   // MUST include this
#include "cpu/ozone/ozone_impl.hh"

#include <list>
#include <vector>

template <class Impl>
class OzoneDynInst : public BaseDynInst<Impl>
{
  public:
    // Typedefs
    typedef typename Impl::OzoneCPU OzoneCPU;

    typedef typename OzoneCPU::ImplState ImplState;

    // Typedef for DynInstPtr.  This is really just a RefCountingPtr<OoODynInst>.
    typedef typename Impl::DynInstPtr DynInstPtr;

    typedef TheISA::ExtMachInst ExtMachInst;
    typedef TheISA::MachInst MachInst;
    typedef TheISA::FloatReg FloatReg;
    typedef TheISA::FloatRegBits FloatRegBits;
    typedef TheISA::MiscReg MiscReg;
    typedef typename std::list<DynInstPtr>::iterator ListIt;

    // Note that this is duplicated from the BaseDynInst class; I'm
    // simply not sure the enum would carry through so I could use it
    // in array declarations in this class.
    enum {
        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,
        MaxInstDestRegs = TheISA::MaxInstDestRegs
    };

    OzoneDynInst(OzoneCPU *cpu);

    OzoneDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC,
                 InstSeqNum seq_num, OzoneCPU *cpu);

    OzoneDynInst(StaticInstPtr inst);

    ~OzoneDynInst();

    void setSrcInst(DynInstPtr &newSrcInst, int regIdx)
    { srcInsts[regIdx] = newSrcInst; }

    bool srcInstReady(int regIdx);

    void setPrevDestInst(DynInstPtr &oldDestInst, int regIdx)
    { prevDestInst[regIdx] = oldDestInst; }

    DynInstPtr &getPrevDestInst(int regIdx)
    { return prevDestInst[regIdx]; }

    void addDependent(DynInstPtr &dependent_inst);

    std::vector<DynInstPtr> &getDependents() { return dependents; }
    std::vector<DynInstPtr> &getMemDeps() { return memDependents; }
    std::list<DynInstPtr> &getMemSrcs() { return srcMemInsts; }

    void wakeDependents();

    void wakeMemDependents();

    void addMemDependent(DynInstPtr &inst) { memDependents.push_back(inst); }

    void addSrcMemInst(DynInstPtr &inst) { srcMemInsts.push_back(inst); }

    void markMemInstReady(OzoneDynInst<Impl> *inst);

    // For now I will remove instructions from the list when they wake
    // up.  In the future, you only really need a counter.
    bool memDepReady() { return srcMemInsts.empty(); }

  private:
    void initInstPtrs();

    std::vector<DynInstPtr> dependents;

    std::vector<DynInstPtr> memDependents;

    std::list<DynInstPtr> srcMemInsts;

    /** The instruction that produces the value of the source
     *  registers.  These may be NULL if the value has already been
     *  read from the source instruction.
     */
    DynInstPtr srcInsts[MaxInstSrcRegs];

    /**
     *  Previous rename instruction for this destination.
     */
    DynInstPtr prevDestInst[MaxInstSrcRegs];

  public:

    Fault initiateAcc();

    Fault completeAcc(PacketPtr pkt);

    // The register accessor methods provide the index of the
    // instruction's operand (e.g., 0 or 1), not the architectural
    // register index, to simplify the implementation of register
    // renaming.  We find the architectural register index by indexing
    // into the instruction's own operand index table.  Note that a
    // raw pointer to the StaticInst is provided instead of a
    // ref-counted StaticInstPtr to redice overhead.  This is fine as
    // long as these methods don't copy the pointer into any long-term
    // storage (which is pretty hard to imagine they would have reason
    // to do).

    uint64_t readIntRegOperand(const StaticInst *si, int idx)
    {
        return srcInsts[idx]->readIntResult();
    }

    FloatReg readFloatRegOperand(const StaticInst *si, int idx)
    {
        return srcInsts[idx]->readFloatResult();
    }

    FloatReg readFloatRegOperand(const StaticInst *si, int idx)
    {
        return srcInsts[idx]->readFloatResult();
    }

    FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
    {
        return srcInsts[idx]->readIntResult();
    }

    /** @todo: Make results into arrays so they can handle multiple dest
     *  registers.
     */
    void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
    {
        BaseDynInst<Impl>::setIntReg(si, idx, val);
    }

    void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
    {
        BaseDynInst<Impl>::setFloatReg(si, idx, val);
    }

    void setFloatRegOperandBits(const StaticInst *si, int idx,
                                FloatRegBits val)
    {
        BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
    }

    void setIntResult(uint64_t result) { this->instResult.integer = result; }
    void setDoubleResult(double result) { this->instResult.dbl = result; }

    bool srcsReady();
    bool eaSrcsReady();

    Fault execute();

    Fault executeEAComp()
    { return NoFault; }

    Fault executeMemAcc()
    { return this->staticInst->memAccInst()->execute(this, this->traceData); }

    void clearDependents();

    void clearMemDependents();

  public:
    // ISA stuff
    MiscReg readMiscRegNoEffect(int misc_reg);

    MiscReg readMiscReg(int misc_reg);

    void setMiscRegNoEffect(int misc_reg, const MiscReg &val);

    void setMiscReg(int misc_reg, const MiscReg &val);

#if FULL_SYSTEM
    Fault hwrei();
    void trap(Fault fault);
    bool simPalCheck(int palFunc);
#else
    void syscall(uint64_t &callnum);
#endif

    ListIt iqIt;
    bool iqItValid;
};

#endif // __CPU_OZONE_DYN_INST_HH__
