void GProcessor::retire() { #ifdef DEBUG // Check for progress. When a processor gets stuck, it sucks big time if ((((int)globalClock) & 0x1FFFFFL) == 0) { if (ROB.empty()) { // ROB should not be empty for lots of time if (prevDInstID == 1) { MSG("GProcessor::retire CPU[%d] ROB empty for long time @%lld", Id, globalClock); } prevDInstID = 1; }else{ DInst *dinst = ROB.top(); if (prevDInstID == dinst->getID()) { I(0); MSG("ExeEngine::retire CPU[%d] no forward progress from pc=0x%x with %d @%lld" ,Id, (uint)dinst->getInst()->getAddr() ,(uint)dinst->getInst()->currentID(), globalClock ); dinst->dump("HEAD"); LDSTBuffer::dump(""); } prevDInstID = dinst->getID(); } } #endif robUsed.sample(ROB.size()); ushort i; for(i=0;i<RetireWidth && !ROB.empty();i++) { DInst *dinst = ROB.top(); if( !dinst->isExecuted() ) { addStatsNoRetire(i, dinst, NotExecuted); return; } // save it now because retire can destroy DInst int rp = dinst->getInst()->getDstPool(); //BEGIN STAT -------------------------------------------------------------------------------------------------------- #if defined(STAT) ConfObject* statConf = new ConfObject; THREAD_ID threadID = dinst->get_threadID(); //Check to see if we're profling or not if(statConf->return_enableSynth() == 1) { Synthesis::checkContainerSizes(threadID); //FIXME Bug with flushing the instructionQueues tuple<DInst, Time_t> instruction_cycle(*dinst, globalClock); Synthesis::analysis(instruction_cycle); // instructionQueueVector[threadID]->push_back(instruction_cycle); // if((INT_32)instructionQueueVector[threadID]->size() > statConf->return_windowSize()) // { // Synthesis::analysis(instructionQueueVector[threadID]->front()); // instructionQueueVector[threadID]->pop_front(); // } // // //if this is the end of the thread, we need to flush the instruction queue // if(dinst->getInst()->getICode()->func == mint_exit) // { // while(instructionQueueVector[threadID]->empty() == 0) // { // Synthesis::analysis(instructionQueueVector[threadID]->front()); // instructionQueueVector[threadID]->pop_front(); // } // } } delete statConf; #endif //END STAT ---------------------------------------------------------------------------------------------------------- //BEGIN PROFILING -------------------------------------------------------------------------------------------------------- #if defined(PROFILE) ConfObject *statConf = new ConfObject; THREAD_ID threadID = dinst->get_threadID(); if(statConf->return_enableProfiling() == 1) { tuple<DInst, Time_t> instruction_cycle(*dinst, globalClock); //Need to ensure that the vector is large enough to hold the next thread if(threadID >= Profiling::transactionDistance.size()) { if(threadID == Profiling::transactionDistance.size()) { std::cerr << "Profiling::Push back to transactionDistance with " << threadID; UINT_32 temp_1 = 0; Profiling::transactionDistance.push_back(temp_1); std::cerr << " and new size of " << Profiling::transactionDistance.size() << "*" << std::endl; } else { std::cerr << "Profiling::Resizing transactionDistance with " << threadID; Profiling::transactionDistance.resize(threadID + 1); std::cerr << " and new size of " << Profiling::transactionDistance.size() << "*" << std::endl; } } if(threadID >= Profiling::isTransaction.size()) { if(threadID == Profiling::isTransaction.size()) { std::cerr << "Profiling::Push back to isTransaction with " << threadID; BOOL temp_1 = 0; Profiling::isTransaction.push_back(temp_1); std::cerr << " and new size of " << Profiling::isTransaction.size() << "*" << std::endl; } else { std::cerr << "Profiling::Resizing isTransaction with " << threadID; Profiling::isTransaction.resize(threadID + 1); std::cerr << " and new size of " << Profiling::isTransaction.size() << "*" << std::endl; } } if(threadID >= instructionQueueVector.size()) { if(threadID == instructionQueueVector.size()) { std::cerr << "Profiling::Push back to instructionQueueVector with " << threadID; instructionQueueVector.push_back(new std::deque< tuple<DInst, Time_t> >); std::cerr << " and new size of " << instructionQueueVector.size() << " and capacity of " << instructionQueueVector.capacity() << "*" << std::endl; } else { std::cerr << "Profiling::Resizing instructionQueueVector with " << threadID; instructionQueueVector.resize(threadID + 1, new std::deque< tuple<DInst, Time_t> >); std::cerr << " and new size of " << instructionQueueVector.size() << " and capacity of " << instructionQueueVector.capacity() << "*" << std::endl; } } if(threadID >= Profiling::currBBStats.size()) { if(threadID == Profiling::currBBStats.size()) { std::cerr << "Profiling::Push back to currBBStats with " << threadID; Profiling::currBBStats.push_back(new WorkloadCharacteristics()); std::cerr << " and new size of " << Profiling::currBBStats.size() << " and capacity of " << Profiling::currBBStats.capacity() << "*" << std::endl; } else { std::cerr << "Profiling::Resizing currBBStats with " << threadID; Profiling::currBBStats.resize(threadID + 1, new WorkloadCharacteristics()); std::cerr << " and new size of " << Profiling::currBBStats.size() << " and capacity of " << Profiling::currBBStats.capacity() << "*" << std::endl; } } if(threadID >= Profiling::firstTransaction.size()) { if(threadID == Profiling::firstTransaction.size()) { std::cerr << "Profiling::Push back to firstTransaction with " << threadID; UINT_32 temp_1 = 1; Profiling::firstTransaction.push_back(temp_1); std::cerr << " and new size of " << Profiling::firstTransaction.size() << " and capacity of " << Profiling::firstTransaction.capacity() << "*" << std::endl; } else { std::cerr << "Profiling::Resizing firstTransaction with " << threadID; Profiling::firstTransaction.resize(threadID + 1); std::cerr << " and new size of " << Profiling::firstTransaction.size() << " and capacity of " << Profiling::firstTransaction.capacity() << "*" << std::endl; Profiling::firstTransaction[threadID] = 1; } } instructionQueueVector[threadID]->push_back(instruction_cycle); if((INT_32)instructionQueueVector[threadID]->size() > statConf->return_windowSize()) { instruction_cycle = instructionQueueVector[threadID]->front(); instructionQueueVector[threadID]->pop_front(); Profiling::analysis(instruction_cycle); } } delete statConf; #endif //END PROFILING -------------------------------------------------------------------------------------------------------- #if (defined TM) // We must grab the type here since we will not be able to use it past the retirement phase transInstType tempTransType = dinst->transType; sType synchType = dinst->synchType; int transPid = dinst->transPid; int transTid = dinst->transTid; int transBCFlag = dinst->transBCFlag; #endif bool fake = dinst->isFake(); I(dinst->getResource()); RetOutcome retOutcome = dinst->getResource()->retire(dinst); if( retOutcome != Retired) { addStatsNoRetire(i, dinst, retOutcome); return; } // dinst CAN NOT be used beyond this point #if (defined TM) instCountTM++; // Call the proper reporting function based on the type of instruction switch(tempTransType){ case transCommit: if(transBCFlag != 2) tmReport->reportCommit(transPid); break; case transBegin: if(transBCFlag != 2) tmReport->reportBegin(transPid, this->Id); break; case transLoad: tmReport->reportLoad(transPid); break; case transStore: tmReport->reportStore(transPid); break; case transAbort: tmReport->beginTMStats(instCountTM); break; case transInt: case transFp: case transBJ: case transFence: tmReport->registerTransInst(transPid,tempTransType); break; case transOther: break; case transNT: tmReport->incrementCommittedInstCountByCpu ( this->Id ); break; } if (synchType == barrier ) { tmReport->reportBarrier ( this->Id); } #endif if (!fake) regPool[rp]++; ROB.pop(); robEnergy->inc(); // read ROB entry (finished?, update retirement rat...) } if(!ROB.empty() || i != 0) addStatsRetire(i); }
void GProcessor::retire() { #ifdef DEBUG // Check for progress. When a processor gets stuck, it sucks big time if ((((int)globalClock) & 0x1FFFFFL) == 0) { if (ROB.empty()) { // ROB should not be empty for lots of time if (prevDInstID == 1) { MSG("GProcessor::retire CPU[%d] ROB empty for long time @%lld", Id, globalClock); } prevDInstID = 1; } else { DInst *dinst = ROB.top(); if (prevDInstID == dinst->getID()) { I(0); MSG("ExeEngine::retire CPU[%d] no forward progress from pc=0x%x with %d @%lld" ,Id, (uint)dinst->getInst()->getAddr() ,(uint)dinst->getInst()->currentID(), globalClock ); dinst->dump("HEAD"); LDSTBuffer::dump(""); } prevDInstID = dinst->getID(); } } #endif robUsed.sample(ROB.size()); ushort i; for(i=0; i<RetireWidth && !ROB.empty(); i++) { DInst *dinst = ROB.top(); if( !dinst->isExecuted() ) { addStatsNoRetire(i, dinst, NotExecuted); return; } uint32_t refetchAt = 1; for(VAddr refAddr: dinst->getRefetchAddrs()) { CBMemRequest::create(refetchAt, memorySystem->getDataSource(), MemRead, refAddr, 0); refetchAt++; } // save it now because retire can destroy DInst int32_t rp = dinst->getInst()->getDstPool(); bool fake = dinst->isFake(); I(dinst->getResource()); RetOutcome retOutcome = dinst->getResource()->retire(dinst); if( retOutcome != Retired) { addStatsNoRetire(i, dinst, retOutcome); return; } // dinst CAN NOT be used beyond this point if (!fake) regPool[rp]++; ROB.pop(); robEnergy->inc(); // read ROB entry (finished?, update retirement rat...) #if (defined TM) tmInsts.inc(); #endif } if(!ROB.empty() || i != 0) addStatsRetire(i); }