X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcpu%2Fbase_dyn_inst.hh;h=6d9a5325332387808e395b1d688fe432b037d28f;hb=8d476b41e60cfdadbde50c2d9ae54900455f6098;hp=6ea00dd3d664c0b94260e53bf30cee959b2d6c57;hpb=1d1837ee9855f06af963f96948c33623bf905e7d;p=gem5.git diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 6ea00dd3d..6d9a53253 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -1,4 +1,17 @@ /* + * Copyright (c) 2011,2013 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2006 The Regents of The University of Michigan * Copyright (c) 2009 The University of Edinburgh * All rights reserved. @@ -33,35 +46,36 @@ #ifndef __CPU_BASE_DYN_INST_HH__ #define __CPU_BASE_DYN_INST_HH__ +#include #include #include #include +#include -#include "arch/faults.hh" -#include "base/fast_alloc.hh" +#include "arch/generic/tlb.hh" +#include "arch/utility.hh" #include "base/trace.hh" -#include "config/full_system.hh" #include "config/the_isa.hh" +#include "cpu/checker/cpu.hh" #include "cpu/o3/comm.hh" +#include "cpu/exec_context.hh" #include "cpu/exetrace.hh" #include "cpu/inst_seq.hh" #include "cpu/op_class.hh" #include "cpu/static_inst.hh" #include "cpu/translation.hh" #include "mem/packet.hh" +#include "mem/request.hh" +#include "sim/byteswap.hh" #include "sim/system.hh" -#include "sim/tlb.hh" /** * @file * Defines a dynamic instruction context. */ -// Forward declaration. -class StaticInstPtr; - template -class BaseDynInst : public FastAlloc, public RefCounted +class BaseDynInst : public ExecContext, public RefCounted { public: // Typedef for the CPU. @@ -70,94 +84,29 @@ class BaseDynInst : public FastAlloc, public RefCounted // Logical register index type. typedef TheISA::RegIndex RegIndex; - // Integer register type. - typedef TheISA::IntReg IntReg; - // Floating point register type. - typedef TheISA::FloatReg FloatReg; // The DynInstPtr type. typedef typename Impl::DynInstPtr DynInstPtr; + typedef RefCountingPtr > BaseDynInstPtr; // The list of instructions iterator type. typedef typename std::list::iterator ListIt; enum { MaxInstSrcRegs = TheISA::MaxInstSrcRegs, /// Max source regs - MaxInstDestRegs = TheISA::MaxInstDestRegs, /// Max dest regs + MaxInstDestRegs = TheISA::MaxInstDestRegs /// Max dest regs }; - /** The StaticInst used by this BaseDynInst. */ - StaticInstPtr staticInst; - - //////////////////////////////////////////// - // - // INSTRUCTION EXECUTION - // - //////////////////////////////////////////// - /** InstRecord that tracks this instructions. */ - Trace::InstRecord *traceData; - - void demapPage(Addr vaddr, uint64_t asn) - { - cpu->demapPage(vaddr, asn); - } - void demapInstPage(Addr vaddr, uint64_t asn) - { - cpu->demapPage(vaddr, asn); - } - void demapDataPage(Addr vaddr, uint64_t asn) - { - cpu->demapPage(vaddr, asn); - } - - /** - * Does a read to a given address. - * @param addr The address to read. - * @param data The read's data is written into this parameter. - * @param flags The request's flags. - * @return Returns any fault due to the read. - */ - template - Fault read(Addr addr, T &data, unsigned flags); - - Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags); - - /** - * Does a write to a given address. - * @param data The data to be written. - * @param addr The address to write to. - * @param flags The request's flags. - * @param res The result of the write (for load locked/store conditionals). - * @return Returns any fault due to the write. - */ - template - Fault write(T data, Addr addr, unsigned flags, uint64_t *res); - - Fault writeBytes(uint8_t *data, unsigned size, - Addr addr, unsigned flags, uint64_t *res); - - /** Splits a request in two if it crosses a dcache block. */ - void splitRequest(RequestPtr req, RequestPtr &sreqLow, - RequestPtr &sreqHigh); - - /** Initiate a DTB address translation. */ - void initiateTranslation(RequestPtr req, RequestPtr sreqLow, - RequestPtr sreqHigh, uint64_t *res, - BaseTLB::Mode mode); - - /** Finish a DTB address translation. */ - void finishTranslation(WholeTranslationState *state); - - void prefetch(Addr addr, unsigned flags); - void writeHint(Addr addr, int size, unsigned flags); - Fault copySrcTranslate(Addr src); - Fault copy(Addr dest); - - /** @todo: Consider making this private. */ - public: - /** The sequence number of the instruction. */ - InstSeqNum seqNum; + union Result { + uint64_t integer; + double dbl; + void set(uint64_t i) { integer = i; } + void set(double d) { dbl = d; } + void get(uint64_t& i) { i = integer; } + void get(double& d) { d = dbl; } + }; + protected: enum Status { IqEntry, /// Instruction is in the IQ RobEntry, /// Instruction is in the ROB @@ -184,131 +133,240 @@ class BaseDynInst : public FastAlloc, public RefCounted NumStatus }; - /** The status of this BaseDynInst. Several bits can be set. */ - std::bitset status; - - /** The thread this instruction is from. */ - ThreadID threadNumber; + enum Flags { + TranslationStarted, + TranslationCompleted, + PossibleLoadViolation, + HitExternalSnoop, + EffAddrValid, + RecordResult, + Predicate, + PredTaken, + /** Whether or not the effective address calculation is completed. + * @todo: Consider if this is necessary or not. + */ + EACalcDone, + IsStrictlyOrdered, + ReqMade, + MemOpDone, + MaxFlags + }; - /** data address space ID, for loads & stores. */ - short asid; + public: + /** The sequence number of the instruction. */ + InstSeqNum seqNum; - /** How many source registers are ready. */ - unsigned readyRegs; + /** The StaticInst used by this BaseDynInst. */ + const StaticInstPtr staticInst; /** Pointer to the Impl's CPU object. */ ImplCPU *cpu; + BaseCPU *getCpuPtr() { return cpu; } + /** Pointer to the thread state. */ ImplState *thread; /** The kind of fault this instruction has generated. */ Fault fault; - /** Pointer to the data for the memory access. */ - uint8_t *memData; + /** InstRecord that tracks this instructions. */ + Trace::InstRecord *traceData; - /** The effective virtual address (lds & stores only). */ - Addr effAddr; + protected: + /** The result of the instruction; assumes an instruction can have many + * destination registers. + */ + std::queue instResult; - /** Is the effective virtual address valid. */ - bool effAddrValid; + /** PC state for this instruction. */ + TheISA::PCState pc; - /** The effective physical address. */ - Addr physEffAddr; + /* An amalgamation of a lot of boolean values into one */ + std::bitset instFlags; - /** Effective virtual address for a copy source. */ - Addr copySrcEffAddr; + /** The status of this BaseDynInst. Several bits can be set. */ + std::bitset status; - /** Effective physical address for a copy source. */ - Addr copySrcPhysEffAddr; + /** Whether or not the source register is ready. + * @todo: Not sure this should be here vs the derived class. + */ + std::bitset _readySrcRegIdx; - /** The memory request flags (from translation). */ - unsigned memReqFlags; + public: + /** The thread this instruction is from. */ + ThreadID threadNumber; - union Result { - uint64_t integer; -// float fp; - double dbl; - }; + /** Iterator pointing to this BaseDynInst in the list of all insts. */ + ListIt instListIt; - /** The result of the instruction; assumes for now that there's only one - * destination register. - */ - Result instResult; + ////////////////////// Branch Data /////////////// + /** Predicted PC state after this instruction. */ + TheISA::PCState predPC; - /** Records changes to result? */ - bool recordResult; + /** The Macroop if one exists */ + const StaticInstPtr macroop; - /** PC of this instruction. */ - Addr PC; + /** How many source registers are ready. */ + uint8_t readyRegs; - /** Micro PC of this instruction. */ - Addr microPC; + public: + /////////////////////// Load Store Data ////////////////////// + /** The effective virtual address (lds & stores only). */ + Addr effAddr; - protected: - /** Next non-speculative PC. It is not filled in at fetch, but rather - * once the target of the branch is truly known (either decode or - * execute). + /** The effective physical address. */ + Addr physEffAddrLow; + + /** The effective physical address + * of the second request for a split request */ - Addr nextPC; + Addr physEffAddrHigh; - /** Next non-speculative NPC. Target PC for Mips or Sparc. */ - Addr nextNPC; + /** The memory request flags (from translation). */ + unsigned memReqFlags; - /** Next non-speculative micro PC. */ - Addr nextMicroPC; + /** data address space ID, for loads & stores. */ + short asid; - /** Predicted next PC. */ - Addr predPC; + /** The size of the request */ + uint8_t effSize; - /** Predicted next NPC. */ - Addr predNPC; + /** Pointer to the data for the memory access. */ + uint8_t *memData; - /** Predicted next microPC */ - Addr predMicroPC; + /** Load queue index. */ + int16_t lqIdx; - /** If this is a branch that was predicted taken */ - bool predTaken; + /** Store queue index. */ + int16_t sqIdx; - public: -#ifdef DEBUG - void dumpSNList(); -#endif + /////////////////////// TLB Miss ////////////////////// + /** + * Saved memory requests (needed when the DTB address translation is + * delayed due to a hw page table walk). + */ + RequestPtr savedReq; + RequestPtr savedSreqLow; + RequestPtr savedSreqHigh; - /** Whether or not the source register is ready. - * @todo: Not sure this should be here vs the derived class. + /////////////////////// Checker ////////////////////// + // Need a copy of main request pointer to verify on writes. + RequestPtr reqToVerify; + + private: + /** Instruction effective address. + * @todo: Consider if this is necessary or not. */ - bool _readySrcRegIdx[MaxInstSrcRegs]; + Addr instEffAddr; protected: /** Flattened register index of the destination registers of this * instruction. */ - TheISA::RegIndex _flatDestRegIdx[TheISA::MaxInstDestRegs]; - - /** Flattened register index of the source registers of this - * instruction. - */ - TheISA::RegIndex _flatSrcRegIdx[TheISA::MaxInstSrcRegs]; + std::array _flatDestRegIdx; /** Physical register index of the destination registers of this * instruction. */ - PhysRegIndex _destRegIdx[TheISA::MaxInstDestRegs]; + std::array _destRegIdx; /** Physical register index of the source registers of this * instruction. */ - PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs]; + std::array _srcRegIdx; /** Physical register index of the previous producers of the * architected destinations. */ - PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs]; + std::array _prevDestRegIdx; + + + public: + /** Records changes to result? */ + void recordResult(bool f) { instFlags[RecordResult] = f; } + + /** Is the effective virtual address valid. */ + bool effAddrValid() const { return instFlags[EffAddrValid]; } + + /** Whether or not the memory operation is done. */ + bool memOpDone() const { return instFlags[MemOpDone]; } + void memOpDone(bool f) { instFlags[MemOpDone] = f; } + + + //////////////////////////////////////////// + // + // INSTRUCTION EXECUTION + // + //////////////////////////////////////////// + + void demapPage(Addr vaddr, uint64_t asn) + { + cpu->demapPage(vaddr, asn); + } + void demapInstPage(Addr vaddr, uint64_t asn) + { + cpu->demapPage(vaddr, asn); + } + void demapDataPage(Addr vaddr, uint64_t asn) + { + cpu->demapPage(vaddr, asn); + } + + Fault initiateMemRead(Addr addr, unsigned size, Request::Flags flags); + + Fault writeMem(uint8_t *data, unsigned size, Addr addr, + Request::Flags flags, uint64_t *res); + + /** Splits a request in two if it crosses a dcache block. */ + void splitRequest(RequestPtr req, RequestPtr &sreqLow, + RequestPtr &sreqHigh); + + /** Initiate a DTB address translation. */ + void initiateTranslation(RequestPtr req, RequestPtr sreqLow, + RequestPtr sreqHigh, uint64_t *res, + BaseTLB::Mode mode); + + /** Finish a DTB address translation. */ + void finishTranslation(WholeTranslationState *state); + + /** True if the DTB address translation has started. */ + bool translationStarted() const { return instFlags[TranslationStarted]; } + void translationStarted(bool f) { instFlags[TranslationStarted] = f; } + + /** True if the DTB address translation has completed. */ + bool translationCompleted() const { return instFlags[TranslationCompleted]; } + void translationCompleted(bool f) { instFlags[TranslationCompleted] = f; } + + /** True if this address was found to match a previous load and they issued + * out of order. If that happend, then it's only a problem if an incoming + * snoop invalidate modifies the line, in which case we need to squash. + * If nothing modified the line the order doesn't matter. + */ + bool possibleLoadViolation() const { return instFlags[PossibleLoadViolation]; } + void possibleLoadViolation(bool f) { instFlags[PossibleLoadViolation] = f; } + + /** True if the address hit a external snoop while sitting in the LSQ. + * If this is true and a older instruction sees it, this instruction must + * reexecute + */ + bool hitExternalSnoop() const { return instFlags[HitExternalSnoop]; } + void hitExternalSnoop(bool f) { instFlags[HitExternalSnoop] = f; } + + /** + * Returns true if the DTB address translation is being delayed due to a hw + * page table walk. + */ + bool isTranslationDelayed() const + { + return (translationStarted() && !translationCompleted()); + } public: +#ifdef DEBUG + void dumpSNList(); +#endif /** Returns the physical register index of the i'th destination * register. @@ -321,6 +379,7 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns the physical register index of the i'th source register. */ PhysRegIndex renamedSrcRegIdx(int idx) const { + assert(TheISA::MaxInstSrcRegs > idx); return _srcRegIdx[idx]; } @@ -332,12 +391,6 @@ class BaseDynInst : public FastAlloc, public RefCounted return _flatDestRegIdx[idx]; } - /** Returns the flattened register index of the i'th source register */ - TheISA::RegIndex flattenedSrcRegIdx(int idx) const - { - return _flatSrcRegIdx[idx]; - } - /** Returns the physical register index of the previous physical register * that remapped to the same logical register index. */ @@ -366,13 +419,6 @@ class BaseDynInst : public FastAlloc, public RefCounted _srcRegIdx[idx] = renamed_src; } - /** Flattens a source architectural register index into a logical index. - */ - void flattenSrcReg(int idx, TheISA::RegIndex flattened_src) - { - _flatSrcRegIdx[idx] = flattened_src; - } - /** Flattens a destination architectural register index into a logical * index. */ @@ -382,32 +428,19 @@ class BaseDynInst : public FastAlloc, public RefCounted } /** BaseDynInst constructor given a binary instruction. * @param staticInst A StaticInstPtr to the underlying instruction. - * @param PC The PC of the instruction. - * @param pred_PC The predicted next PC. - * @param pred_NPC The predicted next NPC. - * @param seq_num The sequence number of the instruction. - * @param cpu Pointer to the instruction's CPU. - */ - BaseDynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC, - Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC, - InstSeqNum seq_num, ImplCPU *cpu); - - /** BaseDynInst constructor given a binary instruction. - * @param inst The binary instruction. - * @param PC The PC of the instruction. - * @param pred_PC The predicted next PC. - * @param pred_NPC The predicted next NPC. + * @param pc The PC state for the instruction. + * @param predPC The predicted next PC state for the instruction. * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - BaseDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, Addr microPC, - Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC, - InstSeqNum seq_num, ImplCPU *cpu); + BaseDynInst(const StaticInstPtr &staticInst, const StaticInstPtr ¯oop, + TheISA::PCState pc, TheISA::PCState predPC, + InstSeqNum seq_num, ImplCPU *cpu); /** BaseDynInst constructor given a StaticInst pointer. * @param _staticInst The StaticInst for this BaseDynInst. */ - BaseDynInst(StaticInstPtr &_staticInst); + BaseDynInst(const StaticInstPtr &staticInst, const StaticInstPtr ¯oop); /** BaseDynInst destructor. */ ~BaseDynInst(); @@ -424,13 +457,19 @@ class BaseDynInst : public FastAlloc, public RefCounted void dump(std::string &outstring); /** Read this CPU's ID. */ - int cpuId() { return cpu->cpuId(); } + int cpuId() const { return cpu->cpuId(); } + + /** Read this CPU's Socket ID. */ + uint32_t socketId() const { return cpu->socketId(); } + + /** Read this CPU's data requestor ID */ + MasterID masterId() const { return cpu->dataMasterId(); } /** Read this context's system-wide ID **/ - int contextId() { return thread->contextId(); } + ContextID contextId() const { return thread->contextId(); } /** Returns the fault type. */ - Fault getFault() { return fault; } + Fault getFault() const { return fault; } /** Checks whether or not this instruction has had its branch target * calculated yet. For now it is not utilized and is hacked to be @@ -439,63 +478,40 @@ class BaseDynInst : public FastAlloc, public RefCounted */ bool doneTargCalc() { return false; } - /** Returns the next PC. This could be the speculative next PC if it is - * called prior to the actual branch target being calculated. - */ - Addr readNextPC() { return nextPC; } - - /** Returns the next NPC. This could be the speculative next NPC if it is - * called prior to the actual branch target being calculated. - */ - Addr readNextNPC() - { -#if ISA_HAS_DELAY_SLOT - return nextNPC; -#else - return nextPC + sizeof(TheISA::MachInst); -#endif - } - - Addr readNextMicroPC() - { - return nextMicroPC; - } - /** Set the predicted target of this current instruction. */ - void setPredTarg(Addr predicted_PC, Addr predicted_NPC, - Addr predicted_MicroPC) + void setPredTarg(const TheISA::PCState &_predPC) { - predPC = predicted_PC; - predNPC = predicted_NPC; - predMicroPC = predicted_MicroPC; + predPC = _predPC; } + const TheISA::PCState &readPredTarg() { return predPC; } + /** Returns the predicted PC immediately after the branch. */ - Addr readPredPC() { return predPC; } + Addr predInstAddr() { return predPC.instAddr(); } /** Returns the predicted PC two instructions after the branch */ - Addr readPredNPC() { return predNPC; } + Addr predNextInstAddr() { return predPC.nextInstAddr(); } /** Returns the predicted micro PC after the branch */ - Addr readPredMicroPC() { return predMicroPC; } + Addr predMicroPC() { return predPC.microPC(); } /** Returns whether the instruction was predicted taken or not. */ bool readPredTaken() { - return predTaken; + return instFlags[PredTaken]; } void setPredTaken(bool predicted_taken) { - predTaken = predicted_taken; + instFlags[PredTaken] = predicted_taken; } /** Returns whether the instruction mispredicted. */ bool mispredicted() { - return readPredPC() != readNextPC() || - readPredNPC() != readNextNPC() || - readPredMicroPC() != readNextMicroPC(); + TheISA::PCState tempPC = pc; + TheISA::advancePC(tempPC, staticInst); + return !(tempPC == predPC); } // @@ -509,7 +525,6 @@ class BaseDynInst : public FastAlloc, public RefCounted { return staticInst->isStoreConditional(); } bool isInstPrefetch() const { return staticInst->isInstPrefetch(); } bool isDataPrefetch() const { return staticInst->isDataPrefetch(); } - bool isCopy() const { return staticInst->isCopy(); } bool isInteger() const { return staticInst->isInteger(); } bool isFloating() const { return staticInst->isFloating(); } bool isControl() const { return staticInst->isControl(); } @@ -526,6 +541,7 @@ class BaseDynInst : public FastAlloc, public RefCounted { return staticInst->isSerializeBefore() || status[SerializeBefore]; } bool isSerializeAfter() const { return staticInst->isSerializeAfter() || status[SerializeAfter]; } + bool isSquashAfter() const { return staticInst->isSquashAfter(); } bool isMemBarrier() const { return staticInst->isMemBarrier(); } bool isWriteBarrier() const { return staticInst->isWriteBarrier(); } bool isNonSpeculative() const { return staticInst->isNonSpeculative(); } @@ -572,7 +588,8 @@ class BaseDynInst : public FastAlloc, public RefCounted OpClass opClass() const { return staticInst->opClass(); } /** Returns the branch target address. */ - Addr branchTarget() const { return staticInst->branchTarget(PC); } + TheISA::PCState branchTarget() const + { return staticInst->branchTarget(pc); } /** Returns the number of source registers. */ int8_t numSrcRegs() const { return staticInst->numSrcRegs(); } @@ -584,6 +601,7 @@ class BaseDynInst : public FastAlloc, public RefCounted // for machines with separate int & FP reg files int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); } int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); } + int8_t numCCDestRegs() const { return staticInst->numCCDestRegs(); } /** Returns the logical register index of the i'th destination register. */ RegIndex destRegIdx(int i) const { return staticInst->destRegIdx(i); } @@ -591,56 +609,56 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns the logical register index of the i'th source register. */ RegIndex srcRegIdx(int i) const { return staticInst->srcRegIdx(i); } - /** Returns the result of an integer instruction. */ - uint64_t readIntResult() { return instResult.integer; } + /** Pops a result off the instResult queue */ + template + void popResult(T& t) + { + if (!instResult.empty()) { + instResult.front().get(t); + instResult.pop(); + } + } - /** Returns the result of a floating point instruction. */ - float readFloatResult() { return (float)instResult.dbl; } + /** Read the most recent result stored by this instruction */ + template + void readResult(T& t) + { + instResult.back().get(t); + } - /** Returns the result of a floating point (double) instruction. */ - double readDoubleResult() { return instResult.dbl; } + /** Pushes a result onto the instResult queue */ + template + void setResult(T t) + { + if (instFlags[RecordResult]) { + Result instRes; + instRes.set(t); + instResult.push(instRes); + } + } /** Records an integer register being set to a value. */ - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) + void setIntRegOperand(const StaticInst *si, int idx, IntReg val) { - if (recordResult) - instResult.integer = val; + setResult(val); } - /** Records an fp register being set to a value. */ - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, - int width) + /** Records a CC register being set to a value. */ + void setCCRegOperand(const StaticInst *si, int idx, CCReg val) { - if (recordResult) { - if (width == 32) - instResult.dbl = (double)val; - else if (width == 64) - instResult.dbl = val; - else - panic("Unsupported width!"); - } + setResult(val); } /** Records an fp register being set to a value. */ void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) { - if (recordResult) - instResult.dbl = (double)val; + setResult(val); } /** Records an fp register being set to an integer value. */ - void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val, - int width) + void setFloatRegOperandBits(const StaticInst *si, int idx, FloatRegBits val) { - if (recordResult) - instResult.integer = val; - } - - /** Records an fp register being set to an integer value. */ - void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val) - { - if (recordResult) - instResult.integer = val; + setResult(val); } /** Records that one of the source registers is ready. */ @@ -769,29 +787,33 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns whether or not this instruction is squashed in the ROB. */ bool isSquashedInROB() const { return status[SquashedInROB]; } + /** Read the PC state of this instruction. */ + TheISA::PCState pcState() const { return pc; } + + /** Set the PC state of this instruction. */ + void pcState(const TheISA::PCState &val) { pc = val; } + /** Read the PC of this instruction. */ - const Addr readPC() const { return PC; } + Addr instAddr() const { return pc.instAddr(); } + + /** Read the PC of the next instruction. */ + Addr nextInstAddr() const { return pc.nextInstAddr(); } /**Read the micro PC of this instruction. */ - const Addr readMicroPC() const { return microPC; } + Addr microPC() const { return pc.microPC(); } - /** Set the next PC of this instruction (its actual target). */ - void setNextPC(Addr val) + bool readPredicate() { - nextPC = val; + return instFlags[Predicate]; } - /** Set the next NPC of this instruction (the target in Mips or Sparc).*/ - void setNextNPC(Addr val) + void setPredicate(bool val) { -#if ISA_HAS_DELAY_SLOT - nextNPC = val; -#endif - } + instFlags[Predicate] = val; - void setNextMicroPC(Addr val) - { - nextMicroPC = val; + if (traceData) { + traceData->setPredicate(val); + } } /** Sets the ASID. */ @@ -806,54 +828,24 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns the thread context. */ ThreadContext *tcBase() { return thread->getTC(); } - private: - /** Instruction effective address. - * @todo: Consider if this is necessary or not. - */ - Addr instEffAddr; - - /** Whether or not the effective address calculation is completed. - * @todo: Consider if this is necessary or not. - */ - bool eaCalcDone; - - /** Is this instruction's memory access uncacheable. */ - bool isUncacheable; - - /** Has this instruction generated a memory request. */ - bool reqMade; - public: /** Sets the effective address. */ - void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; } + void setEA(Addr ea) { instEffAddr = ea; instFlags[EACalcDone] = true; } /** Returns the effective address. */ - const Addr &getEA() const { return instEffAddr; } + Addr getEA() const { return instEffAddr; } /** Returns whether or not the eff. addr. calculation has been completed. */ - bool doneEACalc() { return eaCalcDone; } + bool doneEACalc() { return instFlags[EACalcDone]; } /** Returns whether or not the eff. addr. source registers are ready. */ bool eaSrcsReady(); - /** Whether or not the memory operation is done. */ - bool memOpDone; - - /** Is this instruction's memory access uncacheable. */ - bool uncacheable() { return isUncacheable; } + /** Is this instruction's memory access strictly ordered? */ + bool strictlyOrdered() const { return instFlags[IsStrictlyOrdered]; } /** Has this instruction generated a memory request. */ - bool hasRequest() { return reqMade; } - - public: - /** Load queue index. */ - int16_t lqIdx; - - /** Store queue index. */ - int16_t sqIdx; - - /** Iterator pointing to this BaseDynInst in the list of all insts. */ - ListIt instListIt; + bool hasRequest() { return instFlags[ReqMade]; } /** Returns iterator to this instruction in the list of all insts. */ ListIt &getInstListIt() { return instListIt; } @@ -863,121 +855,130 @@ class BaseDynInst : public FastAlloc, public RefCounted public: /** Returns the number of consecutive store conditional failures. */ - unsigned readStCondFailures() + unsigned int readStCondFailures() const { return thread->storeCondFailures; } /** Sets the number of consecutive store conditional failures. */ - void setStCondFailures(unsigned sc_failures) + void setStCondFailures(unsigned int sc_failures) { thread->storeCondFailures = sc_failures; } + + public: + // monitor/mwait funtions + void armMonitor(Addr address) { cpu->armMonitor(threadNumber, address); } + bool mwait(PacketPtr pkt) { return cpu->mwait(threadNumber, pkt); } + void mwaitAtomic(ThreadContext *tc) + { return cpu->mwaitAtomic(threadNumber, tc, cpu->dtb); } + AddressMonitor *getAddrMonitor() + { return cpu->getCpuAddrMonitor(threadNumber); } }; template Fault -BaseDynInst::readBytes(Addr addr, uint8_t *data, - unsigned size, unsigned flags) +BaseDynInst::initiateMemRead(Addr addr, unsigned size, + Request::Flags flags) { - reqMade = true; - Request *req = new Request(asid, addr, size, flags, this->PC, - thread->contextId(), threadNumber); - + instFlags[ReqMade] = true; + Request *req = NULL; Request *sreqLow = NULL; Request *sreqHigh = NULL; - // Only split the request if the ISA supports unaligned accesses. - if (TheISA::HasUnalignedMemAcc) { - splitRequest(req, sreqLow, sreqHigh); - } - initiateTranslation(req, sreqLow, sreqHigh, NULL, BaseTLB::Read); - - if (fault == NoFault) { - effAddr = req->getVaddr(); - effAddrValid = true; - fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx); + if (instFlags[ReqMade] && translationStarted()) { + req = savedReq; + sreqLow = savedSreqLow; + sreqHigh = savedSreqHigh; } else { - // Commit will have to clean up whatever happened. Set this - // instruction as executed. - this->setExecuted(); - } + req = new Request(asid, addr, size, flags, masterId(), this->pc.instAddr(), + thread->contextId()); - if (fault != NoFault) { - // Return a fixed value to keep simulation deterministic even - // along misspeculated paths. - bzero(data, size); - } + req->taskId(cpu->taskId()); - if (traceData) { - traceData->setAddr(addr); + // Only split the request if the ISA supports unaligned accesses. + if (TheISA::HasUnalignedMemAcc) { + splitRequest(req, sreqLow, sreqHigh); + } + initiateTranslation(req, sreqLow, sreqHigh, NULL, BaseTLB::Read); } - return fault; -} - -template -template -inline Fault -BaseDynInst::read(Addr addr, T &data, unsigned flags) -{ - Fault fault = readBytes(addr, (uint8_t *)&data, sizeof(T), flags); - - data = TheISA::gtoh(data); - - if (traceData) { - traceData->setData(data); + if (translationCompleted()) { + if (fault == NoFault) { + effAddr = req->getVaddr(); + effSize = size; + instFlags[EffAddrValid] = true; + + if (cpu->checker) { + if (reqToVerify != NULL) { + delete reqToVerify; + } + reqToVerify = new Request(*req); + } + fault = cpu->read(req, sreqLow, sreqHigh, lqIdx); + } else { + // Commit will have to clean up whatever happened. Set this + // instruction as executed. + this->setExecuted(); + } } + if (traceData) + traceData->setMem(addr, size, flags); + return fault; } template Fault -BaseDynInst::writeBytes(uint8_t *data, unsigned size, - Addr addr, unsigned flags, uint64_t *res) +BaseDynInst::writeMem(uint8_t *data, unsigned size, Addr addr, + Request::Flags flags, uint64_t *res) { - if (traceData) { - traceData->setAddr(addr); - } - - reqMade = true; - Request *req = new Request(asid, addr, size, flags, this->PC, - thread->contextId(), threadNumber); + if (traceData) + traceData->setMem(addr, size, flags); + instFlags[ReqMade] = true; + Request *req = NULL; Request *sreqLow = NULL; Request *sreqHigh = NULL; - // Only split the request if the ISA supports unaligned accesses. - if (TheISA::HasUnalignedMemAcc) { - splitRequest(req, sreqLow, sreqHigh); + if (instFlags[ReqMade] && translationStarted()) { + req = savedReq; + sreqLow = savedSreqLow; + sreqHigh = savedSreqHigh; + } else { + req = new Request(asid, addr, size, flags, masterId(), this->pc.instAddr(), + thread->contextId()); + + req->taskId(cpu->taskId()); + + // Only split the request if the ISA supports unaligned accesses. + if (TheISA::HasUnalignedMemAcc) { + splitRequest(req, sreqLow, sreqHigh); + } + initiateTranslation(req, sreqLow, sreqHigh, res, BaseTLB::Write); } - initiateTranslation(req, sreqLow, sreqHigh, res, BaseTLB::Write); - if (fault == NoFault) { + if (fault == NoFault && translationCompleted()) { effAddr = req->getVaddr(); - effAddrValid = true; + effSize = size; + instFlags[EffAddrValid] = true; + + if (cpu->checker) { + if (reqToVerify != NULL) { + delete reqToVerify; + } + reqToVerify = new Request(*req); + } fault = cpu->write(req, sreqLow, sreqHigh, data, sqIdx); } return fault; } -template -template -inline Fault -BaseDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res) -{ - if (traceData) { - traceData->setData(data); - } - data = TheISA::htog(data); - return writeBytes((uint8_t *)&data, sizeof(T), addr, flags, res); -} - template inline void BaseDynInst::splitRequest(RequestPtr req, RequestPtr &sreqLow, RequestPtr &sreqHigh) { // Check to see if the request crosses the next level block boundary. - unsigned block_size = cpu->getDcachePort()->peerBlockSize(); + unsigned block_size = cpu->cacheLineSize(); Addr addr = req->getVaddr(); Addr split_addr = roundDown(addr + req->getSize() - 1, block_size); assert(split_addr <= addr || split_addr - addr < block_size); @@ -994,26 +995,55 @@ BaseDynInst::initiateTranslation(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh, uint64_t *res, BaseTLB::Mode mode) { + translationStarted(true); + if (!TheISA::HasUnalignedMemAcc || sreqLow == NULL) { WholeTranslationState *state = new WholeTranslationState(req, NULL, res, mode); // One translation if the request isn't split. - DataTranslation > *trans = - new DataTranslation >(this, state); + DataTranslation *trans = + new DataTranslation(this, state); + cpu->dtb->translateTiming(req, thread->getTC(), trans, mode); + + if (!translationCompleted()) { + // The translation isn't yet complete, so we can't possibly have a + // fault. Overwrite any existing fault we might have from a previous + // execution of this instruction (e.g. an uncachable load that + // couldn't execute because it wasn't at the head of the ROB). + fault = NoFault; + + // Save memory requests. + savedReq = state->mainReq; + savedSreqLow = state->sreqLow; + savedSreqHigh = state->sreqHigh; + } } else { WholeTranslationState *state = new WholeTranslationState(req, sreqLow, sreqHigh, NULL, res, mode); // Two translations when the request is split. - DataTranslation > *stransLow = - new DataTranslation >(this, state, 0); - DataTranslation > *stransHigh = - new DataTranslation >(this, state, 1); + DataTranslation *stransLow = + new DataTranslation(this, state, 0); + DataTranslation *stransHigh = + new DataTranslation(this, state, 1); cpu->dtb->translateTiming(sreqLow, thread->getTC(), stransLow, mode); cpu->dtb->translateTiming(sreqHigh, thread->getTC(), stransHigh, mode); + + if (!translationCompleted()) { + // The translation isn't yet complete, so we can't possibly have a + // fault. Overwrite any existing fault we might have from a previous + // execution of this instruction (e.g. an uncachable load that + // couldn't execute because it wasn't at the head of the ROB). + fault = NoFault; + + // Save memory requests. + savedReq = state->mainReq; + savedSreqLow = state->sreqLow; + savedSreqHigh = state->sreqHigh; + } } } @@ -1023,11 +1053,18 @@ BaseDynInst::finishTranslation(WholeTranslationState *state) { fault = state->getFault(); - if (state->isUncacheable()) - isUncacheable = true; + instFlags[IsStrictlyOrdered] = state->isStrictlyOrdered(); if (fault == NoFault) { - physEffAddr = state->getPaddr(); + // save Paddr for a single req + physEffAddrLow = state->getPaddr(); + + // case for the request that has been split + if (state->isSplit) { + physEffAddrLow = state->sreqLow->getPaddr(); + physEffAddrHigh = state->sreqHigh->getPaddr(); + } + memReqFlags = state->getFlags(); if (state->mainReq->isCondSwap()) { @@ -1039,6 +1076,8 @@ BaseDynInst::finishTranslation(WholeTranslationState *state) state->deleteReqs(); } delete state; + + translationCompleted(true); } #endif // __CPU_BASE_DYN_INST_HH__