void MESI_SMPCache::writeLine(uint32_t wrPC, uint32_t addr){
  /*This method implements actions taken when instruction wrPC
   *writes to memory location addr*/

  /*Find the line to which this address maps*/ 
  MESI_SMPCacheState * st = (MESI_SMPCacheState *)cache->findLine(addr);    
   
  /*
   *If the tags didn't match, or the line was invalid, it is a 
   *write miss
   */ 
  if(!st || (st && !(st->isValid())) ){ 

    numWriteMisses++;
    
    if(st){

      /*We're writing to an invalid line*/
      numWriteOnInvalidMisses++;

    }
 
    /*
     * Let the other caches snoop this write access and update their
     * state accordingly.  This action is effectively putting the write
     * on the bus.
     */ 
    MESI_SMPCache::InvalidateReply inv_ack = writeRemoteAction(addr);
    numInvalidatesSent++;

    /*Fill the line with the new written block*/
    fillLine(addr,MESI_MODIFIED);

    return;

  }else if(st->getState() == MESI_SHARED || 
            st->getState() == MESI_EXCLUSIVE){
    /* If the block is shared and we're writing, still count it as a cache hit,
     * but we need to invalidate all of the sharers' copies and upgrade to Modified 
     * in order to write.
     */
    numWriteHits++;

    if (st->getState() == MESI_SHARED){
      /*Write-on-shared Coherence Misses*/
      numWriteOnSharedMisses++;
      /*Let the other sharers snoop this write, and invalidate themselves*/
      MESI_SMPCache::InvalidateReply inv_ack = writeRemoteAction(addr);
      numInvalidatesSent++;
    }



    /*Change the state of the line to Modified to reflect the write*/
    st->changeStateTo(MESI_MODIFIED);
    return;

  }else{ //Write Hit

    /*Already have it writable: No coherence action required!*/
    numWriteHits++;

    return;

  }

}
Exemple #2
0
  /** Make a write request.
   * @param access the memory access being made
   * @param doStoreBufferAccess whether to use the det store buffer for this write */
  virtual void write( const DataAccess& access, bool doStoreBufferAccess ) {
    State* myLine = NULL;
    CacheResponse r = L1cache->search( access.addr(), myLine );

    if ( r != MISSED_TO_MEMORY ) {

      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;
        break;
      case L2_HIT: {
        timeInMemoryHierarchy += L2_HIT_LATENCY;
        if ( myLine->isDirty() ) {
          deterministicTimeInMemoryHierarchy += L2_HIT_LATENCY;
        } else {
          deterministicTimeInMemoryHierarchy += L1_HIT_LATENCY;
        }
        break;
      }
      case L3_HIT:
        timeInMemoryHierarchy += L3_HIT_LATENCY;
        // shared cache hits aren't det
        deterministicTimeInMemoryHierarchy += L1_HIT_LATENCY;
        break;
      default:
        assert(false);
      }

      // we either hit somewhere in our private cache(s) or we hit in the shared cache,
      // but we may not have write permissions
      L1cache->access( access.addr(), myLine );

      switch ( myLine->getState() ) {
      case MESI_SHARED: // upgrade miss
        numUpgradeMisses++;
        writeRemoteAction( access ); // invalidate other copies
        timeInMemoryHierarchy += REMOTE_HIT_LATENCY;

        myLine->changeStateTo( MESI_MODIFIED );
        if ( useDetStoreBuffers && doStoreBufferAccess ) {
          myLine->setDirty();
          StoreBufferIsEmpty = false;
        }
        return;
      case MESI_EXCLUSIVE: // write hit
      case MESI_MODIFIED:
        numWriteHits++;

        // TODO: fix this duplication from the MESI_SHARED case
        myLine->changeStateTo( MESI_MODIFIED );
        if ( useDetStoreBuffers && doStoreBufferAccess ) {
          myLine->setDirty();
          StoreBufferIsEmpty = false;
        }
        return;
      default:
        assert(false);
      }

    }

    // we didn't have the line at all - need to check for remote copies

    InvalidateReply inv_ack = writeRemoteAction( access );

    // remote hits and missing to memory aren't det
    deterministicTimeInMemoryHierarchy += L1_HIT_LATENCY;

    if ( inv_ack.nobodyHasThisLine ) {
      numWriteMisses++;
      timeInMemoryHierarchy += MEMORY_ACCESS_LATENCY;
    } else {
      numWriteRemoteHits++;
      timeInMemoryHierarchy += REMOTE_HIT_LATENCY;
    }

    L1cache->access( access.addr(), myLine );

    myLine->changeStateTo( MESI_MODIFIED );
    if ( useDetStoreBuffers && doStoreBufferAccess ) {
      myLine->setDirty();
      StoreBufferIsEmpty = false;
    }

  } // end write()