Пример #1
0
bool SingleMSHR<Addr_t, Cache_t>::issue(Addr_t paddr, MemOperation mo)
{
  MSHRit it = ms.find(calcLineAddr(paddr));

  nUse.inc();
  if(mo == MemRead)
    nUseReads.inc();

  if(mo == MemWrite)
    nUseWrites.inc();

  if(!overflow.empty()) {
    return false;
  }

  I(nFreeEntries >= 0 && nFreeEntries <=nEntries);

  if(it == ms.end()) {
    if(nFreeEntries > 0) {
      ms[calcLineAddr(paddr)].firstRequest(paddr, calcLineAddr(paddr), 
					   nReads, nWrites, mo);
      bf.insert(calcLineAddr(paddr));
      nFreeEntries--;

#ifdef MSHR_BASICOCCSTATS
      updateOccHistogram();
#endif

      nOutsReqs++;

#ifdef MSHR_BASICOCCSTATS
      if(mo == MemRead)
	occStats->incRdReqs();
#endif

      nIssuesNewEntry.inc();
      avgQueueSize.sample(0);

      checkSubEntries(paddr, mo);

#ifdef MSHR_EXTRAOCCSTATS
      occStats->sampleEntry( calcLineAddr(paddr) );
#endif
      return true;
    }
  }

  return false;
}
Пример #2
0
bool SingleMSHR<Addr_t, Cache_t>::isOnlyWrites(Addr_t paddr)
{
  const_MSHRit it = ms.find(calcLineAddr(paddr));
  I(it != ms.end());

  return ((*it).second.getUsedReads() == 0);
}
Пример #3
0
bool SingleMSHR<Addr_t, Cache_t>::canAcceptRequestSpecial(Addr_t paddr, MemOperation mo)
{
  if(!overflow.empty()) {
    nCanNotAccept.inc();
    return false;
  }

  const_MSHRit it = ms.find(calcLineAddr(paddr));
  I(nFreeEntries >= 0 && nFreeEntries <= nEntries);

  if(it == ms.end()) {
    if(nFreeEntries <= 0) {
      nCanNotAccept.inc();
      return false;
    }
    nCanAccept.inc();
    return true;
  }

  I(it != ms.end());

  bool canAccept = (*it).second.canAcceptRequest(mo);
  if(canAccept)
    nCanAccept.inc();
  else {
    nCanNotAccept.inc();

    if(mo == MemWrite && !(*it).second.hasFreeWrites())
      nCanNotAcceptTooManyWrites.inc();
    else
      nCanNotAcceptSubEntryFull.inc();
  }

  return canAccept;
}
Пример #4
0
MSHRentry<Addr_t>* SingleMSHR<Addr_t, Cache_t>::getEntry(Addr_t paddr)
{
  MSHRentry<Addr_t> *me = NULL;
  MSHRit dispIt = ms.find(calcLineAddr(paddr));

  if(dispIt!=ms.end())
    me = &((*dispIt).second);

  return me;
}
Пример #5
0
void SingleMSHR<Addr_t, Cache_t>::checkSubEntries(Addr_t paddr, MemOperation mo)
{
  MSHRit it = ms.find(calcLineAddr(paddr));
  I(it != ms.end());

  if((*it).second.isRdWrSharing()) {
    if(!(*it).second.hasFreeReads() ||!(*it).second.hasFreeWrites()) {
      nFullReadEntries++;
      nFullWriteEntries++;
    }
  } else {
    if(!(*it).second.hasFreeReads() && mo == MemRead) {
      nFullReadEntries++;
    }
    if(!(*it).second.hasFreeWrites() && mo == MemWrite) {
      nFullWriteEntries++;
    }
  }
}
Пример #6
0
void SingleMSHR<Addr_t, Cache_t>::addEntry(Addr_t paddr, CallbackBase *c,
                                           CallbackBase *ovflwc, MemOperation mo)
{
  MSHRit it = ms.find(calcLineAddr(paddr));
  I(ovflwc); // for single MSHR, overflow handler REQUIRED!

  if(!overflow.empty()) {
    toOverflow(paddr, c, ovflwc, mo);
    return;
  }

  if(it == ms.end())  {// we must be overflowing because the issue did not happen
    toOverflow(paddr, c, ovflwc, mo);
    return;
  }

  I(it != ms.end());

  if((*it).second.addRequest(paddr, c, mo)) {
    // ok, the addrequest succeeded, the request was added
    avgQueueSize.sample((*it).second.getPendingReqs() - 1);
    nOutsReqs++;

#ifdef MSHR_BASICOCCSTATS
    if(mo == MemRead)
      occStats->incRdReqs();
#endif

    // there was no overflow, so the callback needs to be destroyed
    ovflwc->destroy();
    // check to see if we have filled up the subentries
    checkSubEntries(paddr, mo);

    //MSG("[%llu] nFullRd=%d nFullWr=%d a:%lu",globalClock,
    //      nFullReadEntries,nFullWriteEntries, calcLineAddr(paddr));
    return;
  } else {
    // too many oustanding requests to the same line already. send to overflow
    toOverflow(paddr, c, ovflwc, mo);
    return;
  }
}
Пример #7
0
bool SingleMSHR<Addr_t, Cache_t>::retire(Addr_t paddr)
{
  bool rmEntry = false;

  MSHRit it = ms.find(calcLineAddr(paddr));
  I(it != ms.end());
  I(calcLineAddr(paddr) == (*it).second.getLineAddr());

  maxOutsReqs.sample(nOutsReqs);
  nOutsReqs--;

  //MSG("[%llu] nFullSubE=%d a=%lu",globalClock,nFullReadEntries,calcLineAddr(paddr));

  rmEntry = (*it).second.retire();
  if(rmEntry) {
    // the last pending request for the MSHRentry was completed
    // recycle the entry
    nRetiredEntries.inc();
    avgReqsPerLine.sample((*it).second.getUsedReads() + (*it).second.getUsedWrites());
    maxUsedEntries.sample(nEntries - nFreeEntries);
    avgWritesPerLine.sample((*it).second.getUsedWrites());
    avgWritesPerLineComb.sample((*it).second.getNWrittenWords());
    
    occStats->decRdReqs((*it).second.getUsedReads());

    if((*it).second.getUsedWrites() > 0)
      nRetiredEntriesWritten.inc();

    if( ! (*it).second.hasFreeReads() ) {
      nFullReadEntries--;
      I(nFullReadEntries>=0);
    }

    if( ! (*it).second.hasFreeWrites() ) {
      nFullWriteEntries--;
      I(nFullWriteEntries>=0);
    }

    if((*it).second.isL2Hit()) 
      occStats->avgReadSubentriesL2Hit.sample((*it).second.getUsedReads());
    else
      occStats->avgReadSubentriesL2Miss.sample((*it).second.getUsedReads());

#ifdef MSHR_EXTRAOCCSTATS
    // extra MSHR occ stats
    occStats->subEntriesHist.sample((*it).second.getUsedReads()+
				    (*it).second.getUsedWrites(), 1);

    occStats->subEntriesReadsHist.sample((*it).second.getUsedReads(), 1);

    occStats->subEntriesWritesHist.sample((*it).second.getUsedWrites(), 1);

    occStats->subEntriesWritesHistComb.sample((*it).second.getNWrittenWords(), 1);

    occStats->subEntriesHistComb.sample((*it).second.getUsedReads()+
					(*it).second.getNWrittenWords(), 1);
    
    if((*it).second.getUsedReads() == 0 &&
       (*it).second.getUsedWrites() > 0) {
      nOnlyWrites.inc();
      occStats->retireWrEntry((*it).second.getLineAddr());
    } else if( (*it).second.getUsedReads() > 0 &&
      (*it).second.getUsedWrites() == 0 ) {
      occStats->retireRdEntry((*it).second.getLineAddr());
    } else {
      I( (*it).second.getUsedWrites() > 0 );  
      I( (*it).second.getUsedReads() > 0 );
      occStats->retireRdWrEntry((*it).second.getLineAddr());  
    }
#endif
    
    nFreeEntries++;
    updateOccHistogram();
    bf.remove((*it).second.getLineAddr());
    ms.erase(it);
  }

  checkOverflow();

  return rmEntry;
}
Пример #8
0
void SingleMSHR<Addr_t, Cache_t>::checkOverflow()
{
  if(overflow.empty()) //nothing to do
    return;

  if(checkingOverflow) // i am already checking the overflow
    return;

  I(!overflow.empty());
  I(!checkingOverflow);

  checkingOverflow = true;

  int nConsumed = 0;

  do {
    OverflowField f = overflow.front();
    MSHRit it = ms.find(calcLineAddr(f.paddr));

    if(it == ms.end()) {
      if(nFreeEntries > 0) {
        ms[calcLineAddr(f.paddr)].firstRequest(f.paddr, calcLineAddr(f.paddr),
                                               nReads, nWrites, f.mo);
	checkSubEntries(f.paddr, f.mo);
#ifdef MSHR_EXTRAOCCSTATS
        occStats->sampleEntry( calcLineAddr( f.paddr ) );
#endif
        bf.insert(calcLineAddr(f.paddr));
        nFreeEntries--;
        updateOccHistogram();
        nConsumed++;
        nOutsReqs++;
	if(f.mo == MemRead)
	  occStats->incRdReqs();

        f.ovflwcb->call();
        f.cb->destroy();
        overflow.pop_front();
        nIssuesNewEntry.inc();
        avgQueueSize.sample(0);

      } else {
        break;
      }
    } else { // just try to add the entry
      if((*it).second.addRequest(f.paddr, f.cb, f.mo)) {
        // succesfully accepted entry, but no need to call the callback
        // since there was already an entry pending for the same line
        avgQueueSize.sample((*it).second.getPendingReqs() - 1);
        f.ovflwcb->destroy();
        overflow.pop_front();
        nOutsReqs++;
	if(f.mo == MemRead)
	  occStats->incRdReqs();


	checkSubEntries(f.paddr, f.mo);
        //MSG("[%llu] nFullRd=%d nFullWr=%d a:%lu",globalClock,
        //  nFullReadEntries,nFullWriteEntries,calcLineAddr(f.paddr));
      } else {
        break;
      }
    }
  } while(!overflow.empty());

  if(nConsumed)
    avgOverflowConsumptions.sample(nConsumed);

  checkingOverflow = false;
}