iew_impl.hh
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 1,585 行 · 第 1/4 页
HH
1,585 行
}}template<class Impl>voidDefaultIEW<Impl>::squash(unsigned tid){ DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n", tid); // Tell the IQ to start squashing. instQueue.squash(tid); // Tell the LDSTQ to start squashing. ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid); updatedQueues = true; // Clear the skid buffer in case it has any data in it. DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n", tid, fromCommit->commitInfo[tid].doneSeqNum); while (!skidBuffer[tid].empty()) { if (skidBuffer[tid].front()->isLoad() || skidBuffer[tid].front()->isStore() ) { toRename->iewInfo[tid].dispatchedToLSQ++; } toRename->iewInfo[tid].dispatched++; skidBuffer[tid].pop(); } emptyRenameInsts(tid);}template<class Impl>voidDefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid){ DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x " "[sn:%i].\n", tid, inst->readPC(), inst->seqNum); toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; toCommit->mispredPC[tid] = inst->readPC(); toCommit->branchMispredict[tid] = true;#if ISA_HAS_DELAY_SLOT int instSize = sizeof(TheISA::MachInst); toCommit->branchTaken[tid] = !(inst->readNextPC() + instSize == inst->readNextNPC() && (inst->readNextPC() == inst->readPC() + instSize || inst->readNextPC() == inst->readPC() + 2 * instSize));#else toCommit->branchTaken[tid] = inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst));#endif toCommit->nextPC[tid] = inst->readNextPC(); toCommit->nextNPC[tid] = inst->readNextNPC(); toCommit->nextMicroPC[tid] = inst->readNextMicroPC(); toCommit->includeSquashInst[tid] = false; wroteToTimeBuffer = true;}template<class Impl>voidDefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid){ DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, " "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum); toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; toCommit->nextPC[tid] = inst->readNextPC(); toCommit->nextNPC[tid] = inst->readNextNPC(); toCommit->branchMispredict[tid] = false; toCommit->includeSquashInst[tid] = false; wroteToTimeBuffer = true;}template<class Impl>voidDefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid){ DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, " "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum); toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; toCommit->nextPC[tid] = inst->readPC(); toCommit->nextNPC[tid] = inst->readNextPC(); toCommit->branchMispredict[tid] = false; // Must include the broadcasted SN in the squash. toCommit->includeSquashInst[tid] = true; ldstQueue.setLoadBlockedHandled(tid); wroteToTimeBuffer = true;}template<class Impl>voidDefaultIEW<Impl>::block(unsigned tid){ DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid); if (dispatchStatus[tid] != Blocked && dispatchStatus[tid] != Unblocking) { toRename->iewBlock[tid] = true; wroteToTimeBuffer = true; } // Add the current inputs to the skid buffer so they can be // reprocessed when this stage unblocks. skidInsert(tid); dispatchStatus[tid] = Blocked;}template<class Impl>voidDefaultIEW<Impl>::unblock(unsigned tid){ DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid " "buffer %u.\n",tid, tid); // If the skid bufffer is empty, signal back to previous stages to unblock. // Also switch status to running. if (skidBuffer[tid].empty()) { toRename->iewUnblock[tid] = true; wroteToTimeBuffer = true; DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid); dispatchStatus[tid] = Running; }}template<class Impl>voidDefaultIEW<Impl>::wakeDependents(DynInstPtr &inst){ instQueue.wakeDependents(inst);}template<class Impl>voidDefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst){ instQueue.rescheduleMemInst(inst);}template<class Impl>voidDefaultIEW<Impl>::replayMemInst(DynInstPtr &inst){ instQueue.replayMemInst(inst);}template<class Impl>voidDefaultIEW<Impl>::instToCommit(DynInstPtr &inst){ // This function should not be called after writebackInsts in a // single cycle. That will cause problems with an instruction // being added to the queue to commit without being processed by // writebackInsts prior to being sent to commit. // First check the time slot that this instruction will write // to. If there are free write ports at the time, then go ahead // and write the instruction to that time. If there are not, // keep looking back to see where's the first time there's a // free slot. while ((*iewQueue)[wbCycle].insts[wbNumInst]) { ++wbNumInst; if (wbNumInst == wbWidth) { ++wbCycle; wbNumInst = 0; } assert((wbCycle * wbWidth + wbNumInst) <= wbMax); } DPRINTF(IEW, "Current wb cycle: %i, width: %i, numInst: %i\nwbActual:%i\n", wbCycle, wbWidth, wbNumInst, wbCycle * wbWidth + wbNumInst); // Add finished instruction to queue to commit. (*iewQueue)[wbCycle].insts[wbNumInst] = inst; (*iewQueue)[wbCycle].size++;}template <class Impl>unsignedDefaultIEW<Impl>::validInstsFromRename(){ unsigned inst_count = 0; for (int i=0; i<fromRename->size; i++) { if (!fromRename->insts[i]->isSquashed()) inst_count++; } return inst_count;}template<class Impl>voidDefaultIEW<Impl>::skidInsert(unsigned tid){ DynInstPtr inst = NULL; while (!insts[tid].empty()) { inst = insts[tid].front(); insts[tid].pop(); DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into " "dispatch skidBuffer %i\n",tid, inst->seqNum, inst->readPC(),tid); skidBuffer[tid].push(inst); } assert(skidBuffer[tid].size() <= skidBufferMax && "Skidbuffer Exceeded Max Size");}template<class Impl>intDefaultIEW<Impl>::skidCount(){ int max=0; std::list<unsigned>::iterator threads = activeThreads->begin(); std::list<unsigned>::iterator end = activeThreads->end(); while (threads != end) { unsigned tid = *threads++; unsigned thread_count = skidBuffer[tid].size(); if (max < thread_count) max = thread_count; } return max;}template<class Impl>boolDefaultIEW<Impl>::skidsEmpty(){ std::list<unsigned>::iterator threads = activeThreads->begin(); std::list<unsigned>::iterator end = activeThreads->end(); while (threads != end) { unsigned tid = *threads++; if (!skidBuffer[tid].empty()) return false; } return true;}template <class Impl>voidDefaultIEW<Impl>::updateStatus(){ bool any_unblocking = false; std::list<unsigned>::iterator threads = activeThreads->begin(); std::list<unsigned>::iterator end = activeThreads->end(); while (threads != end) { unsigned tid = *threads++; if (dispatchStatus[tid] == Unblocking) { any_unblocking = true; break; } } // If there are no ready instructions waiting to be scheduled by the IQ, // and there's no stores waiting to write back, and dispatch is not // unblocking, then there is no internal activity for the IEW stage. if (_status == Active && !instQueue.hasReadyInsts() && !ldstQueue.willWB() && !any_unblocking) { DPRINTF(IEW, "IEW switching to idle\n"); deactivateStage(); _status = Inactive; } else if (_status == Inactive && (instQueue.hasReadyInsts() || ldstQueue.willWB() || any_unblocking)) { // Otherwise there is internal activity. Set to active. DPRINTF(IEW, "IEW switching to active\n"); activateStage(); _status = Active; }}template <class Impl>voidDefaultIEW<Impl>::resetEntries(){ instQueue.resetEntries(); ldstQueue.resetEntries();}template <class Impl>voidDefaultIEW<Impl>::readStallSignals(unsigned tid){ if (fromCommit->commitBlock[tid]) { stalls[tid].commit = true; } if (fromCommit->commitUnblock[tid]) { assert(stalls[tid].commit); stalls[tid].commit = false; }}template <class Impl>boolDefaultIEW<Impl>::checkStall(unsigned tid){ bool ret_val(false); if (stalls[tid].commit) { DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid); ret_val = true; } else if (instQueue.isFull(tid)) { DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid); ret_val = true; } else if (ldstQueue.isFull(tid)) { DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid); if (ldstQueue.numLoads(tid) > 0 ) { DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n", tid,ldstQueue.getLoadHeadSeqNum(tid)); } if (ldstQueue.numStores(tid) > 0) { DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n", tid,ldstQueue.getStoreHeadSeqNum(tid)); } ret_val = true; } else if (ldstQueue.isStalled(tid)) { DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid); ret_val = true; } return ret_val;}template <class Impl>voidDefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid){ // Check if there's a squash signal, squash if there is // Check stall signals, block if there is. // If status was Blocked // if so then go to unblocking // If status was Squashing // check if squashing is not high. Switch to running this cycle. readStallSignals(tid); if (fromCommit->commitInfo[tid].squash) { squash(tid); if (dispatchStatus[tid] == Blocked || dispatchStatus[tid] == Unblocking) { toRename->iewUnblock[tid] = true; wroteToTimeBuffer = true; } dispatchStatus[tid] = Squashing; fetchRedirect[tid] = false; return; } if (fromCommit->commitInfo[tid].robSquashing) { DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n", tid); dispatchStatus[tid] = Squashing; emptyRenameInsts(tid);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?