/*
 * 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 "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__
