/* * 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 #include template class OzoneDynInst : public BaseDynInst { public: // Typedefs typedef typename Impl::OzoneCPU OzoneCPU; typedef typename OzoneCPU::ImplState ImplState; // Typedef for DynInstPtr. This is really just a RefCountingPtr. 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::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 &getDependents() { return dependents; } std::vector &getMemDeps() { return memDependents; } std::list &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 *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 dependents; std::vector memDependents; std::list 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, int width) { switch(width) { case 32: return srcInsts[idx]->readFloatResult(); case 64: return srcInsts[idx]->readDoubleResult(); default: panic("Width not supported"); return 0; } } FloatReg readFloatRegOperand(const StaticInst *si, int idx) { return srcInsts[idx]->readFloatResult(); } FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, int width) { return srcInsts[idx]->readIntResult(); } 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::setIntReg(si, idx, val); } void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, int width) { BaseDynInst::setFloatReg(si, idx, val, width); } void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) { BaseDynInst::setFloatReg(si, idx, val); } void setFloatRegOperandBits(const StaticInst *si, int idx, FloatRegBits val, int width) { BaseDynInst::setFloatRegBits(si, idx, val); } void setFloatRegOperandBits(const StaticInst *si, int idx, FloatRegBits val) { BaseDynInst::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__