iew_impl.hh
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 1,585 行 · 第 1/4 页
HH
1,585 行
DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n", inst->readPC(), inst->threadNumber,inst->seqNum); // Check if the instruction is squashed; if so then skip it if (inst->isSquashed()) { DPRINTF(IEW, "Execute: Instruction was squashed.\n"); // Consider this instruction executed so that commit can go // ahead and retire the instruction. inst->setExecuted(); // Not sure if I should set this here or just let commit try to // commit any squashed instructions. I like the latter a bit more. inst->setCanCommit(); ++iewExecSquashedInsts; decrWb(inst->seqNum); continue; } Fault fault = NoFault; // Execute instruction. // Note that if the instruction faults, it will be handled // at the commit stage. if (inst->isMemRef() && (!inst->isDataPrefetch() && !inst->isInstPrefetch())) { DPRINTF(IEW, "Execute: Calculating address for memory " "reference.\n"); // Tell the LDSTQ to execute this instruction (if it is a load). if (inst->isLoad()) { // Loads will mark themselves as executed, and their writeback // event adds the instruction to the queue to commit fault = ldstQueue.executeLoad(inst); } else if (inst->isStore()) { fault = ldstQueue.executeStore(inst); // If the store had a fault then it may not have a mem req if (!inst->isStoreConditional() && fault == NoFault) { inst->setExecuted(); instToCommit(inst); } else if (fault != NoFault) { // If the instruction faulted, then we need to send it along to commit // without the instruction completing. DPRINTF(IEW, "Store has fault %s! [sn:%lli]\n", fault->name(), inst->seqNum); // Send this instruction to commit, also make sure iew stage // realizes there is activity. inst->setExecuted(); instToCommit(inst); activityThisCycle(); } // Store conditionals will mark themselves as // executed, and their writeback event will add the // instruction to the queue to commit. } else { panic("Unexpected memory type!\n"); } } else { inst->execute(); inst->setExecuted(); instToCommit(inst); } updateExeInstStats(inst); // Check if branch prediction was correct, if not then we need // to tell commit to squash in flight instructions. Only // handle this if there hasn't already been something that // redirects fetch in this group of instructions. // This probably needs to prioritize the redirects if a different // scheduler is used. Currently the scheduler schedules the oldest // instruction first, so the branch resolution order will be correct. unsigned tid = inst->threadNumber; if (!fetchRedirect[tid] || toCommit->squashedSeqNum[tid] > inst->seqNum) { if (inst->mispredicted()) { fetchRedirect[tid] = true; DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); DPRINTF(IEW, "Predicted target was %#x, %#x.\n", inst->readPredPC(), inst->readPredNPC()); DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," " NPC: %#x.\n", inst->readNextPC(), inst->readNextNPC()); // If incorrect, then signal the ROB that it must be squashed. squashDueToBranch(inst, tid); if (inst->readPredTaken()) { predictedTakenIncorrect++; } else { predictedNotTakenIncorrect++; } } else if (ldstQueue.violation(tid)) { assert(inst->isMemRef()); // If there was an ordering violation, then get the // DynInst that caused the violation. Note that this // clears the violation signal. DynInstPtr violator; violator = ldstQueue.getMemDepViolator(tid); DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " "%#x, inst PC: %#x. Addr is: %#x.\n", violator->readPC(), inst->readPC(), inst->physEffAddr); // Ensure the violating instruction is older than // current squash/* if (fetchRedirect[tid] && violator->seqNum >= toCommit->squashedSeqNum[tid] + 1) continue;*/ fetchRedirect[tid] = true; // Tell the instruction queue that a violation has occured. instQueue.violation(inst, violator); // Squash. squashDueToMemOrder(inst,tid); ++memOrderViolationEvents; } else if (ldstQueue.loadBlocked(tid) && !ldstQueue.isLoadBlockedHandled(tid)) { fetchRedirect[tid] = true; DPRINTF(IEW, "Load operation couldn't execute because the " "memory system is blocked. PC: %#x [sn:%lli]\n", inst->readPC(), inst->seqNum); squashDueToMemBlocked(inst, tid); } } else { // Reset any state associated with redirects that will not // be used. if (ldstQueue.violation(tid)) { assert(inst->isMemRef()); DynInstPtr violator = ldstQueue.getMemDepViolator(tid); DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " "%#x, inst PC: %#x. Addr is: %#x.\n", violator->readPC(), inst->readPC(), inst->physEffAddr); DPRINTF(IEW, "Violation will not be handled because " "already squashing\n"); ++memOrderViolationEvents; } if (ldstQueue.loadBlocked(tid) && !ldstQueue.isLoadBlockedHandled(tid)) { DPRINTF(IEW, "Load operation couldn't execute because the " "memory system is blocked. PC: %#x [sn:%lli]\n", inst->readPC(), inst->seqNum); DPRINTF(IEW, "Blocked load will not be handled because " "already squashing\n"); ldstQueue.setLoadBlockedHandled(tid); } } } // Update and record activity if we processed any instructions. if (inst_num) { if (exeStatus == Idle) { exeStatus = Running; } updatedQueues = true; cpu->activityThisCycle(); } // Need to reset this in case a writeback event needs to write into the // iew queue. That way the writeback event will write into the correct // spot in the queue. wbNumInst = 0;}template <class Impl>voidDefaultIEW<Impl>::writebackInsts(){ // Loop through the head of the time buffer and wake any // dependents. These instructions are about to write back. Also // mark scoreboard that this instruction is finally complete. // Either have IEW have direct access to scoreboard, or have this // as part of backwards communication. for (int inst_num = 0; inst_num < wbWidth && toCommit->insts[inst_num]; inst_num++) { DynInstPtr inst = toCommit->insts[inst_num]; int tid = inst->threadNumber; DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %#x.\n", inst->seqNum, inst->readPC()); iewInstsToCommit[tid]++; // Some instructions will be sent to commit without having // executed because they need commit to handle them. // E.g. Uncached loads have not actually executed when they // are first sent to commit. Instead commit must tell the LSQ // when it's ready to execute the uncached load. if (!inst->isSquashed() && inst->isExecuted() && inst->getFault() == NoFault) { int dependents = instQueue.wakeDependents(inst); for (int i = 0; i < inst->numDestRegs(); i++) { //mark as Ready DPRINTF(IEW,"Setting Destination Register %i\n", inst->renamedDestRegIdx(i)); scoreboard->setReg(inst->renamedDestRegIdx(i)); } if (dependents) { producerInst[tid]++; consumerInst[tid]+= dependents; } writebackCount[tid]++; } decrWb(inst->seqNum); }}template<class Impl>voidDefaultIEW<Impl>::tick(){ wbNumInst = 0; wbCycle = 0; wroteToTimeBuffer = false; updatedQueues = false; sortInsts(); // Free function units marked as being freed this cycle. fuPool->processFreeUnits(); std::list<unsigned>::iterator threads = activeThreads->begin(); std::list<unsigned>::iterator end = activeThreads->end(); // Check stall and squash signals, dispatch any instructions. while (threads != end) { unsigned tid = *threads++; DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid); checkSignalsAndUpdate(tid); dispatch(tid); } if (exeStatus != Squashing) { executeInsts(); writebackInsts(); // Have the instruction queue try to schedule any ready instructions. // (In actuality, this scheduling is for instructions that will // be executed next cycle.) instQueue.scheduleReadyInsts(); // Also should advance its own time buffers if the stage ran. // Not the best place for it, but this works (hopefully). issueToExecQueue.advance(); } bool broadcast_free_entries = false; if (updatedQueues || exeStatus == Running || updateLSQNextCycle) { exeStatus = Idle; updateLSQNextCycle = false; broadcast_free_entries = true; } // Writeback any stores using any leftover bandwidth. ldstQueue.writebackStores(); // Check the committed load/store signals to see if there's a load // or store to commit. Also check if it's being told to execute a // nonspeculative instruction. // This is pretty inefficient... threads = activeThreads->begin(); while (threads != end) { unsigned tid = (*threads++); DPRINTF(IEW,"Processing [tid:%i]\n",tid); // Update structures based on instructions committed. if (fromCommit->commitInfo[tid].doneSeqNum != 0 && !fromCommit->commitInfo[tid].squash && !fromCommit->commitInfo[tid].robSquashing) { ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid); ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid); updateLSQNextCycle = true; instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid); } if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) { //DPRINTF(IEW,"NonspecInst from thread %i",tid); if (fromCommit->commitInfo[tid].uncached) { instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad); fromCommit->commitInfo[tid].uncachedLoad->setAtCommit(); } else { instQueue.scheduleNonSpec( fromCommit->commitInfo[tid].nonSpecSeqNum); } } if (broadcast_free_entries) { toFetch->iewInfo[tid].iqCount = instQueue.getCount(tid); toFetch->iewInfo[tid].ldstqCount = ldstQueue.getCount(tid); toRename->iewInfo[tid].usedIQ = true; toRename->iewInfo[tid].freeIQEntries = instQueue.numFreeEntries(); toRename->iewInfo[tid].usedLSQ = true; toRename->iewInfo[tid].freeLSQEntries = ldstQueue.numFreeEntries(tid); wroteToTimeBuffer = true; } DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n", tid, toRename->iewInfo[tid].dispatched); } DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). " "LSQ has %i free entries.\n", instQueue.numFreeEntries(), instQueue.hasReadyInsts(), ldstQueue.numFreeEntries()); updateStatus(); if (wroteToTimeBuffer) { DPRINTF(Activity, "Activity this cycle.\n"); cpu->activityThisCycle(); }}template <class Impl>voidDefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst){ int thread_number = inst->threadNumber; // // Pick off the software prefetches //#ifdef TARGET_ALPHA if (inst->isDataPrefetch()) iewExecutedSwp[thread_number]++; else iewIewExecutedcutedInsts++;#else iewExecutedInsts++;#endif // // Control operations // if (inst->isControl()) iewExecutedBranches[thread_number]++; // // Memory operations // if (inst->isMemRef()) { iewExecutedRefs[thread_number]++; if (inst->isLoad()) { iewExecLoadInsts[thread_number]++; } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?