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; 

  }

}
Beispiel #2
0
  /** 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()