Ejemplo n.º 1
0
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);

}
Ejemplo n.º 2
0
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);
  
}
Ejemplo n.º 3
0
DInst *LSQFull::executing(DInst *dinst)
  /* dinst got executed (out-of-order) {{{1 */
{
  I(dinst->getAddr());

  AddrType tag = calcWord(dinst);

  const Instruction *inst = dinst->getInst();
  DInst *faulty = 0;

#if 0
  AddrDInstQMap::const_iterator instIt = instMap.begin();
  I(instIt != instMap.end());

  I(!dinst->isExecuted());

  while(instIt != instMap.end()) {
    if (instIt->first != tag){
      instIt++;
      continue; 
    }
#endif
  std::pair<AddrDInstQMap::iterator, AddrDInstQMap::iterator> ret;
  ret = instMap.equal_range(tag);
  for (AddrDInstQMap::iterator instIt=ret.first; instIt!=ret.second; ++instIt) {
    I(instIt->first == tag);

    //inst->dump("Executed");
    DInst *qdinst = instIt->second;
    if(qdinst == dinst) {
      continue;
    }

    const Instruction *qinst  = qdinst->getInst();

    //bool beforeInst = qdinst->getID() < dinst->getID();
    bool oooExecuted = qdinst->getID() > dinst->getID();
    if(oooExecuted){

      if(qdinst->isExecuted() && qdinst->getPC() != dinst->getPC()) { 

        if(inst->isStore() && qinst->isLoad()) { 
          if (faulty == 0)
            faulty = qdinst; 
          else if (faulty->getID() < qdinst->getID())
            faulty = qdinst;
        }
      }
    }else{
      if (!dinst->isLoadForwarded() && inst->isLoad() && qinst->isStore() && qdinst->isExecuted()) {
        dinst->setLoadForwarded();
        stldForwarding.inc(dinst->getStatsFlag());
      }
    }
  }

  I(!dinst->isExecuted()); // first clear, then mark executed
  return faulty;
}
/* }}} */

void LSQFull::remove(DInst *dinst)
  /* Remove from the LSQ {{{1 (in-order) */
{
  I(dinst->getAddr());

 //const Instruction *inst = dinst->getInst();

  std::pair<AddrDInstQMap::iterator,AddrDInstQMap::iterator> rangeIt;
  //rangeIt = instMap.equal_range(calcWord(dinst));  
  AddrDInstQMap::iterator instIt = instMap.begin();

  //for(AddrDInstQMap::iterator it = rangeIt.first; it != rangeIt.second ; it++) {
  while(instIt != instMap.end()){
    if(instIt->second == dinst) {
      instMap.erase(instIt);
      return;
    }
    instIt++;
  }
}