commit_impl.hh
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 1,375 行 · 第 1/3 页
HH
1,375 行
oldpc = PC[tid]; cpu->system->pcEventQueue.service(thread[tid]->getTC()); count++; } while (oldpc != PC[tid]); if (count > 1) { DPRINTF(Commit, "PC skip function event, stopping commit\n"); break; } } else { DPRINTF(Commit, "Unable to commit head instruction PC:%#x " "[tid:%i] [sn:%i].\n", head_inst->readPC(), tid ,head_inst->seqNum); break; } } } DPRINTF(CommitRate, "%i\n", num_committed); numCommittedDist.sample(num_committed); if (num_committed == commitWidth) { commitEligibleSamples++; }}template <class Impl>boolDefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num){ assert(head_inst); int tid = head_inst->threadNumber; // If the instruction is not executed yet, then it will need extra // handling. Signal backwards that it should be executed. if (!head_inst->isExecuted()) { // Keep this number correct. We have not yet actually executed // and committed this instruction. thread[tid]->funcExeInst--; if (head_inst->isNonSpeculative() || head_inst->isStoreConditional() || head_inst->isMemBarrier() || head_inst->isWriteBarrier()) { DPRINTF(Commit, "Encountered a barrier or non-speculative " "instruction [sn:%lli] at the head of the ROB, PC %#x.\n", head_inst->seqNum, head_inst->readPC()); if (inst_num > 0 || iewStage->hasStoresToWB()) { DPRINTF(Commit, "Waiting for all stores to writeback.\n"); return false; } toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum; // Change the instruction so it won't try to commit again until // it is executed. head_inst->clearCanCommit(); ++commitNonSpecStalls; return false; } else if (head_inst->isLoad()) { if (inst_num > 0 || iewStage->hasStoresToWB()) { DPRINTF(Commit, "Waiting for all stores to writeback.\n"); return false; } assert(head_inst->uncacheable()); DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n", head_inst->seqNum, head_inst->readPC()); // Send back the non-speculative instruction's sequence // number. Tell the lsq to re-execute the load. toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum; toIEW->commitInfo[tid].uncached = true; toIEW->commitInfo[tid].uncachedLoad = head_inst; head_inst->clearCanCommit(); return false; } else { panic("Trying to commit un-executed instruction " "of unknown type!\n"); } } if (head_inst->isThreadSync()) { // Not handled for now. panic("Thread sync instructions are not handled yet.\n"); } // Check if the instruction caused a fault. If so, trap. Fault inst_fault = head_inst->getFault(); // Stores mark themselves as completed. if (!head_inst->isStore() && inst_fault == NoFault) { head_inst->setCompleted(); }#if USE_CHECKER // Use checker prior to updating anything due to traps or PC // based events. if (cpu->checker) { cpu->checker->verify(head_inst); }#endif // DTB will sometimes need the machine instruction for when // faults happen. So we will set it here, prior to the DTB // possibly needing it for its fault. thread[tid]->setInst( static_cast<TheISA::MachInst>(head_inst->staticInst->machInst)); if (inst_fault != NoFault) { DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n", head_inst->seqNum, head_inst->readPC()); if (iewStage->hasStoresToWB() || inst_num > 0) { DPRINTF(Commit, "Stores outstanding, fault must wait.\n"); return false; } head_inst->setCompleted();#if USE_CHECKER if (cpu->checker && head_inst->isStore()) { cpu->checker->verify(head_inst); }#endif assert(!thread[tid]->inSyscall); // Mark that we're in state update mode so that the trap's // execution doesn't generate extra squashes. thread[tid]->inSyscall = true; // Execute the trap. Although it's slightly unrealistic in // terms of timing (as it doesn't wait for the full timing of // the trap event to complete before updating state), it's // needed to update the state as soon as possible. This // prevents external agents from changing any specific state // that the trap need. cpu->trap(inst_fault, tid); // Exit state update mode to avoid accidental updating. thread[tid]->inSyscall = false; commitStatus[tid] = TrapPending; if (head_inst->traceData) { head_inst->traceData->setFetchSeq(head_inst->seqNum); head_inst->traceData->setCPSeq(thread[tid]->numInst); head_inst->traceData->dump(); delete head_inst->traceData; head_inst->traceData = NULL; } // Generate trap squash event. generateTrapEvent(tid);// warn("%lli fault (%d) handled @ PC %08p", curTick, inst_fault->name(), head_inst->readPC()); return false; } updateComInstStats(head_inst);#if FULL_SYSTEM if (thread[tid]->profile) {// bool usermode = TheISA::inUserMode(thread[tid]->getTC());// thread[tid]->profilePC = usermode ? 1 : head_inst->readPC(); thread[tid]->profilePC = head_inst->readPC(); ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(), head_inst->staticInst); if (node) thread[tid]->profileNode = node; }#endif if (head_inst->traceData) { head_inst->traceData->setFetchSeq(head_inst->seqNum); head_inst->traceData->setCPSeq(thread[tid]->numInst); head_inst->traceData->dump(); delete head_inst->traceData; head_inst->traceData = NULL; } // Update the commit rename map for (int i = 0; i < head_inst->numDestRegs(); i++) { renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i), head_inst->renamedDestRegIdx(i)); } if (head_inst->isCopy()) panic("Should not commit any copy instructions!"); // Finally clear the head ROB entry. rob->retireHead(tid); // If this was a store, record it for this cycle. if (head_inst->isStore()) committedStores[tid] = true; // Return true to indicate that we have committed an instruction. return true;}template <class Impl>voidDefaultCommit<Impl>::getInsts(){ DPRINTF(Commit, "Getting instructions from Rename stage.\n"); // Read any renamed instructions and place them into the ROB. int insts_to_process = std::min((int)renameWidth, fromRename->size); for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) { DynInstPtr inst; inst = fromRename->insts[inst_num]; int tid = inst->threadNumber; if (!inst->isSquashed() && commitStatus[tid] != ROBSquashing && commitStatus[tid] != TrapPending) { changedROBNumEntries[tid] = true; DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n", inst->readPC(), inst->seqNum, tid); rob->insertInst(inst); assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid)); youngestSeqNum[tid] = inst->seqNum; } else { DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was " "squashed, skipping.\n", inst->readPC(), inst->seqNum, tid); } }}template <class Impl>voidDefaultCommit<Impl>::skidInsert(){ DPRINTF(Commit, "Attempting to any instructions from rename into " "skidBuffer.\n"); for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) { DynInstPtr inst = fromRename->insts[inst_num]; if (!inst->isSquashed()) { DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ", "skidBuffer.\n", inst->readPC(), inst->seqNum, inst->threadNumber); skidBuffer.push(inst); } else { DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was " "squashed, skipping.\n", inst->readPC(), inst->seqNum, inst->threadNumber); } }}template <class Impl>voidDefaultCommit<Impl>::markCompletedInsts(){ // Grab completed insts out of the IEW instruction queue, and mark // instructions completed within the ROB. for (int inst_num = 0; inst_num < fromIEW->size && fromIEW->insts[inst_num]; ++inst_num) { if (!fromIEW->insts[inst_num]->isSquashed()) { DPRINTF(Commit, "[tid:%i]: Marking PC %#x, [sn:%lli] ready " "within ROB.\n", fromIEW->insts[inst_num]->threadNumber, fromIEW->insts[inst_num]->readPC(), fromIEW->insts[inst_num]->seqNum); // Mark the instruction as ready to commit. fromIEW->insts[inst_num]->setCanCommit(); } }}template <class Impl>boolDefaultCommit<Impl>::robDoneSquashing(){ std::list<unsigned>::iterator threads = activeThreads->begin(); std::list<unsigned>::iterator end = activeThreads->end(); while (threads != end) { unsigned tid = *threads++; if (!rob->isDoneSquashing(tid)) return false; } return true;}template <class Impl>voidDefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst){ unsigned thread = inst->threadNumber; // // Pick off the software prefetches //#ifdef TARGET_ALPHA if (inst->isDataPrefetch()) { statComSwp[thread]++; } else { statComInst[thread]++; }#else statComInst[thread]++;#endif // // Control Instructions // if (inst->isControl()) statComBranches[thread]++; // // Memory references // if (inst->isMemRef()) { statComRefs[thread]++; if (inst->isLoad()) { statComLoads[thread]++; } } if (inst->isMemBarrier()) { statComMembars[thread]++; }}////////////////////////////////////////// //// SMT COMMIT POLICY MAINTAINED HERE //// //////////////////////////////////////////template <class Impl>intDefaultCommit<Impl>::getCommittingThread(){ if (numThreads > 1) { switch (commitPolicy) { case Aggressive: //If Policy is Aggressive, commit will call //this function multiple times per //cycle return oldestReady(); case RoundRobin: return roundRobin(); case OldestReady: return oldestReady(); default: return -1; } } else { assert(!activeThreads->empty()); int tid = activeThreads->front(); if (commitStatus[tid] == Running || commitStatus[tid] == Idle || commitStatus[tid] == FetchTrapPending) { return tid; } else { return -1; } }}template<class Impl>intDefaultCommit<Impl>::roundRobin(){ std::list<unsigned>::iterator pri_iter = priority_list.begin(); std::list<unsigned>::iterator end = priority_list.end(); while (pri_iter != end) { unsigned tid = *pri_iter; if (commitStatus[tid] == Running || commitStatus[tid] == Idle || commitStatus[tid] == FetchTrapPending) { if (rob->isHeadReady(tid)) { priority_list.erase(pri_iter); priority_list.push_back(tid); return tid; } } pri_iter++; } return -1;}template<class Impl>intDefaultCommit<Impl>::oldestReady(){ unsigned oldest = 0; bool first = true; std::list<unsigned>::iterator threads = activeThreads->begin(); std::list<unsigned>::iterator end = activeThreads->end(); while (threads != end) { unsigned tid = *threads++; if (!rob->isEmpty(tid) && (commitStatus[tid] == Running || commitStatus[tid] == Idle || commitStatus[tid] == FetchTrapPending)) { if (rob->isHeadReady(tid)) { DynInstPtr head_inst = rob->readHeadInst(tid); if (first) { oldest = tid; first = false; } else if (head_inst->seqNum < oldest) { oldest = tid; } } } } if (!first) { return oldest; } else { return -1; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?