ruby: call setMRU from L1 controllers, not from sequencer
authorNilay Vaish <nilay@cs.wisc.edu>
Sat, 5 Sep 2015 14:35:39 +0000 (09:35 -0500)
committerNilay Vaish <nilay@cs.wisc.edu>
Sat, 5 Sep 2015 14:35:39 +0000 (09:35 -0500)
Currently the sequencer calls the function setMRU that updates the replacement
policy structures with the first level caches.  While functionally this is
correct, the problem is that this requires calling findTagInSet() which is an
expensive function.  This patch removes the calls to setMRU from the sequencer.
All controllers should now update the replacement policy on their own.

The set and the way index for a given cache entry can be found within the
AbstractCacheEntry structure. Use these indicies to update the replacement
policy structures.

src/mem/protocol/MESI_Three_Level-L0cache.sm
src/mem/protocol/MESI_Two_Level-L1cache.sm
src/mem/protocol/MI_example-cache.sm
src/mem/protocol/MOESI_CMP_directory-L1cache.sm
src/mem/protocol/MOESI_CMP_token-L1cache.sm
src/mem/protocol/MOESI_hammer-cache.sm
src/mem/protocol/RubySlicc_Types.sm
src/mem/ruby/structures/CacheMemory.cc
src/mem/ruby/structures/CacheMemory.hh
src/mem/ruby/system/Sequencer.cc

index 4a0766ce82ee33d0cf9c8940d51754dae07cb231..7e8626dc9dd0f9f4df7ff009658f058af315e01a 100644 (file)
@@ -459,21 +459,38 @@ machine(L0Cache, "MESI Directory L0 Cache")
     }
   }
 
-  action(h_load_hit, "h", desc="If not prefetch, notify sequencer the load completed.") {
+  action(h_load_hit, "hd", desc="If not prefetch, notify sequencer the load completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    Dcache.setMRU(cache_entry);
     sequencer.readCallback(address, cache_entry.DataBlk);
   }
 
-  action(hx_load_hit, "hx", desc="If not prefetch, notify sequencer the load completed.") {
+  action(h_ifetch_hit, "hi", desc="If not prefetch, notify sequencer the ifetch completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    Icache.setMRU(cache_entry);
+    sequencer.readCallback(address, cache_entry.DataBlk);
+  }
+
+  action(hx_load_hit, "hxd", desc="notify sequencer the load completed.") {
+    assert(is_valid(cache_entry));
+    DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    Dcache.setMRU(cache_entry);
+    sequencer.readCallback(address, cache_entry.DataBlk, true);
+  }
+
+  action(hx_ifetch_hit, "hxi", desc="notify sequencer the ifetch completed.") {
+    assert(is_valid(cache_entry));
+    DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    Icache.setMRU(cache_entry);
     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);
+    Dcache.setMRU(cache_entry);
     sequencer.writeCallback(address, cache_entry.DataBlk);
     cache_entry.Dirty := true;
   }
@@ -481,6 +498,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
   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);
+    Dcache.setMRU(cache_entry);
     sequencer.writeCallback(address, cache_entry.DataBlk, true);
     cache_entry.Dirty := true;
   }
@@ -625,7 +643,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
   }
 
   transition({S,E,M}, Ifetch) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileInstHit;
     k_popMandatoryQueue;
   }
@@ -712,7 +730,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
 
   transition(Inst_IS, Data, S) {
     u_writeInstToCache;
-    hx_load_hit;
+    hx_ifetch_hit;
     s_deallocateTBE;
     o_popIncomingResponseQueue;
     kd_wakeUpDependents;
@@ -720,7 +738,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
 
   transition(Inst_IS, Data_Exclusive, E) {
     u_writeInstToCache;
-    hx_load_hit;
+    hx_ifetch_hit;
     s_deallocateTBE;
     o_popIncomingResponseQueue;
     kd_wakeUpDependents;
index 8033e5983d2f3d66400a35782609ce636d5b0670..b9be4663fcad87a20664324a0328b2daa7b0cd37 100644 (file)
@@ -810,36 +810,47 @@ machine(L1Cache, "MESI Directory L1 Cache CMP")
     sequencer.invalidateSC(address);
   }
 
-  action(h_load_hit, "h",
-         desc="If not prefetch, notify sequencer the load completed.")
+  action(h_load_hit, "hd",
+         desc="Notify sequencer the load completed.")
   {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Dcache.setMRU(cache_entry);
     sequencer.readCallback(address, cache_entry.DataBlk);
   }
 
-  action(hx_load_hit, "hx",
-         desc="If not prefetch, notify sequencer the load completed.")
+  action(h_ifetch_hit, "hi", desc="Notify sequencer the instruction fetch completed.")
   {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Icache.setMRU(cache_entry);
+    sequencer.readCallback(address, cache_entry.DataBlk);
+  }
+
+  action(hx_load_hit, "hx", desc="Notify sequencer the load completed.")
+  {
+    assert(is_valid(cache_entry));
+    DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Icache.setMRU(address);
+    L1Dcache.setMRU(address);
     sequencer.readCallback(address, cache_entry.DataBlk, true);
   }
 
-  action(hh_store_hit, "\h",
-         desc="If not prefetch, notify sequencer that store completed.")
+  action(hh_store_hit, "\h", desc="Notify sequencer that store completed.")
   {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Dcache.setMRU(cache_entry);
     sequencer.writeCallback(address, cache_entry.DataBlk);
     cache_entry.Dirty := true;
   }
 
-  action(hhx_store_hit, "\hx",
-         desc="If not prefetch, notify sequencer that store completed.")
+  action(hhx_store_hit, "\hx", desc="Notify sequencer that store completed.")
   {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Icache.setMRU(address);
+    L1Dcache.setMRU(address);
     sequencer.writeCallback(address, cache_entry.DataBlk, true);
     cache_entry.Dirty := true;
   }
@@ -1081,7 +1092,7 @@ machine(L1Cache, "MESI Directory L1 Cache CMP")
   }
 
   transition({S,E,M}, Ifetch) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileInstHit;
     k_popMandatoryQueue;
   }
index f3b1600f913c0013fa9007ba3604759d09bacb9b..3341066150602248f7a2b92e5f84f12ab3e4016d 100644 (file)
@@ -352,6 +352,7 @@ machine(L1Cache, "MI Example L1 Cache")
   action(r_load_hit, "r", desc="Notify sequencer the load completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
+    cacheMemory.setMRU(cache_entry);
     sequencer.readCallback(address, cache_entry.DataBlk, false);
   }
 
@@ -359,6 +360,7 @@ machine(L1Cache, "MI Example L1 Cache")
     peek(responseNetwork_in, ResponseMsg) {
       assert(is_valid(cache_entry));
       DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
+      cacheMemory.setMRU(cache_entry);
       sequencer.readCallback(address, cache_entry.DataBlk, true,
                              machineIDToMachineType(in_msg.Sender));
     }
@@ -367,6 +369,7 @@ machine(L1Cache, "MI Example L1 Cache")
   action(s_store_hit, "s", desc="Notify sequencer that store completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
+    cacheMemory.setMRU(cache_entry);
     sequencer.writeCallback(address, cache_entry.DataBlk, false);
   }
 
@@ -374,6 +377,7 @@ machine(L1Cache, "MI Example L1 Cache")
     peek(responseNetwork_in, ResponseMsg) {
       assert(is_valid(cache_entry));
       DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
+      cacheMemory.setMRU(cache_entry);
       sequencer.writeCallback(address, cache_entry.DataBlk, true,
                               machineIDToMachineType(in_msg.Sender));
     }
index 6c5d3a20f07bf764658eea5f1aed3e0ee83572ce..2ef80efd2d4d794c040db4799c33542701264e28 100644 (file)
@@ -635,21 +635,32 @@ machine(L1Cache, "Directory protocol")
     }
   }
 
-  action(h_load_hit, "h", desc="Notify sequencer the load completed.") {
+  action(h_load_hit, "hd", desc="Notify sequencer the load completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Dcache.setMRU(cache_entry);
+    sequencer.readCallback(address, cache_entry.DataBlk);
+  }
+
+  action(h_ifetch_hit, "hi", desc="Notify the sequencer about ifetch completion.") {
+    assert(is_valid(cache_entry));
+    DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Icache.setMRU(cache_entry);
     sequencer.readCallback(address, cache_entry.DataBlk);
   }
 
   action(hx_load_hit, "hx", desc="Notify sequencer the load completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Icache.setMRU(address);
+    L1Dcache.setMRU(address);
     sequencer.readCallback(address, cache_entry.DataBlk, true);
   }
 
   action(hh_store_hit, "\h", desc="Notify sequencer that store completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Dcache.setMRU(cache_entry);
     sequencer.writeCallback(address, cache_entry.DataBlk);
     cache_entry.Dirty := true;
   }
@@ -657,6 +668,8 @@ machine(L1Cache, "Directory protocol")
   action(xx_store_hit, "\xx", desc="Notify sequencer that store completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Icache.setMRU(address);
+    L1Dcache.setMRU(address);
     sequencer.writeCallback(address, cache_entry.DataBlk, true);
     cache_entry.Dirty := true;
   }
@@ -964,7 +977,7 @@ machine(L1Cache, "Directory protocol")
   }
 
   transition({S, SM, O, OM, MM, MM_W, M, M_W}, Ifetch) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileInstHit;
     k_popMandatoryQueue;
   }
index c5a7cd940bba13df205b696a75a96bce48ac4792..230adfc4b59141f86e3d15e40c85c1f084adf94b 100644 (file)
@@ -1282,12 +1282,22 @@ machine(L1Cache, "Token protocol")
     }
   }
 
+  action(h_load_hit, "hd", desc="Notify sequencer the load completed.") {
+    assert(is_valid(cache_entry));
+    DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
+            address, cache_entry.DataBlk);
 
-  action(h_load_hit, "h", desc="Notify sequencer the load completed.") {
+    L1Dcache.setMRU(cache_entry);
+    sequencer.readCallback(address, cache_entry.DataBlk, false,
+                           MachineType:L1Cache);
+  }
+
+  action(h_ifetch_hit, "hi", desc="Notify sequencer the load completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
             address, cache_entry.DataBlk);
 
+    L1Icache.setMRU(cache_entry);
     sequencer.readCallback(address, cache_entry.DataBlk, false,
                            MachineType:L1Cache);
   }
@@ -1297,6 +1307,8 @@ machine(L1Cache, "Token protocol")
     DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
             address, cache_entry.DataBlk);
     peek(responseNetwork_in, ResponseMsg) {
+      L1Icache.setMRU(address);
+      L1Dcache.setMRU(address);
       sequencer.readCallback(address, cache_entry.DataBlk,
                              isExternalHit(address, in_msg.Sender),
                              machineIDToMachineType(in_msg.Sender));
@@ -1308,6 +1320,7 @@ machine(L1Cache, "Token protocol")
     DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
             address, cache_entry.DataBlk);
 
+    L1Dcache.setMRU(cache_entry);
     sequencer.writeCallback(address, cache_entry.DataBlk, false,
                             MachineType:L1Cache);
     cache_entry.Dirty := true;
@@ -1319,6 +1332,8 @@ machine(L1Cache, "Token protocol")
     DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
             address, cache_entry.DataBlk);
     peek(responseNetwork_in, ResponseMsg) {
+      L1Icache.setMRU(address);
+      L1Dcache.setMRU(address);
       sequencer.writeCallback(address, cache_entry.DataBlk,
                               isExternalHit(address, in_msg.Sender),
                               machineIDToMachineType(in_msg.Sender));
@@ -1700,7 +1715,7 @@ machine(L1Cache, "Token protocol")
   }
 
   transition({S, SM, S_L, SM_L}, Ifetch) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileInstHit;
     k_popMandatoryQueue;
   }
@@ -1782,7 +1797,7 @@ machine(L1Cache, "Token protocol")
 
   // Transitions from Owned
   transition({O, OM}, Ifetch) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileInstHit;
     k_popMandatoryQueue;
   }
@@ -1872,7 +1887,7 @@ machine(L1Cache, "Token protocol")
 
   // Transitions from Modified
   transition({MM, MM_W}, Ifetch) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileInstHit;
     k_popMandatoryQueue;
   }
@@ -1947,7 +1962,7 @@ machine(L1Cache, "Token protocol")
 
   // Transitions from Dirty Exclusive
   transition({M, M_W}, Ifetch) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileInstHit;
     k_popMandatoryQueue;
   }
index 303bf178417c48580d723ac131a0bcf77905fa68..88b7308ed964ba5a616da409883c38021ec04612 100644 (file)
@@ -853,9 +853,18 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
     }
   }
 
-  action(h_load_hit, "h", desc="Notify sequencer the load completed.") {
+  action(h_load_hit, "hd", desc="Notify sequencer the load completed.") {
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Dcache.setMRU(cache_entry);
+    sequencer.readCallback(address, cache_entry.DataBlk, false,
+                           testAndClearLocalHit(cache_entry));
+  }
+
+  action(h_ifetch_hit, "hi", desc="Notify sequencer the ifetch completed.") {
+    assert(is_valid(cache_entry));
+    DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+    L1Icache.setMRU(cache_entry);
     sequencer.readCallback(address, cache_entry.DataBlk, false,
                            testAndClearLocalHit(cache_entry));
   }
@@ -865,7 +874,8 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
     assert(is_valid(tbe));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
     peek(responseToCache_in, ResponseMsg) {
-
+      L1Icache.setMRU(address);
+      L1Dcache.setMRU(address);
       sequencer.readCallback(address, cache_entry.DataBlk, true,
                  machineIDToMachineType(in_msg.Sender), tbe.InitialRequestTime,
                  tbe.ForwardRequestTime, tbe.FirstResponseTime);
@@ -876,6 +886,7 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
     assert(is_valid(cache_entry));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
     peek(mandatoryQueue_in, RubyRequest) {
+      L1Dcache.setMRU(cache_entry);
       sequencer.writeCallback(address, cache_entry.DataBlk, false,
                               testAndClearLocalHit(cache_entry));
 
@@ -897,7 +908,8 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
     assert(is_valid(tbe));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
     peek(responseToCache_in, ResponseMsg) {
-
+      L1Icache.setMRU(address);
+      L1Dcache.setMRU(address);
       sequencer.writeCallback(address, cache_entry.DataBlk, true,
               machineIDToMachineType(in_msg.Sender), tbe.InitialRequestTime,
               tbe.ForwardRequestTime, tbe.FirstResponseTime);
@@ -910,7 +922,8 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
     assert(is_valid(cache_entry));
     assert(is_valid(tbe));
     DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
-
+    L1Icache.setMRU(address);
+    L1Dcache.setMRU(address);
     sequencer.writeCallback(address, cache_entry.DataBlk, true,
             machineIDToMachineType(tbe.LastResponder), tbe.InitialRequestTime,
             tbe.ForwardRequestTime, tbe.FirstResponseTime);
@@ -1504,7 +1517,7 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
   }
 
   transition({S, SM, ISM}, Ifetch) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileL1InstHit;
     k_popMandatoryQueue;
   }
@@ -1518,7 +1531,7 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
   }
 
   transition(SR, Ifetch, S) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileL1InstMiss;
     uu_profileL2Hit;
     k_popMandatoryQueue;
@@ -1566,7 +1579,7 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
   }
 
   transition({O, OM, SS, MM_W, M_W}, {Ifetch}) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileL1InstHit;
     k_popMandatoryQueue;
   }
@@ -1580,7 +1593,7 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
   }
 
   transition(OR, Ifetch, O) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileL1InstMiss;
     uu_profileL2Hit;
     k_popMandatoryQueue;
@@ -1631,7 +1644,7 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
 
   // Transitions from Modified
   transition({MM, M}, {Ifetch}) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileL1InstHit;
     k_popMandatoryQueue;
   }
@@ -1657,7 +1670,7 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
   }
 
   transition(MMR, Ifetch, MM) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileL1InstMiss;
     uu_profileL2Hit;
     k_popMandatoryQueue;
@@ -1738,7 +1751,7 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
   }
 
   transition(MR, Ifetch, M) {
-    h_load_hit;
+    h_ifetch_hit;
     uu_profileL1InstMiss;
     uu_profileL2Hit;
     k_popMandatoryQueue;
index d032adfd8968e05ca9a91113b20e82410d32f0eb..f464b3c7d747a21f8816ed17f2ea0becd265104f 100644 (file)
@@ -156,6 +156,7 @@ structure (CacheMemory, external = "yes") {
   Cycles getTagLatency();
   Cycles getDataLatency();
   void setMRU(Addr);
+  void setMRU(AbstractCacheEntry);
   void recordRequestType(CacheRequestType, Addr);
   bool checkResourceAvailable(CacheResourceType, Addr);
 
index ab26477597da4878e2925ba9b3ec9e702491d7b3..931f58a8ef686b111f1d829c5b43920c169026b4 100644 (file)
@@ -343,6 +343,14 @@ CacheMemory::setMRU(Addr address)
         m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
 }
 
+void
+CacheMemory::setMRU(const AbstractCacheEntry *e)
+{
+    uint32_t cacheSet = e->getSetIndex();
+    uint32_t loc = e->getWayIndex();
+    m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
+}
+
 void
 CacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const
 {
index 1af4469508ca12a2cc2a375e08b6075e677a33ca..7ce674e61a6473e2f780ac97a7a18b3bad0abd6d 100644 (file)
@@ -106,6 +106,8 @@ class CacheMemory : public SimObject
 
     // Set this address to most recently used
     void setMRU(Addr address);
+    // Set this entry to most recently used
+    void setMRU(const AbstractCacheEntry *e);
 
     // Functions for locking and unlocking cache lines corresponding to the
     // provided address.  These are required for supporting atomic memory
index b21c70743fbc762ccd5d671d8bb3fdc7bfc72d66..740db7d8ded9ad84d1ac7638ab7d28bde9729d65 100644 (file)
@@ -496,19 +496,15 @@ Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data,
                        const Cycles forwardRequestTime,
                        const Cycles firstResponseTime)
 {
+    warn_once("Replacement policy updates recently became the responsibility "
+              "of SLICC state machines. Make sure to setMRU() near callbacks "
+              "in .sm files!");
+
     PacketPtr pkt = srequest->pkt;
     Addr request_address(pkt->getAddr());
-    Addr request_line_address = makeLineAddress(pkt->getAddr());
     RubyRequestType type = srequest->m_type;
     Cycles issued_time = srequest->issue_time;
 
-    // Set this cache entry to the most recently used
-    if (type == RubyRequestType_IFETCH) {
-        m_instCache_ptr->setMRU(request_line_address);
-    } else {
-        m_dataCache_ptr->setMRU(request_line_address);
-    }
-
     assert(curCycle() >= issued_time);
     Cycles total_latency = curCycle() - issued_time;