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; }
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); }
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; }
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; }
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++; } } }
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; } }
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; }
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; }