void MESI_SMPCache::readLine(uint32_t rdPC, uint32_t addr){ /* *This method implements actions taken on a read access to address addr *at instruction rdPC */ /*Get the state of the line to which this address maps*/ MESI_SMPCacheState *st = (MESI_SMPCacheState *)cache->findLine(addr); /*Read Miss - tags didn't match, or line is invalid*/ if(!st || (st && !(st->isValid())) ){ /*Update event counter for read misses*/ numReadMisses++; if(st){ /*Tag matched, but state was invalid*/ numReadOnInvalidMisses++; } /*Make the other caches snoop this access *and get a remote read service object describing what happened. *This is effectively putting the access on the bus. */ MESI_SMPCache::RemoteReadService rrs = readRemoteAction(addr); numReadRequestsSent++; if(rrs.providedData){ /*If it was shared or modified elsewhere, *the line was provided by another cache. *Update these counters to reflect that */ numReadMissesServicedByOthers++; if(rrs.isShared){ numReadMissesServicedByShared++; }else if (!rrs.isExclusive){ numReadMissesServicedByModified++; } /*Fill the line*/ fillLine(addr,MESI_SHARED); } else { /* we directly got the data from memory since another cache didn't give it to us. this is exclusively ours */ //numReadMissesServicedByOthers++; fillLine(addr,MESI_EXCLUSIVE); } }else{ /*Read Hit - any state but Invalid*/ numReadHits++; return; } }
/** Perform a data read specified by the given `access'. */ virtual void read( const DataAccess& access ) { State* line = NULL; CacheResponse r = L1cache->search( access.addr(), line ); if ( r != MISSED_TO_MEMORY ) { // we hit somewhere in our private cache(s), or a shared cache numReadHits++; switch ( r ) { case L1_HIT: timeInMemoryHierarchy += L1_HIT_LATENCY; // default det cache latency is an L1 hit, so it doesn't matter whether we hit to a dirty line or not deterministicTimeInMemoryHierarchy += L1_HIT_LATENCY; return; case L2_HIT: { timeInMemoryHierarchy += L2_HIT_LATENCY; if ( line->isDirty() ) { deterministicTimeInMemoryHierarchy += L2_HIT_LATENCY; } else { deterministicTimeInMemoryHierarchy += L1_HIT_LATENCY; } return; } case L3_HIT: timeInMemoryHierarchy += L3_HIT_LATENCY; // shared cache hits aren't det deterministicTimeInMemoryHierarchy += L1_HIT_LATENCY; return; default: assert(false); } } // we missed, so check remote caches for data RemoteReadService rrs = readRemoteAction( access ); // remote hits and missing to memory aren't det deterministicTimeInMemoryHierarchy += L1_HIT_LATENCY; MESIState newMesiState = MESI_INVALID; if ( rrs.providedData == false ) { // No Valid Read-Reply: Need to get this data from Memory numReadMisses++; timeInMemoryHierarchy += MEMORY_ACCESS_LATENCY-1; /* NB: we always fetch from memory into Exclusive. */ newMesiState = MESI_EXCLUSIVE; } else if ( rrs.isShared ) { newMesiState = MESI_SHARED; numReadRemoteHits++; timeInMemoryHierarchy += REMOTE_HIT_LATENCY; } else { //Valid Read-Reply From Modified/Exclusive newMesiState = MESI_SHARED; numReadRemoteHits++; timeInMemoryHierarchy += REMOTE_HIT_LATENCY; } assert( newMesiState != MESI_INVALID ); // pull in the actual line L1cache->access( access.addr(), line ); line->changeStateTo( newMesiState ); } // end read()