iew_impl.hh
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 1,585 行 · 第 1/4 页
HH
1,585 行
wroteToTimeBuffer = true; return; } if (checkStall(tid)) { block(tid); dispatchStatus[tid] = Blocked; return; } if (dispatchStatus[tid] == Blocked) { // Status from previous cycle was blocked, but there are no more stall // conditions. Switch over to unblocking. DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n", tid); dispatchStatus[tid] = Unblocking; unblock(tid); return; } if (dispatchStatus[tid] == Squashing) { // Switch status to running if rename isn't being told to block or // squash this cycle. DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n", tid); dispatchStatus[tid] = Running; return; }}template <class Impl>voidDefaultIEW<Impl>::sortInsts(){ int insts_from_rename = fromRename->size;#ifdef DEBUG for (int i = 0; i < numThreads; i++) assert(insts[i].empty());#endif for (int i = 0; i < insts_from_rename; ++i) { insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]); }}template <class Impl>voidDefaultIEW<Impl>::emptyRenameInsts(unsigned tid){ DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions\n", tid); while (!insts[tid].empty()) { if (insts[tid].front()->isLoad() || insts[tid].front()->isStore() ) { toRename->iewInfo[tid].dispatchedToLSQ++; } toRename->iewInfo[tid].dispatched++; insts[tid].pop(); }}template <class Impl>voidDefaultIEW<Impl>::wakeCPU(){ cpu->wakeCPU();}template <class Impl>voidDefaultIEW<Impl>::activityThisCycle(){ DPRINTF(Activity, "Activity this cycle.\n"); cpu->activityThisCycle();}template <class Impl>inline voidDefaultIEW<Impl>::activateStage(){ DPRINTF(Activity, "Activating stage.\n"); cpu->activateStage(O3CPU::IEWIdx);}template <class Impl>inline voidDefaultIEW<Impl>::deactivateStage(){ DPRINTF(Activity, "Deactivating stage.\n"); cpu->deactivateStage(O3CPU::IEWIdx);}template<class Impl>voidDefaultIEW<Impl>::dispatch(unsigned tid){ // If status is Running or idle, // call dispatchInsts() // If status is Unblocking, // buffer any instructions coming from rename // continue trying to empty skid buffer // check if stall conditions have passed if (dispatchStatus[tid] == Blocked) { ++iewBlockCycles; } else if (dispatchStatus[tid] == Squashing) { ++iewSquashCycles; } // Dispatch should try to dispatch as many instructions as its bandwidth // will allow, as long as it is not currently blocked. if (dispatchStatus[tid] == Running || dispatchStatus[tid] == Idle) { DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run " "dispatch.\n", tid); dispatchInsts(tid); } else if (dispatchStatus[tid] == Unblocking) { // Make sure that the skid buffer has something in it if the // status is unblocking. assert(!skidsEmpty()); // If the status was unblocking, then instructions from the skid // buffer were used. Remove those instructions and handle // the rest of unblocking. dispatchInsts(tid); ++iewUnblockCycles; if (validInstsFromRename()) { // Add the current inputs to the skid buffer so they can be // reprocessed when this stage unblocks. skidInsert(tid); } unblock(tid); }}template <class Impl>voidDefaultIEW<Impl>::dispatchInsts(unsigned tid){ // Obtain instructions from skid buffer if unblocking, or queue from rename // otherwise. std::queue<DynInstPtr> &insts_to_dispatch = dispatchStatus[tid] == Unblocking ? skidBuffer[tid] : insts[tid]; int insts_to_add = insts_to_dispatch.size(); DynInstPtr inst; bool add_to_iq = false; int dis_num_inst = 0; // Loop through the instructions, putting them in the instruction // queue. for ( ; dis_num_inst < insts_to_add && dis_num_inst < dispatchWidth; ++dis_num_inst) { inst = insts_to_dispatch.front(); if (dispatchStatus[tid] == Unblocking) { DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid " "buffer\n", tid); } // Make sure there's a valid instruction there. assert(inst); DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to " "IQ.\n", tid, inst->readPC(), inst->seqNum, inst->threadNumber); // Be sure to mark these instructions as ready so that the // commit stage can go ahead and execute them, and mark // them as issued so the IQ doesn't reprocess them. // Check for squashed instructions. if (inst->isSquashed()) { DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, " "not adding to IQ.\n", tid); ++iewDispSquashedInsts; insts_to_dispatch.pop(); //Tell Rename That An Instruction has been processed if (inst->isLoad() || inst->isStore()) { toRename->iewInfo[tid].dispatchedToLSQ++; } toRename->iewInfo[tid].dispatched++; continue; } // Check for full conditions. if (instQueue.isFull(tid)) { DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid); // Call function to start blocking. block(tid); // Set unblock to false. Special case where we are using // skidbuffer (unblocking) instructions but then we still // get full in the IQ. toRename->iewUnblock[tid] = false; ++iewIQFullEvents; break; } else if (ldstQueue.isFull(tid)) { DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid); // Call function to start blocking. block(tid); // Set unblock to false. Special case where we are using // skidbuffer (unblocking) instructions but then we still // get full in the IQ. toRename->iewUnblock[tid] = false; ++iewLSQFullEvents; break; } // Otherwise issue the instruction just fine. if (inst->isLoad()) { DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " "encountered, adding to LSQ.\n", tid); // Reserve a spot in the load store queue for this // memory access. ldstQueue.insertLoad(inst); ++iewDispLoadInsts; add_to_iq = true; toRename->iewInfo[tid].dispatchedToLSQ++; } else if (inst->isStore()) { DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " "encountered, adding to LSQ.\n", tid); ldstQueue.insertStore(inst); ++iewDispStoreInsts; if (inst->isStoreConditional()) { // Store conditionals need to be set as "canCommit()" // so that commit can process them when they reach the // head of commit. // @todo: This is somewhat specific to Alpha. inst->setCanCommit(); instQueue.insertNonSpec(inst); add_to_iq = false; ++iewDispNonSpecInsts; } else { add_to_iq = true; } toRename->iewInfo[tid].dispatchedToLSQ++; } else if (inst->isMemBarrier() || inst->isWriteBarrier()) { // Same as non-speculative stores. inst->setCanCommit(); instQueue.insertBarrier(inst); add_to_iq = false; } else if (inst->isNop()) { DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, " "skipping.\n", tid); inst->setIssued(); inst->setExecuted(); inst->setCanCommit(); instQueue.recordProducer(inst); iewExecutedNop[tid]++; add_to_iq = false; } else if (inst->isExecuted()) { assert(0 && "Instruction shouldn't be executed.\n"); DPRINTF(IEW, "Issue: Executed branch encountered, " "skipping.\n"); inst->setIssued(); inst->setCanCommit(); instQueue.recordProducer(inst); add_to_iq = false; } else { add_to_iq = true; } if (inst->isNonSpeculative()) { DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction " "encountered, skipping.\n", tid); // Same as non-speculative stores. inst->setCanCommit(); // Specifically insert it as nonspeculative. instQueue.insertNonSpec(inst); ++iewDispNonSpecInsts; add_to_iq = false; } // If the instruction queue is not full, then add the // instruction. if (add_to_iq) { instQueue.insert(inst); } insts_to_dispatch.pop(); toRename->iewInfo[tid].dispatched++; ++iewDispatchedInsts; } if (!insts_to_dispatch.empty()) { DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n", tid); block(tid); toRename->iewUnblock[tid] = false; } if (dispatchStatus[tid] == Idle && dis_num_inst) { dispatchStatus[tid] = Running; updatedQueues = true; } dis_num_inst = 0;}template <class Impl>voidDefaultIEW<Impl>::printAvailableInsts(){ int inst = 0; std::cout << "Available Instructions: "; while (fromIssue->insts[inst]) { if (inst%3==0) std::cout << "\n\t"; std::cout << "PC: " << fromIssue->insts[inst]->readPC() << " TN: " << fromIssue->insts[inst]->threadNumber << " SN: " << fromIssue->insts[inst]->seqNum << " | "; inst++; } std::cout << "\n";}template <class Impl>voidDefaultIEW<Impl>::executeInsts(){ wbNumInst = 0; wbCycle = 0; std::list<unsigned>::iterator threads = activeThreads->begin(); std::list<unsigned>::iterator end = activeThreads->end(); while (threads != end) { unsigned tid = *threads++; fetchRedirect[tid] = false; } // Uncomment this if you want to see all available instructions.// printAvailableInsts(); // Execute/writeback any instructions that are available. int insts_to_execute = fromIssue->size; int inst_num = 0; for (; inst_num < insts_to_execute; ++inst_num) { DPRINTF(IEW, "Execute: Executing instructions from IQ.\n"); DynInstPtr inst = instQueue.getInstToExecute();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?