diff -r cf1afc88070f -r 22c55ce9cf87 src/cpu/base_dyn_inst.hh --- a/src/cpu/base_dyn_inst.hh Tue Mar 01 03:00:42 2011 -0800 +++ b/src/cpu/base_dyn_inst.hh Tue Mar 01 16:49:04 2011 -0500 @@ -124,88 +124,15 @@ 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); - - /** True if the DTB address translation has started. */ - bool translationStarted; - - /** True if the DTB address translation has completed. */ - bool translationCompleted; - - /** - * Returns true if the DTB address translation is being delayed due to a hw - * page table walk. - */ - bool isTranslationDelayed() const - { - return (translationStarted && !translationCompleted); - } - - /** - * Saved memory requests (needed when the DTB address translation is - * delayed due to a hw page table walk). - */ - RequestPtr savedReq; - RequestPtr savedSreqLow; - RequestPtr savedSreqHigh; - /** @todo: Consider making this private. */ public: /** The sequence number of the instruction. */ InstSeqNum seqNum; - enum Status { - IqEntry, /// Instruction is in the IQ - RobEntry, /// Instruction is in the ROB - LsqEntry, /// Instruction is in the LSQ + enum BaseStatus { + Executed, /// Instruction has executed + Squashed, /// Instruction is squashed Completed, /// Instruction has completed - ResultReady, /// Instruction has its result - CanIssue, /// Instruction can issue and execute - Issued, /// Instruction has issued - Executed, /// Instruction has executed - CanCommit, /// Instruction can commit - AtCommit, /// Instruction has reached commit - Committed, /// Instruction has committed - Squashed, /// Instruction is squashed - SquashedInIQ, /// Instruction is squashed in the IQ - SquashedInLSQ, /// Instruction is squashed in the LSQ - SquashedInROB, /// Instruction is squashed in the ROB RecoverInst, /// Is a recover instruction BlockingInst, /// Is a blocking instruction ThreadsyncWait, /// Is a thread synchronization instruction @@ -213,11 +140,9 @@ /// instructions ahead of it SerializeAfter, /// Needs to serialize instructions behind it SerializeHandled, /// Serialization has been handled - NumStatus + NumBaseStatus }; - - /** The status of this BaseDynInst. Several bits can be set. */ - std::bitset status; + std::bitset status; /** The thread this instruction is from. */ ThreadID threadNumber; @@ -258,20 +183,6 @@ /** The memory request flags (from translation). */ unsigned memReqFlags; - union Result { - uint64_t integer; -// float fp; - double dbl; - }; - - /** The result of the instruction; assumes for now that there's only one - * destination register. - */ - Result instResult; - - /** Records changes to result? */ - bool recordResult; - /** Did this instruction execute, or is it predicated false */ bool predicate; @@ -317,27 +228,7 @@ */ PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs]; - /** Physical register index of the previous producers of the - * architected destinations. - */ - PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs]; - public: - - /** Returns the physical register index of the i'th destination - * register. - */ - PhysRegIndex renamedDestRegIdx(int idx) const - { - return _destRegIdx[idx]; - } - - /** Returns the physical register index of the i'th source register. */ - PhysRegIndex renamedSrcRegIdx(int idx) const - { - return _srcRegIdx[idx]; - } - /** Returns the flattened register index of the i'th destination * register. */ @@ -352,34 +243,6 @@ return _flatSrcRegIdx[idx]; } - /** Returns the physical register index of the previous physical register - * that remapped to the same logical register index. - */ - PhysRegIndex prevDestRegIdx(int idx) const - { - return _prevDestRegIdx[idx]; - } - - /** Renames a destination register to a physical register. Also records - * the previous physical register that the logical register mapped to. - */ - void renameDestReg(int idx, - PhysRegIndex renamed_dest, - PhysRegIndex previous_rename) - { - _destRegIdx[idx] = renamed_dest; - _prevDestRegIdx[idx] = previous_rename; - } - - /** Renames a source logical register to the physical register which - * has/will produce that logical register's result. - * @todo: add in whether or not the source register is ready. - */ - void renameSrcReg(int idx, PhysRegIndex renamed_src) - { - _srcRegIdx[idx] = renamed_src; - } - /** Flattens a source architectural register index into a logical index. */ void flattenSrcReg(int idx, TheISA::RegIndex flattened_src) @@ -394,6 +257,13 @@ { _flatDestRegIdx[idx] = flattened_dest; } + + /** Returns if a source register is ready. */ + bool isReadySrcRegIdx(int idx) const + { + return this->_readySrcRegIdx[idx]; + } + /** BaseDynInst constructor given a binary instruction. * @param staticInst A StaticInstPtr to the underlying instruction. * @param pc The PC state for the instruction. @@ -580,183 +450,23 @@ /** 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; } - - /** Returns the result of a floating point instruction. */ - float readFloatResult() { return (float)instResult.dbl; } - - /** Returns the result of a floating point (double) instruction. */ - double readDoubleResult() { return instResult.dbl; } - - /** Records an integer register being set to a value. */ - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) - { - if (recordResult) - instResult.integer = val; - } - - /** Records an fp register being set to a value. */ - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, - int width) - { - if (recordResult) { - if (width == 32) - instResult.dbl = (double)val; - else if (width == 64) - instResult.dbl = val; - else - panic("Unsupported width!"); - } - } - - /** Records an fp register being set to a value. */ - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) - { - if (recordResult) - instResult.dbl = (double)val; - } - - /** Records an fp register being set to an integer value. */ - void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val, - int width) - { - 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; - } - - /** Records that one of the source registers is ready. */ - void markSrcRegReady(); - - /** Marks a specific register as ready. */ - void markSrcRegReady(RegIndex src_idx); - - /** Returns if a source register is ready. */ - bool isReadySrcRegIdx(int idx) const - { - return this->_readySrcRegIdx[idx]; - } - - /** Sets this instruction as completed. */ - void setCompleted() { status.set(Completed); } - - /** Returns whether or not this instruction is completed. */ - bool isCompleted() const { return status[Completed]; } - - /** Marks the result as ready. */ - void setResultReady() { status.set(ResultReady); } - - /** Returns whether or not the result is ready. */ - bool isResultReady() const { return status[ResultReady]; } - - /** Sets this instruction as ready to issue. */ - void setCanIssue() { status.set(CanIssue); } - - /** Returns whether or not this instruction is ready to issue. */ - bool readyToIssue() const { return status[CanIssue]; } - - /** Clears this instruction being able to issue. */ - void clearCanIssue() { status.reset(CanIssue); } - - /** Sets this instruction as issued from the IQ. */ - void setIssued() { status.set(Issued); } - - /** Returns whether or not this instruction has issued. */ - bool isIssued() const { return status[Issued]; } - - /** Clears this instruction as being issued. */ - void clearIssued() { status.reset(Issued); } - /** Sets this instruction as executed. */ void setExecuted() { status.set(Executed); } /** Returns whether or not this instruction has executed. */ bool isExecuted() const { return status[Executed]; } - /** Sets this instruction as ready to commit. */ - void setCanCommit() { status.set(CanCommit); } - - /** Clears this instruction as being ready to commit. */ - void clearCanCommit() { status.reset(CanCommit); } - - /** Returns whether or not this instruction is ready to commit. */ - bool readyToCommit() const { return status[CanCommit]; } - - void setAtCommit() { status.set(AtCommit); } - - bool isAtCommit() { return status[AtCommit]; } - - /** Sets this instruction as committed. */ - void setCommitted() { status.set(Committed); } - - /** Returns whether or not this instruction is committed. */ - bool isCommitted() const { return status[Committed]; } - /** Sets this instruction as squashed. */ void setSquashed() { status.set(Squashed); } /** Returns whether or not this instruction is squashed. */ bool isSquashed() const { return status[Squashed]; } - //Instruction Queue Entry - //----------------------- - /** Sets this instruction as a entry the IQ. */ - void setInIQ() { status.set(IqEntry); } + /** Sets this instruction as completed. */ + void setCompleted() { status.set(Completed); } - /** Sets this instruction as a entry the IQ. */ - void clearInIQ() { status.reset(IqEntry); } - - /** Returns whether or not this instruction has issued. */ - bool isInIQ() const { return status[IqEntry]; } - - /** Sets this instruction as squashed in the IQ. */ - void setSquashedInIQ() { status.set(SquashedInIQ); status.set(Squashed);} - - /** Returns whether or not this instruction is squashed in the IQ. */ - bool isSquashedInIQ() const { return status[SquashedInIQ]; } - - - //Load / Store Queue Functions - //----------------------- - /** Sets this instruction as a entry the LSQ. */ - void setInLSQ() { status.set(LsqEntry); } - - /** Sets this instruction as a entry the LSQ. */ - void removeInLSQ() { status.reset(LsqEntry); } - - /** Returns whether or not this instruction is in the LSQ. */ - bool isInLSQ() const { return status[LsqEntry]; } - - /** Sets this instruction as squashed in the LSQ. */ - void setSquashedInLSQ() { status.set(SquashedInLSQ);} - - /** Returns whether or not this instruction is squashed in the LSQ. */ - bool isSquashedInLSQ() const { return status[SquashedInLSQ]; } - - - //Reorder Buffer Functions - //----------------------- - /** Sets this instruction as a entry the ROB. */ - void setInROB() { status.set(RobEntry); } - - /** Sets this instruction as a entry the ROB. */ - void clearInROB() { status.reset(RobEntry); } - - /** Returns whether or not this instruction is in the ROB. */ - bool isInROB() const { return status[RobEntry]; } - - /** Sets this instruction as squashed in the ROB. */ - void setSquashedInROB() { status.set(SquashedInROB); } - - /** Returns whether or not this instruction is squashed in the ROB. */ - bool isSquashedInROB() const { return status[SquashedInROB]; } + /** Returns whether or not this instruction is completed. */ + bool isCompleted() const { return status[Completed]; } /** Read the PC state of this instruction. */ const TheISA::PCState pcState() const { return pc; } @@ -799,7 +509,7 @@ /** Returns the thread context. */ ThreadContext *tcBase() { return thread->getTC(); } - private: + protected: /** Instruction effective address. * @todo: Consider if this is necessary or not. */ @@ -839,12 +549,6 @@ 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; @@ -864,207 +568,4 @@ { thread->storeCondFailures = sc_failures; } }; -template -Fault -BaseDynInst::readBytes(Addr addr, uint8_t *data, - unsigned size, unsigned flags) -{ - reqMade = true; - Request *req = NULL; - Request *sreqLow = NULL; - Request *sreqHigh = NULL; - - if (reqMade && translationStarted) { - req = savedReq; - sreqLow = savedSreqLow; - sreqHigh = savedSreqHigh; - } else { - req = new Request(asid, addr, size, flags, this->pc.instAddr(), - thread->contextId(), threadNumber); - - // 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 (translationCompleted) { - if (fault == NoFault) { - effAddr = req->getVaddr(); - effAddrValid = true; - fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx); - } else { - // Commit will have to clean up whatever happened. Set this - // instruction as executed. - this->setExecuted(); - } - - if (fault != NoFault) { - // Return a fixed value to keep simulation deterministic even - // along misspeculated paths. - if (data) - bzero(data, size); - } - } - - if (traceData) { - traceData->setAddr(addr); - } - - 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); - } - - return fault; -} - -template -Fault -BaseDynInst::writeBytes(uint8_t *data, unsigned size, - Addr addr, unsigned flags, uint64_t *res) -{ - if (traceData) { - traceData->setAddr(addr); - } - - reqMade = true; - Request *req = NULL; - Request *sreqLow = NULL; - Request *sreqHigh = NULL; - - if (reqMade && translationStarted) { - req = savedReq; - sreqLow = savedSreqLow; - sreqHigh = savedSreqHigh; - } else { - req = new Request(asid, addr, size, flags, this->pc.instAddr(), - thread->contextId(), threadNumber); - - // Only split the request if the ISA supports unaligned accesses. - if (TheISA::HasUnalignedMemAcc) { - splitRequest(req, sreqLow, sreqHigh); - } - initiateTranslation(req, sreqLow, sreqHigh, res, BaseTLB::Write); - } - - if (fault == NoFault && translationCompleted) { - effAddr = req->getVaddr(); - effAddrValid = true; - 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(); - Addr addr = req->getVaddr(); - Addr split_addr = roundDown(addr + req->getSize() - 1, block_size); - assert(split_addr <= addr || split_addr - addr < block_size); - - // Spans two blocks. - if (split_addr > addr) { - req->splitOnVaddr(split_addr, sreqLow, sreqHigh); - } -} - -template -inline void -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); - cpu->dtb->translateTiming(req, thread->getTC(), trans, mode); - if (!translationCompleted) { - // 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); - - cpu->dtb->translateTiming(sreqLow, thread->getTC(), stransLow, mode); - cpu->dtb->translateTiming(sreqHigh, thread->getTC(), stransHigh, mode); - if (!translationCompleted) { - // Save memory requests. - savedReq = state->mainReq; - savedSreqLow = state->sreqLow; - savedSreqHigh = state->sreqHigh; - } - } -} - -template -inline void -BaseDynInst::finishTranslation(WholeTranslationState *state) -{ - fault = state->getFault(); - - if (state->isUncacheable()) - isUncacheable = true; - - if (fault == NoFault) { - physEffAddr = state->getPaddr(); - memReqFlags = state->getFlags(); - - if (state->mainReq->isCondSwap()) { - assert(state->res); - state->mainReq->setExtraData(*state->res); - } - - } else { - state->deleteReqs(); - } - delete state; - - translationCompleted = true; -} - #endif // __CPU_BASE_DYN_INST_HH__ diff -r cf1afc88070f -r 22c55ce9cf87 src/cpu/base_dyn_inst_impl.hh --- a/src/cpu/base_dyn_inst_impl.hh Tue Mar 01 03:00:42 2011 -0800 +++ b/src/cpu/base_dyn_inst_impl.hh Tue Mar 01 16:49:04 2011 -0500 @@ -119,25 +119,16 @@ effAddrValid = false; physEffAddr = 0; - translationStarted = false; - translationCompleted = false; - isUncacheable = false; reqMade = false; readyRegs = 0; - instResult.integer = 0; - recordResult = true; - status.reset(); eaCalcDone = false; memOpDone = false; predicate = true; - lqIdx = -1; - sqIdx = -1; - // Eventually make this a parameter. threadNumber = 0; @@ -230,26 +221,6 @@ } template -void -BaseDynInst::markSrcRegReady() -{ - DPRINTF(IQ, "[sn:%lli] has %d ready out of %d sources. RTI %d)\n", - seqNum, readyRegs+1, numSrcRegs(), readyToIssue()); - if (++readyRegs == numSrcRegs()) { - setCanIssue(); - } -} - -template -void -BaseDynInst::markSrcRegReady(RegIndex src_idx) -{ - _readySrcRegIdx[src_idx] = true; - - markSrcRegReady(); -} - -template bool BaseDynInst::eaSrcsReady() { diff -r cf1afc88070f -r 22c55ce9cf87 src/cpu/o3/dyn_inst.hh --- a/src/cpu/o3/dyn_inst.hh Tue Mar 01 03:00:42 2011 -0800 +++ b/src/cpu/o3/dyn_inst.hh Tue Mar 01 16:49:04 2011 -0500 @@ -107,6 +107,67 @@ /** Completes the access. Only valid for memory operations. */ Fault completeAcc(PacketPtr pkt); + /** + * 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 + inline 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 + inline 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); + + /** True if the DTB address translation has started. */ + bool translationStarted; + + /** True if the DTB address translation has completed. */ + bool translationCompleted; + + /** + * Returns true if the DTB address translation is being delayed due to a hw + * page table walk. + */ + bool isTranslationDelayed() const + { + return (translationStarted && !translationCompleted); + } + + /** + * Saved memory requests (needed when the DTB address translation is + * delayed due to a hw page table walk). + */ + RequestPtr savedReq; + RequestPtr savedSreqLow; + RequestPtr savedSreqHigh; + private: /** Initializes variables. */ void initVars(); @@ -122,7 +183,44 @@ /** Number of destination misc. registers. */ int _numDestMiscRegs; + /** Physical register index of the previous producers of the + * architected destinations. + */ + PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs]; + public: + /** Returns the physical register index of the i'th destination + * register. + */ + PhysRegIndex renamedDestRegIdx(int idx) const; + + /** Returns the physical register index of the i'th source register. */ + PhysRegIndex renamedSrcRegIdx(int idx) const; + + /** Returns the physical register index of the previous physical register + * that remapped to the same logical register index. + */ + PhysRegIndex prevDestRegIdx(int idx) const; + + /** Renames a destination register to a physical register. Also records + * the previous physical register that the logical register mapped to. + */ + void renameDestReg(int idx, + PhysRegIndex renamed_dest, + PhysRegIndex previous_rename); + + /** Renames a source logical register to the physical register which + * has/will produce that logical register's result. + * @todo: add in whether or not the source register is ready. + */ + void renameSrcReg(int idx, PhysRegIndex renamed_src); + + /** Records that one of the source registers is ready. */ + void markSrcRegReady(); + + /** Marks a specific register as ready. */ + void markSrcRegReady(RegIndex src_idx); + /** Reads a misc. register, including any side-effects the read * might have as defined by the architecture. */ @@ -205,6 +303,28 @@ #endif public: + union Result { + uint64_t integer; +// float fp; + double dbl; + }; + + /** The result of the instruction; assumes for now that there's only one + * destination register. + */ + Result instResult; + + /** Records changes to result? */ + bool recordResult; + + /** Returns the result of an integer instruction. */ + uint64_t readIntResult() { return instResult.integer; } + + /** Returns the result of a floating point instruction. */ + float readFloatResult() { return (float)instResult.dbl; } + + /** Returns the result of a floating point (double) instruction. */ + double readDoubleResult() { return instResult.dbl; } // The register accessor methods provide the index of the // instruction's operand (e.g., 0 or 1), not the architectural @@ -217,57 +337,60 @@ // storage (which is pretty hard to imagine they would have reason // to do). - uint64_t readIntRegOperand(const StaticInst *si, int idx) - { - return this->cpu->readIntReg(this->_srcRegIdx[idx]); - } - - FloatReg readFloatRegOperand(const StaticInst *si, int idx) - { - return this->cpu->readFloatReg(this->_srcRegIdx[idx]); - } - - FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) - { - return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); - } + uint64_t readIntRegOperand(const StaticInst *si, int idx); + FloatReg readFloatRegOperand(const StaticInst *si, int idx); + FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx); /** @todo: Make results into arrays so they can handle multiple dest * registers. */ - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) - { - this->cpu->setIntReg(this->_destRegIdx[idx], val); - BaseDynInst::setIntRegOperand(si, idx, val); - } + void setIntRegOperand(const StaticInst *si, int idx, uint64_t val); + void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val); + void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, + int width); + void setFloatRegOperandBits(const StaticInst *si, int idx, + FloatRegBits val); + void setFloatRegOperandBits(const StaticInst *si, int idx, + FloatRegBits val, int width); - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) - { - this->cpu->setFloatReg(this->_destRegIdx[idx], val); - BaseDynInst::setFloatRegOperand(si, idx, val); - } - - void setFloatRegOperandBits(const StaticInst *si, int idx, - FloatRegBits val) - { - this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); - BaseDynInst::setFloatRegOperandBits(si, idx, val); - } - -#if THE_ISA == MIPS_ISA uint64_t readRegOtherThread(int misc_reg) { - panic("MIPS MT not defined for O3 CPU.\n"); + panic("MT ISA Extensions not defined for O3 CPU.\n"); return 0; } void setRegOtherThread(int misc_reg, const TheISA::MiscReg &val) { - panic("MIPS MT not defined for O3 CPU.\n"); + panic("MT ISA Extentions not defined for O3 CPU.\n"); } -#endif public: + enum Status { + IqEntry, /// Instruction is in IQ + SquashedInIQ, /// Instruction is squashed in the IQ + RobEntry, /// Instruction is in the ROB + SquashedInROB, /// Instruction is squashed in the ROB + LsqEntry, /// Instruction is in the LSQ + SquashedInLSQ, /// Instruction is squashed in the LSQ + ResultReady, /// Instruction has its result + CanIssue, /// Instruction can issue and execute + Issued, /// Instruction has issued + Executed, /// Instruction has executed + CanCommit, /// Instruction can commit + AtCommit, /// Instruction has reached commit + Committed, /// Instruction has committed + NumO3Status + }; + + /** The status of this BaseO3DynInst. Several bits can be set. */ + std::bitset o3Status; + + /** Load queue index. */ + int16_t lqIdx; + + /** Store queue index. */ + int16_t sqIdx; + /** Calculates EA part of a memory instruction. Currently unused, * though it may be useful in the future if we want to split * memory operations into EA calculation and memory access parts. @@ -285,7 +408,224 @@ { return this->staticInst->memAccInst()->execute(this, this->traceData); } + + /** Marks the result as ready. */ + void setResultReady() { o3Status.set(ResultReady); } + + /** Returns whether or not the result is ready. */ + bool isResultReady() const { return o3Status[ResultReady]; } + + /** Sets this instruction as ready to issue. */ + void setCanIssue() { o3Status.set(CanIssue); } + + /** Returns whether or not this instruction is ready to issue. */ + bool readyToIssue() const { return o3Status[CanIssue]; } + + /** Clears this instruction being able to issue. */ + void clearCanIssue() { o3Status.reset(CanIssue); } + + /** Sets this instruction as issued from the IQ. */ + void setIssued() { o3Status.set(Issued); } + + /** Returns whether or not this instruction has issued. */ + bool isIssued() const { return o3Status[Issued]; } + + /** Clears this instruction as being issued. */ + void clearIssued() { o3Status.reset(Issued); } + + /** Sets this instruction as ready to commit. */ + void setCanCommit() { o3Status.set(CanCommit); } + + /** Clears this instruction as being ready to commit. */ + void clearCanCommit() { o3Status.reset(CanCommit); } + + /** Returns whether or not this instruction is ready to commit. */ + bool readyToCommit() const { return o3Status[CanCommit]; } + + void setAtCommit() { o3Status.set(AtCommit); } + + bool isAtCommit() { return o3Status[AtCommit]; } + + /** Sets this instruction as committed. */ + void setCommitted() { o3Status.set(Committed); } + + /** Returns whether or not this instruction is committed. */ + bool isCommitted() const { return o3Status[Committed]; } + + //Instruction Queue Entry + //----------------------- + /** Sets this instruction as a entry the IQ. */ + void setInIQ() { o3Status.set(IqEntry); } + + /** Sets this instruction as a entry the IQ. */ + void clearInIQ() { o3Status.reset(IqEntry); } + + /** Returns whether or not this instruction has issued. */ + bool isInIQ() const { return o3Status[IqEntry]; } + + /** Sets this instruction as squashed in the IQ. */ + void setSquashedInIQ(); + + /** Returns whether or not this instruction is squashed in the IQ. */ + bool isSquashedInIQ() const { return o3Status[SquashedInIQ]; } + + + //Load / Store Queue Functions + //----------------------- + /** Sets this instruction as a entry the LSQ. */ + void setInLSQ() { o3Status.set(LsqEntry); } + + /** Sets this instruction as a entry the LSQ. */ + void removeInLSQ() { o3Status.reset(LsqEntry); } + + /** Returns whether or not this instruction is in the LSQ. */ + bool isInLSQ() const { return o3Status[LsqEntry]; } + + /** Sets this instruction as squashed in the LSQ. */ + void setSquashedInLSQ() { o3Status.set(SquashedInLSQ);} + + /** Returns whether or not this instruction is squashed in the LSQ. */ + bool isSquashedInLSQ() const { return o3Status[SquashedInLSQ]; } + + + //Reorder Buffer Functions + //----------------------- + /** Sets this instruction as a entry the ROB. */ + void setInROB() { o3Status.set(RobEntry); } + + /** Sets this instruction as a entry the ROB. */ + void clearInROB() { o3Status.reset(RobEntry); } + + /** Returns whether or not this instruction is in the ROB. */ + bool isInROB() const { return o3Status[RobEntry]; } + + /** Sets this instruction as squashed in the ROB. */ + void setSquashedInROB() { o3Status.set(SquashedInROB); } + + /** Returns whether or not this instruction is squashed in the ROB. */ + bool isSquashedInROB() const { return o3Status[SquashedInROB]; } + }; -#endif // __CPU_O3_ALPHA_DYN_INST_HH__ +template +template +inline Fault +BaseO3DynInst::read(Addr addr, T &data, unsigned flags) +{ + Fault fault = readBytes(addr, (uint8_t *)&data, sizeof(T), flags); + data = TheISA::gtoh(data); + + if (this->traceData) { + this->traceData->setData(data); + } + + return fault; +} + + +template +Fault +BaseO3DynInst::readBytes(Addr addr, uint8_t *data, + unsigned size, unsigned flags) +{ + this->reqMade = true; + Request *req = NULL; + Request *sreqLow = NULL; + Request *sreqHigh = NULL; + + if (this->reqMade && translationStarted) { + req = savedReq; + sreqLow = savedSreqLow; + sreqHigh = savedSreqHigh; + } else { + req = new Request(this->asid, addr, size, flags, this->pc.instAddr(), + this->thread->contextId(), this->threadNumber); + + // 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 (translationCompleted) { + if (this->fault == NoFault) { + this->effAddr = req->getVaddr(); + this->effAddrValid = true; + this->fault = this->cpu->read(req, sreqLow, sreqHigh, data, lqIdx); + } else { + // Commit will have to clean up whatever happened. Set this + // instruction as executed. + this->setExecuted(); + } + + if (this->fault != NoFault) { + // Return a fixed value to keep simulation deterministic even + // along misspeculated paths. + if (data) + bzero(data, size); + } + } + + if (this->traceData) { + this->traceData->setAddr(addr); + } + + return this->fault; +} + + +template +template +inline Fault +BaseO3DynInst::write(T data, Addr addr, unsigned flags, uint64_t *res) +{ + if (this->traceData) { + this->traceData->setData(data); + } + data = TheISA::htog(data); + return writeBytes((uint8_t *)&data, sizeof(T), addr, flags, res); +} + +template +Fault +BaseO3DynInst::writeBytes(uint8_t *data, unsigned size, + Addr addr, unsigned flags, uint64_t *res) +{ + if (this->traceData) { + this->traceData->setAddr(addr); + } + + this->reqMade = true; + Request *req = NULL; + Request *sreqLow = NULL; + Request *sreqHigh = NULL; + + if (this->reqMade && translationStarted) { + req = savedReq; + sreqLow = savedSreqLow; + sreqHigh = savedSreqHigh; + } else { + req = new Request(this->asid, addr, size, flags, this->pc.instAddr(), + this->thread->contextId(), this->threadNumber); + + // Only split the request if the ISA supports unaligned accesses. + if (TheISA::HasUnalignedMemAcc) { + splitRequest(req, sreqLow, sreqHigh); + } + initiateTranslation(req, sreqLow, sreqHigh, res, BaseTLB::Write); + } + + if (this->fault == NoFault && translationCompleted) { + this->effAddr = req->getVaddr(); + this->effAddrValid = true; + this->fault = this->cpu->write(req, sreqLow, sreqHigh, data, sqIdx); + } + + return this->fault; +} + + +#endif // __CPU_O3_DYN_INST_HH__ + diff -r cf1afc88070f -r 22c55ce9cf87 src/cpu/o3/dyn_inst_impl.hh --- a/src/cpu/o3/dyn_inst_impl.hh Tue Mar 01 03:00:42 2011 -0800 +++ b/src/cpu/o3/dyn_inst_impl.hh Tue Mar 01 16:49:04 2011 -0500 @@ -72,6 +72,17 @@ void BaseO3DynInst::initVars() { + translationStarted = false; + translationCompleted = false; + + instResult.integer = 0; + recordResult = true; + + o3Status.reset(); + + lqIdx = -1; + sqIdx = -1; + // Make sure to have the renamed register entries set to the same // as the normal register entries. It will allow the IQ to work // without any modifications. @@ -203,3 +214,237 @@ } #endif +template +uint64_t +BaseO3DynInst::readIntRegOperand(const StaticInst *si, int idx) +{ + return this->cpu->readIntReg(this->_srcRegIdx[idx]); +} + +template +TheISA::FloatReg +BaseO3DynInst::readFloatRegOperand(const StaticInst *si, int idx) +{ + return this->cpu->readFloatReg(this->_srcRegIdx[idx]); +} + +template +TheISA::FloatRegBits +BaseO3DynInst::readFloatRegOperandBits(const StaticInst *si, int idx) +{ + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); +} + +template +void +BaseO3DynInst::setIntRegOperand(const StaticInst *si, int idx, uint64_t val) +{ + this->cpu->setIntReg(this->_destRegIdx[idx], val); + + if (recordResult) + instResult.integer = val; +} + +template +void +BaseO3DynInst::setFloatRegOperand(const StaticInst *si, int idx, + TheISA::FloatReg val) +{ + this->cpu->setFloatReg(this->_destRegIdx[idx], val); + instResult.dbl = (double)val; +} + +template +void +BaseO3DynInst::setFloatRegOperand(const StaticInst *si, int idx, + TheISA::FloatReg val, int width) +{ + this->cpu->setFloatReg(this->_destRegIdx[idx], val); + + if (recordResult) { + if (width == 32) + instResult.dbl = (double)val; + else if (width == 64) + instResult.dbl = val; + else + panic("Unsupported width!"); + } +} + +template +void +BaseO3DynInst::setFloatRegOperandBits(const StaticInst *si, int idx, + TheISA::FloatRegBits val) +{ + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); + + if (recordResult) + instResult.integer = val; +} + +template +void +BaseO3DynInst::setFloatRegOperandBits(const StaticInst *si, int idx, + TheISA::FloatRegBits val, int width) +{ + this->cpu->setFloatReg(this->_destRegIdx[idx], val); + + if (recordResult) + instResult.integer = val; +} + +template +PhysRegIndex +BaseO3DynInst::renamedDestRegIdx(int idx) const +{ + return this->_destRegIdx[idx]; +} + +template +PhysRegIndex +BaseO3DynInst::renamedSrcRegIdx(int idx) const +{ + return this->_srcRegIdx[idx]; +} + +template +PhysRegIndex +BaseO3DynInst::prevDestRegIdx(int idx) const +{ + return _prevDestRegIdx[idx]; +} + +template +void +BaseO3DynInst::renameDestReg(int idx, + PhysRegIndex renamed_dest, + PhysRegIndex previous_rename) +{ + this->_destRegIdx[idx] = renamed_dest; + _prevDestRegIdx[idx] = previous_rename; +} + +template +void +BaseO3DynInst::renameSrcReg(int idx, PhysRegIndex renamed_src) +{ + this->_srcRegIdx[idx] = renamed_src; +} + + +template +void +BaseO3DynInst::markSrcRegReady() +{ + DPRINTF(IQ, "[sn:%lli] has %d ready out of %d sources. RTI %d)\n", + this->seqNum, this->readyRegs+1, this->numSrcRegs(), + readyToIssue()); + if (++this->readyRegs == this->numSrcRegs()) { + setCanIssue(); + } +} + +template +void +BaseO3DynInst::markSrcRegReady(RegIndex src_idx) +{ + this->_readySrcRegIdx[src_idx] = true; + + markSrcRegReady(); +} + +template +void +BaseO3DynInst::setSquashedInIQ() +{ + o3Status.set(SquashedInIQ); + this->status.set(BaseDynInst::Squashed); +} + + +template +inline void +BaseO3DynInst::splitRequest(RequestPtr req, RequestPtr &sreqLow, + RequestPtr &sreqHigh) +{ + // Check to see if the request crosses the next level block boundary. + unsigned block_size = this->cpu->getDcachePort()->peerBlockSize(); + Addr addr = req->getVaddr(); + Addr split_addr = roundDown(addr + req->getSize() - 1, block_size); + assert(split_addr <= addr || split_addr - addr < block_size); + + // Spans two blocks. + if (split_addr > addr) { + req->splitOnVaddr(split_addr, sreqLow, sreqHigh); + } +} + +template +inline void +BaseO3DynInst::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); + this->cpu->dtb->translateTiming(req, this->thread->getTC(), trans, mode); + if (!translationCompleted) { + // 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); + + this->cpu->dtb->translateTiming(sreqLow, this->thread->getTC(), stransLow, mode); + this->cpu->dtb->translateTiming(sreqHigh, this->thread->getTC(), stransHigh, mode); + if (!translationCompleted) { + // Save memory requests. + savedReq = state->mainReq; + savedSreqLow = state->sreqLow; + savedSreqHigh = state->sreqHigh; + } + } +} + +template +inline void +BaseO3DynInst::finishTranslation(WholeTranslationState *state) +{ + this->fault = state->getFault(); + + if (state->isUncacheable()) + this->isUncacheable = true; + + if (this->fault == NoFault) { + this->physEffAddr = state->getPaddr(); + this->memReqFlags = state->getFlags(); + + if (state->mainReq->isCondSwap()) { + assert(state->res); + state->mainReq->setExtraData(*state->res); + } + + } else { + state->deleteReqs(); + } + delete state; + + translationCompleted = true; +} +