changeset 0a45bbe8536a in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=0a45bbe8536a
description:
        ruby: mesi three level: multiple corrections to the protocol

        1. Eliminate state NP in L0 and L1 Caches:  The two states 'NP' and 'I' 
both
        mean that the cache block is not present in the cache.  'I' also means 
that the
        cache entry has been allocated.  This causes problems when we do not 
correctly
        initialize the cache entry when it is re-used.  Hence, this patch 
eliminates
        the state NP altogether.  Everytime a new block comes into the cache, a 
cache
        entry is allocated.  Everytime a block leaves, the corresponding entry 
is
        deallocated.

        2. Separate transient state for instruction fetches: purely for 
accouting
        purposes.

        3. Drop state IS_I in L1 Cache and the message type STALE_DATA: when
        invalidation is received for a block in IS, the block used to be moved 
to IS_I.
        This meant that the data that would arrive in future would be used but 
not
        stored since the controller lost the permissions after gaining them.  
This
        state is being dropped and now invalidation messages would not 
processed till
        the data has arrived.  This also means that STALE_DATA type is not 
longer
        required.

diffstat:

 src/mem/protocol/MESI_Three_Level-L0cache.sm |  70 ++++++++++++++-------
 src/mem/protocol/MESI_Three_Level-L1cache.sm |  90 ++++++---------------------
 src/mem/protocol/MESI_Three_Level-msg.sm     |   5 -
 3 files changed, 66 insertions(+), 99 deletions(-)

diffs (truncated from 471 to 300 lines):

diff -r 75f7ae6304f3 -r 0a45bbe8536a 
src/mem/protocol/MESI_Three_Level-L0cache.sm
--- a/src/mem/protocol/MESI_Three_Level-L0cache.sm      Mon Aug 03 22:44:28 
2015 -0500
+++ b/src/mem/protocol/MESI_Three_Level-L0cache.sm      Mon Aug 03 22:44:29 
2015 -0500
@@ -48,9 +48,6 @@
     // Base states
 
     // The cache entry has not been allocated.
-    NP, AccessPermission:Invalid, desc="Not present in either cache";
-
-    // The cache entry has been allocated, but is not in use.
     I, AccessPermission:Invalid;
 
     // The cache entry is in shared mode. The processor can read this entry
@@ -67,6 +64,10 @@
 
     // Transient States
 
+    // The cache controller has requested an instruction.  It will be stored
+    // in the shared state so that the processor can read it.
+    Inst_IS, AccessPermission:Busy;
+
     // The cache controller has requested that this entry be fetched in
     // shared state so that the processor can read it.
     IS, AccessPermission:Busy;
@@ -100,7 +101,6 @@
 
     Data,               desc="Data for processor";
     Data_Exclusive,     desc="Data for processor";
-    Data_Stale,         desc="Data for processor, but not for storage";
 
     Ack,        desc="Ack for processor";
     Ack_all,      desc="Last ack for processor";
@@ -172,7 +172,7 @@
     } else if (is_valid(cache_entry)) {
       return cache_entry.CacheState;
     }
-    return State:NP;
+    return State:I;
   }
 
   void setState(TBE tbe, Entry cache_entry, Address addr, State state) {
@@ -266,8 +266,6 @@
             trigger(Event:Data_Exclusive, in_msg.Addr, cache_entry, tbe);
         } else if(in_msg.Class == CoherenceClass:DATA) {
             trigger(Event:Data, in_msg.Addr, cache_entry, tbe);
-        } else if(in_msg.Class == CoherenceClass:STALE_DATA) {
-            trigger(Event:Data_Stale, in_msg.Addr, cache_entry, tbe);
         } else if (in_msg.Class == CoherenceClass:ACK) {
             trigger(Event:Ack, in_msg.Addr, cache_entry, tbe);
         } else if (in_msg.Class == CoherenceClass:WB_ACK) {
@@ -421,6 +419,7 @@
       out_msg.Dest := createMachineID(MachineType:L1Cache, version);
       out_msg.MessageSize := MessageSizeType:Writeback_Data;
     }
+    cache_entry.Dirty := false;
   }
 
   action(fi_sendInvAck, "fi", desc="send data to the L2 cache") {
@@ -447,13 +446,13 @@
       assert(is_valid(cache_entry));
       out_msg.Addr := address;
       out_msg.Class := CoherenceClass:PUTX;
-      out_msg.DataBlk := cache_entry.DataBlk;
       out_msg.Dirty := cache_entry.Dirty;
       out_msg.Sender:= machineID;
       out_msg.Dest := createMachineID(MachineType:L1Cache, version);
 
       if (cache_entry.Dirty) {
         out_msg.MessageSize := MessageSizeType:Writeback_Data;
+        out_msg.DataBlk := cache_entry.DataBlk;
       } else {
         out_msg.MessageSize := MessageSizeType:Writeback_Control;
       }
@@ -466,6 +465,12 @@
     sequencer.readCallback(address, cache_entry.DataBlk);
   }
 
+  action(hx_load_hit, "hx", desc="If not prefetch, notify sequencer the load 
completed.") {
+    assert(is_valid(cache_entry));
+    DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    sequencer.readCallback(address, cache_entry.DataBlk, true);
+  }
+
   action(hh_store_hit, "\h", desc="If not prefetch, notify sequencer that 
store completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
@@ -473,6 +478,13 @@
     cache_entry.Dirty := true;
   }
 
+  action(hhx_store_hit, "\hx", desc="If not prefetch, notify sequencer that 
store completed.") {
+    assert(is_valid(cache_entry));
+    DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    sequencer.writeCallback(address, cache_entry.DataBlk, true);
+    cache_entry.Dirty := true;
+  }
+
   action(i_allocateTBE, "i", desc="Allocate TBE (number of invalidates=0)") {
     check_allocate(TBEs);
     assert(is_valid(cache_entry));
@@ -505,7 +517,13 @@
     peek(messgeBuffer_in, CoherenceMsg) {
       assert(is_valid(cache_entry));
       cache_entry.DataBlk := in_msg.DataBlk;
-      cache_entry.Dirty := in_msg.Dirty;
+    }
+  }
+
+  action(u_writeInstToCache, "ui", desc="Write data to cache") {
+    peek(messgeBuffer_in, CoherenceMsg) {
+      assert(is_valid(cache_entry));
+      cache_entry.DataBlk := in_msg.DataBlk;
     }
   }
 
@@ -560,16 +578,12 @@
   //*****************************************************
 
   // Transitions for Load/Store/Replacement/WriteBack from transient states
-  transition({IS, IM, SM}, {Load, Ifetch, Store, L0_Replacement}) {
+  transition({Inst_IS, IS, IM, SM}, {Load, Ifetch, Store, L0_Replacement}) {
     z_stallAndWaitMandatoryQueue;
   }
 
   // Transitions from Idle
-  transition({NP,I}, L0_Replacement) {
-    ff_deallocateCacheBlock;
-  }
-
-  transition({NP,I}, Load, IS) {
+  transition(I, Load, IS) {
     oo_allocateDCacheBlock;
     i_allocateTBE;
     a_issueGETS;
@@ -577,7 +591,7 @@
     k_popMandatoryQueue;
   }
 
-  transition({NP,I}, Ifetch, IS) {
+  transition(I, Ifetch, Inst_IS) {
     pp_allocateICacheBlock;
     i_allocateTBE;
     a_issueGETS;
@@ -585,7 +599,7 @@
     k_popMandatoryQueue;
   }
 
-  transition({NP,I}, Store, IM) {
+  transition(I, Store, IM) {
     oo_allocateDCacheBlock;
     i_allocateTBE;
     b_issueGETX;
@@ -593,7 +607,7 @@
     k_popMandatoryQueue;
   }
 
-  transition({NP, I, IS, IM}, Inv) {
+  transition({I, IS, IM, Inst_IS}, Inv) {
     fi_sendInvAck;
     l_popRequestQueue;
   }
@@ -682,7 +696,7 @@
 
   transition(IS, Data, S) {
     u_writeDataToCache;
-    h_load_hit;
+    hx_load_hit;
     s_deallocateTBE;
     o_popIncomingResponseQueue;
     kd_wakeUpDependents;
@@ -690,15 +704,23 @@
 
   transition(IS, Data_Exclusive, E) {
     u_writeDataToCache;
-    h_load_hit;
+    hx_load_hit;
     s_deallocateTBE;
     o_popIncomingResponseQueue;
     kd_wakeUpDependents;
   }
 
-  transition(IS, Data_Stale, I) {
-    u_writeDataToCache;
-    h_load_hit;
+  transition(Inst_IS, Data, S) {
+    u_writeInstToCache;
+    hx_load_hit;
+    s_deallocateTBE;
+    o_popIncomingResponseQueue;
+    kd_wakeUpDependents;
+  }
+
+  transition(Inst_IS, Data_Exclusive, E) {
+    u_writeInstToCache;
+    hx_load_hit;
     s_deallocateTBE;
     o_popIncomingResponseQueue;
     kd_wakeUpDependents;
@@ -706,7 +728,7 @@
 
   transition({IM,SM}, Data_Exclusive, M) {
     u_writeDataToCache;
-    hh_store_hit;
+    hhx_store_hit;
     s_deallocateTBE;
     o_popIncomingResponseQueue;
     kd_wakeUpDependents;
diff -r 75f7ae6304f3 -r 0a45bbe8536a 
src/mem/protocol/MESI_Three_Level-L1cache.sm
--- a/src/mem/protocol/MESI_Three_Level-L1cache.sm      Mon Aug 03 22:44:28 
2015 -0500
+++ b/src/mem/protocol/MESI_Three_Level-L1cache.sm      Mon Aug 03 22:44:29 
2015 -0500
@@ -59,7 +59,6 @@
   // STATES
   state_declaration(State, desc="Cache states", default="L1Cache_State_I") {
     // Base states
-    NP, AccessPermission:Invalid, desc="Not present in either cache";
     I, AccessPermission:Invalid, desc="a L1 cache entry Idle";
     S, AccessPermission:Read_Only, desc="a L1 cache entry Shared";
     SS, AccessPermission:Read_Only, desc="a L1 cache entry Shared";
@@ -72,8 +71,6 @@
     IS, AccessPermission:Busy, desc="L1 idle, issued GETS, have not seen 
response yet";
     IM, AccessPermission:Busy, desc="L1 idle, issued GETX, have not seen 
response yet";
     SM, AccessPermission:Read_Only, desc="L1 idle, issued GETX, have not seen 
response yet";
-    IS_I, AccessPermission:Busy, desc="L1 idle, issued GETS, saw Inv before 
data because directory doesn't block on GETS hit";
-
     M_I, AccessPermission:Busy, desc="L1 replacing, waiting for ACK";
     SINK_WB_ACK, AccessPermission:Busy, desc="This is to sink WB_Acks from L2";
 
@@ -174,7 +171,7 @@
     } else if (is_valid(cache_entry)) {
       return cache_entry.CacheState;
     }
-    return State:NP;
+    return State:I;
   }
 
   void setState(TBE tbe, Entry cache_entry, Address addr, State state) {
@@ -279,8 +276,7 @@
         if(in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
           trigger(Event:Data_Exclusive, in_msg.Addr, cache_entry, tbe);
         } else if(in_msg.Type == CoherenceResponseType:DATA) {
-          if ((getState(tbe, cache_entry, in_msg.Addr) == State:IS ||
-               getState(tbe, cache_entry, in_msg.Addr) == State:IS_I) &&
+          if (getState(tbe, cache_entry, in_msg.Addr) == State:IS &&
               machineIDToMachineType(in_msg.Sender) == MachineType:L1Cache) {
 
               trigger(Event:DataS_fromL1, in_msg.Addr, cache_entry, tbe);
@@ -561,13 +557,13 @@
       assert(is_valid(cache_entry));
       out_msg.Addr := address;
       out_msg.Type := CoherenceRequestType:PUTX;
-      out_msg.DataBlk := cache_entry.DataBlk;
       out_msg.Dirty := cache_entry.Dirty;
       out_msg.Requestor:= machineID;
       out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
                           l2_select_low_bit, l2_select_num_bits, clusterID));
       if (cache_entry.Dirty) {
         out_msg.MessageSize := MessageSizeType:Writeback_Data;
+        out_msg.DataBlk := cache_entry.DataBlk;
       } else {
         out_msg.MessageSize := MessageSizeType:Writeback_Control;
       }
@@ -608,21 +604,6 @@
           out_msg.Sender := machineID;
           out_msg.Dest := createMachineID(MachineType:L0Cache, version);
           out_msg.DataBlk := cache_entry.DataBlk;
-          out_msg.Dirty := cache_entry.Dirty;
-          out_msg.MessageSize := MessageSizeType:Response_Data;
-      }
-  }
-
-  action(h_stale_data_to_l0, "hs", desc="If not prefetch, send data to the L0 
cache.") {
-      enqueue(bufferToL0_out, CoherenceMsg, l1_response_latency) {
-          assert(is_valid(cache_entry));
-
-          out_msg.Addr := address;
-          out_msg.Class := CoherenceClass:STALE_DATA;
-          out_msg.Sender := machineID;
-          out_msg.Dest := createMachineID(MachineType:L0Cache, version);
-          out_msg.DataBlk := cache_entry.DataBlk;
-          out_msg.Dirty := cache_entry.Dirty;
           out_msg.MessageSize := MessageSizeType:Response_Data;
       }
   }
@@ -639,7 +620,7 @@
           out_msg.Dirty := cache_entry.Dirty;
           out_msg.MessageSize := MessageSizeType:Response_Data;
 
-          cache_entry.Dirty := true;
+          //cache_entry.Dirty := true;
       }
   }
 
@@ -674,8 +655,10 @@
   action(u_writeDataFromL0Request, "ureql0", desc="Write data to cache") {
     peek(messageBufferFromL0_in, CoherenceMsg) {
       assert(is_valid(cache_entry));
-      cache_entry.DataBlk := in_msg.DataBlk;
-      cache_entry.Dirty := in_msg.Dirty;
+      if (in_msg.Dirty) {
+          cache_entry.DataBlk := in_msg.DataBlk;
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to