On Sun, 23 Jan 2011, Beckmann, Brad wrote:

Thanks Arka for that response.  You summed it up well.

There are just a couple additional things I want to point out:


1.       One thing that makes this mechanism work is that one must rank each 
input port.   In other words, the programmer must understand and communicate 
the dependencies between message classes/protocol virtual channels.  That way 
the correct messages are woken up when the appropriate event occurs.

2.       In Nilay's example, you want to make sure that you don't delay the 
issuing of request A until the replacement of block B completes.  Instead, 
request A should allocate a TBE and issue in parallel with replacing B. The 
mandatory queue is popped only when the cache message is consumed.  When the 
cache message is stalled, it is basically moved to a temporary data structure 
with the message buffer where it waits until a higher priority message of the 
same cache block wakes it up.

Brad


I was testing the patch you had posted. I updated it so that it works with the latest version of the repository. Can you update the review board?

Somehow, I do not see any change in the number of calls to lookup().

--
Nilay
# HG changeset patch
# Parent d10be3f3aa4e3440a58642ca4ddb6472efdfb2a7

diff --git a/src/mem/protocol/MOESI_CMP_token-L1cache.sm 
b/src/mem/protocol/MOESI_CMP_token-L1cache.sm
--- a/src/mem/protocol/MOESI_CMP_token-L1cache.sm
+++ b/src/mem/protocol/MOESI_CMP_token-L1cache.sm
@@ -433,7 +433,7 @@
   // ** IN_PORTS **
 
   // Use Timer
-  in_port(useTimerTable_in, Address, useTimerTable) {
+  in_port(useTimerTable_in, Address, useTimerTable, rank=5) {
     if (useTimerTable_in.isReady()) {
       TBE tbe := L1_TBEs[useTimerTable.readyAddress()];
 
@@ -459,7 +459,7 @@
   }
 
   // Reissue Timer
-  in_port(reissueTimerTable_in, Address, reissueTimerTable) {
+  in_port(reissueTimerTable_in, Address, reissueTimerTable, rank=4) {
     if (reissueTimerTable_in.isReady()) {
       trigger(Event:Request_Timeout, reissueTimerTable.readyAddress(),
               getCacheEntry(reissueTimerTable.readyAddress()),
@@ -467,10 +467,8 @@
     }
   }
 
-
-
   // Persistent Network
-  in_port(persistentNetwork_in, PersistentMsg, persistentToL1Cache) {
+  in_port(persistentNetwork_in, PersistentMsg, persistentToL1Cache, rank=3) {
     if (persistentNetwork_in.isReady()) {
       peek(persistentNetwork_in, PersistentMsg, block_on="Address") {
         assert(in_msg.Destination.isElement(machineID));
@@ -519,9 +517,80 @@
     }
   }
 
+  // Response Network
+  in_port(responseNetwork_in, ResponseMsg, responseToL1Cache, rank=2) {
+    if (responseNetwork_in.isReady()) {
+      peek(responseNetwork_in, ResponseMsg, block_on="Address") {
+        assert(in_msg.Destination.isElement(machineID));
+
+        Entry cache_entry := getCacheEntry(in_msg.Address);
+        TBE tbe := L1_TBEs[in_msg.Address];
+
+        // Mark TBE flag if response received off-chip.  Use this to update 
average latency estimate
+        if ( machineIDToMachineType(in_msg.Sender) == MachineType:L2Cache ) {
+
+          if (in_msg.Sender == mapAddressToRange(in_msg.Address,
+                                                 MachineType:L2Cache,
+                                                 l2_select_low_bit,
+                                                 l2_select_num_bits)) {
+
+            // came from an off-chip L2 cache
+            if (is_valid(tbe)) {
+               // L1_TBEs[in_msg.Address].ExternalResponse := true;
+               // profile_offchipL2_response(in_msg.Address);
+            }
+          }
+          else {
+               // profile_onchipL2_response(in_msg.Address );
+          }
+        } else if ( machineIDToMachineType(in_msg.Sender) == 
MachineType:Directory ) {
+          if (is_valid(tbe)) {
+            setExternalResponse(tbe);
+            // profile_memory_response( in_msg.Address);
+          }
+        } else if ( machineIDToMachineType(in_msg.Sender) == 
MachineType:L1Cache) {
+          //if (isLocalProcessor(machineID, in_msg.Sender) == false) {
+            //if (is_valid(tbe)) {
+               // tbe.ExternalResponse := true;
+               // profile_offchipL1_response(in_msg.Address );
+            //}
+          //}
+          //else {
+               // profile_onchipL1_response(in_msg.Address );
+          //}
+        } else {
+          error("unexpected SenderMachine");
+        }
+
+
+        if (getTokens(cache_entry) + in_msg.Tokens != max_tokens()) {
+          if (in_msg.Type == CoherenceResponseType:ACK) {
+            assert(in_msg.Tokens < (max_tokens() / 2));
+            trigger(Event:Ack, in_msg.Address, cache_entry, tbe);
+          } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER) {
+            trigger(Event:Data_Owner, in_msg.Address, cache_entry, tbe);
+          } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) {
+            assert(in_msg.Tokens < (max_tokens() / 2));
+            trigger(Event:Data_Shared, in_msg.Address, cache_entry, tbe);
+          } else {
+            error("Unexpected message");
+          }
+        } else {
+          if (in_msg.Type == CoherenceResponseType:ACK) {
+            assert(in_msg.Tokens < (max_tokens() / 2));
+            trigger(Event:Ack_All_Tokens, in_msg.Address, cache_entry, tbe);
+          } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER || 
in_msg.Type == CoherenceResponseType:DATA_SHARED) {
+            trigger(Event:Data_All_Tokens, in_msg.Address, cache_entry, tbe);
+          } else {
+            error("Unexpected message");
+          }
+        }
+      }
+    }
+  }
 
   // Request Network
-  in_port(requestNetwork_in, RequestMsg, requestToL1Cache) {
+  in_port(requestNetwork_in, RequestMsg, requestToL1Cache, rank=1) {
     if (requestNetwork_in.isReady()) {
       peek(requestNetwork_in, RequestMsg, block_on="Address") {
         assert(in_msg.Destination.isElement(machineID));
@@ -567,80 +636,8 @@
     }
   }
 
-  // Response Network
-  in_port(responseNetwork_in, ResponseMsg, responseToL1Cache) {
-    if (responseNetwork_in.isReady()) {
-      peek(responseNetwork_in, ResponseMsg, block_on="Address") {
-        assert(in_msg.Destination.isElement(machineID));
-
-        Entry cache_entry := getCacheEntry(in_msg.Address);
-        TBE tbe := L1_TBEs[in_msg.Address];
-
-        // Mark TBE flag if response received off-chip.  Use this to update 
average latency estimate
-        if ( machineIDToMachineType(in_msg.Sender) == MachineType:L2Cache ) {
-
-          if (in_msg.Sender == mapAddressToRange(in_msg.Address,
-                                                 MachineType:L2Cache,
-                                                 l2_select_low_bit,
-                                                 l2_select_num_bits)) {
-
-            // came from an off-chip L2 cache
-            if (is_valid(tbe)) {
-               // L1_TBEs[in_msg.Address].ExternalResponse := true;
-               // profile_offchipL2_response(in_msg.Address);
-            }
-          }
-          else {
-               // profile_onchipL2_response(in_msg.Address );
-          }
-        } else if ( machineIDToMachineType(in_msg.Sender) == 
MachineType:Directory ) {
-          if (is_valid(tbe)) {
-            setExternalResponse(tbe);
-            // profile_memory_response( in_msg.Address);
-          }
-        } else if ( machineIDToMachineType(in_msg.Sender) == 
MachineType:L1Cache) {
-          //if (isLocalProcessor(machineID, in_msg.Sender) == false) {
-            //if (is_valid(tbe)) {
-               // tbe.ExternalResponse := true;
-               // profile_offchipL1_response(in_msg.Address );
-            //}
-          //}
-          //else {
-               // profile_onchipL1_response(in_msg.Address );
-          //}
-        } else {
-          error("unexpected SenderMachine");
-        }
-
-
-        if (getTokens(cache_entry) + in_msg.Tokens != max_tokens()) {
-          if (in_msg.Type == CoherenceResponseType:ACK) {
-            assert(in_msg.Tokens < (max_tokens() / 2));
-            trigger(Event:Ack, in_msg.Address, cache_entry, tbe);
-          } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER) {
-            trigger(Event:Data_Owner, in_msg.Address, cache_entry, tbe);
-          } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) {
-            assert(in_msg.Tokens < (max_tokens() / 2));
-            trigger(Event:Data_Shared, in_msg.Address, cache_entry, tbe);
-          } else {
-            error("Unexpected message");
-          }
-        } else {
-          if (in_msg.Type == CoherenceResponseType:ACK) {
-            assert(in_msg.Tokens < (max_tokens() / 2));
-            trigger(Event:Ack_All_Tokens, in_msg.Address, cache_entry, tbe);
-          } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER || 
in_msg.Type == CoherenceResponseType:DATA_SHARED) {
-            trigger(Event:Data_All_Tokens, in_msg.Address, cache_entry, tbe);
-          } else {
-            error("Unexpected message");
-          }
-        }
-      }
-    }
-  }
-
   // Mandatory Queue
-  in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...") {
+  in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...", rank=0) {
     if (mandatoryQueue_in.isReady()) {
       peek(mandatoryQueue_in, CacheMsg, block_on="LineAddress") {
         // Check for data access to blocks in I-cache and ifetchs to blocks in 
D-cache
@@ -1339,6 +1336,11 @@
     tbe.IssueTime := get_time();
   }
 
+  action(ta_traceStalledAddress, "ta", desc="Trace Stalled Address") {
+    peek(mandatoryQueue_in, CacheMsg) {
+      APPEND_TRANSITION_COMMENT(in_msg.LineAddress);
+    }
+  }
 
   action(j_unsetReissueTimer, "j", desc="Unset reissue timer.") {
     if (reissueTimerTable.isSet(address)) {
@@ -1527,8 +1529,19 @@
     }
   }
 
-  action(zz_recycleMandatoryQueue, "\z", desc="Send the head of the mandatory 
queue to the back of the queue.") {
-    mandatoryQueue_in.recycle();
+  action(zz_stallAndWaitMandatoryQueue, "\z", desc="Send the head of the 
mandatory queue to the back of the queue.") {
+    peek(mandatoryQueue_in, CacheMsg) {
+      APPEND_TRANSITION_COMMENT(in_msg.LineAddress);
+    } 
+    stall_and_wait(mandatoryQueue_in, address);    
+  }
+
+  action(kd_wakeUpDependents, "kd", desc="wake-up dependents") {
+    wake_up_dependents(address);
+  }
+
+  action(ka_wakeUpAllDependents, "ka", desc="wake-up all dependents") {
+    wake_up_all_dependents();
   }
 
   //*****************************************************
@@ -1537,15 +1550,16 @@
 
   // Transitions for Load/Store/L2_Replacement from transient states
   transition({IM, SM, OM, IS, IM_L, IS_L, I_L, S_L, SM_L, M_W, MM_W}, 
L1_Replacement) {
-    zz_recycleMandatoryQueue;
+    ta_traceStalledAddress;
+    zz_stallAndWaitMandatoryQueue;
   }
 
   transition({IM, SM, OM, IS, IM_L, IS_L, SM_L}, {Store, Atomic}) {
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
   }
 
   transition({IM, IS, IM_L, IS_L}, {Load, Ifetch}) {
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
   }
 
 
@@ -1615,8 +1629,10 @@
   }
 
   transition(I, L1_Replacement) {
+    ta_traceStalledAddress;
     tr_tokenReplacement;
     gg_deallocateL1CacheBlock;
+    ka_wakeUpAllDependents;
   }
 
   transition(I, {Transient_GETX, Transient_Local_GETX}) {
@@ -1674,8 +1690,10 @@
   }
 
   transition(S, L1_Replacement, I) {
+    ta_traceStalledAddress;
     cc_sharedReplacement; // Only needed in some cases
     gg_deallocateL1CacheBlock;
+    ka_wakeUpAllDependents;
   }
 
   transition(S, {Transient_GETX, Transient_Local_GETX}, I) {
@@ -1750,8 +1768,10 @@
   }
 
   transition(O, L1_Replacement, I) {
+    ta_traceStalledAddress;
     c_ownedReplacement;
     gg_deallocateL1CacheBlock;
+    ka_wakeUpAllDependents;
   }
 
   transition(O, {Transient_GETX, Transient_Local_GETX}, I) {
@@ -1835,8 +1855,10 @@
   }
 
   transition(MM, L1_Replacement, I) {
+    ta_traceStalledAddress;
     c_ownedReplacement;
     gg_deallocateL1CacheBlock;
+    ka_wakeUpAllDependents;
   }
 
   transition(MM, {Transient_GETX, Transient_Local_GETX, Transient_GETS, 
Transient_Local_GETS}, I) {
@@ -1864,11 +1886,13 @@
   transition(MM_W, Use_TimeoutNoStarvers, MM) {
     s_deallocateTBE;
     jj_unsetUseTimer;
+    kd_wakeUpDependents;
   }
 
   transition(MM_W, Use_TimeoutNoStarvers_NoMig, M) {
     s_deallocateTBE;
     jj_unsetUseTimer;
+    kd_wakeUpDependents;
   }
 
   // Transitions from Dirty Exclusive
@@ -1898,8 +1922,10 @@
   }
 
   transition(M, L1_Replacement, I) {
+    ta_traceStalledAddress;
     c_ownedReplacement;
     gg_deallocateL1CacheBlock;
+    ka_wakeUpAllDependents;
   }
 
   transition(M, {Transient_GETX, Transient_Local_GETX}, I) {
@@ -1948,6 +1974,7 @@
   transition(M_W, {Use_TimeoutNoStarvers, Use_TimeoutNoStarvers_NoMig}, M) {
     s_deallocateTBE;
     jj_unsetUseTimer;
+    kd_wakeUpDependents;
   }
 
   transition(M_W, Use_TimeoutStarverX, I_L) {
@@ -2056,6 +2083,7 @@
     o_scheduleUseTimeout;
     j_unsetReissueTimer;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   transition(SM, Data_Shared) {
@@ -2077,6 +2105,7 @@
     o_scheduleUseTimeout;
     j_unsetReissueTimer;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   transition({IM, SM}, {Transient_GETX, Transient_Local_GETX}, IM) { // We 
don't have the data yet, but we might have collected some tokens.  We give them 
up here to avoid livelock
@@ -2106,6 +2135,7 @@
     o_scheduleUseTimeout;
     j_unsetReissueTimer;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   transition(OM, Data_Shared) {
@@ -2121,6 +2151,7 @@
     o_scheduleUseTimeout;
     j_unsetReissueTimer;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   transition(OM, Request_Timeout) {
@@ -2142,6 +2173,7 @@
     s_deallocateTBE;
     j_unsetReissueTimer;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   transition(IS, Data_Owner, O) {
@@ -2151,6 +2183,7 @@
     s_deallocateTBE;
     j_unsetReissueTimer;
     n_popResponseQueue;
+    kd_wakeUpDependents;    
   }
 
   transition(IS, Data_All_Tokens, M_W) {
@@ -2160,6 +2193,7 @@
     o_scheduleUseTimeout;
     j_unsetReissueTimer;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   transition(IS, Request_Timeout) {
@@ -2247,6 +2281,7 @@
     j_unsetReissueTimer;
     o_scheduleUseTimeout;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   transition(SM_L, Data_All_Tokens, S_L) {
@@ -2288,6 +2323,7 @@
     j_unsetReissueTimer;
     o_scheduleUseTimeout;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
 
@@ -2295,22 +2331,27 @@
 
   transition(I_L, Own_Lock_or_Unlock, I) {
     l_popPersistentQueue;
+    kd_wakeUpDependents;
   }
 
   transition(S_L, Own_Lock_or_Unlock, S) {
     l_popPersistentQueue;
+    kd_wakeUpDependents;
   }
 
   transition(IM_L, Own_Lock_or_Unlock, IM) {
     l_popPersistentQueue;
+    kd_wakeUpDependents;
   }
 
   transition(IS_L, Own_Lock_or_Unlock, IS) {
     l_popPersistentQueue;
+    kd_wakeUpDependents;
   }
 
   transition(SM_L, Own_Lock_or_Unlock, SM) {
     l_popPersistentQueue;
+    kd_wakeUpDependents;
   }
 }
 
diff --git a/src/mem/protocol/MOESI_hammer-cache.sm 
b/src/mem/protocol/MOESI_hammer-cache.sm
--- a/src/mem/protocol/MOESI_hammer-cache.sm
+++ b/src/mem/protocol/MOESI_hammer-cache.sm
@@ -277,7 +277,7 @@
   // ** IN_PORTS **
 
   // Trigger Queue
-  in_port(triggerQueue_in, TriggerMsg, triggerQueue) {
+  in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=3) {
     if (triggerQueue_in.isReady()) {
       peek(triggerQueue_in, TriggerMsg) {
 
@@ -297,10 +297,35 @@
     }
   }
 
-  // Nothing from the request network
+  // Nothing from the unblock network
+
+  // Response Network
+  in_port(responseToCache_in, ResponseMsg, responseToCache, rank=2) {
+    if (responseToCache_in.isReady()) {
+      peek(responseToCache_in, ResponseMsg, block_on="Address") {
+
+        Entry cache_entry := getCacheEntry(in_msg.Address);
+        TBE tbe := TBEs[in_msg.Address];
+
+        if (in_msg.Type == CoherenceResponseType:ACK) {
+          trigger(Event:Ack, in_msg.Address, cache_entry, tbe);
+        } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) {
+          trigger(Event:Shared_Ack, in_msg.Address, cache_entry, tbe);
+        } else if (in_msg.Type == CoherenceResponseType:DATA) {
+          trigger(Event:Data, in_msg.Address, cache_entry, tbe);
+        } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) {
+          trigger(Event:Shared_Data, in_msg.Address, cache_entry, tbe);
+        } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
+          trigger(Event:Exclusive_Data, in_msg.Address, cache_entry, tbe);
+        } else {
+          error("Unexpected message");
+        }
+      }
+    }
+  }
 
   // Forward Network
-  in_port(forwardToCache_in, RequestMsg, forwardToCache) {
+  in_port(forwardToCache_in, RequestMsg, forwardToCache, rank=1) {
     if (forwardToCache_in.isReady()) {
       peek(forwardToCache_in, RequestMsg, block_on="Address") {
 
@@ -338,35 +363,10 @@
     }
   }
 
-  // Response Network
-  in_port(responseToCache_in, ResponseMsg, responseToCache) {
-    if (responseToCache_in.isReady()) {
-      peek(responseToCache_in, ResponseMsg, block_on="Address") {
-
-        Entry cache_entry := getCacheEntry(in_msg.Address);
-        TBE tbe := TBEs[in_msg.Address];
-
-        if (in_msg.Type == CoherenceResponseType:ACK) {
-          trigger(Event:Ack, in_msg.Address, cache_entry, tbe);
-        } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) {
-          trigger(Event:Shared_Ack, in_msg.Address, cache_entry, tbe);
-        } else if (in_msg.Type == CoherenceResponseType:DATA) {
-          trigger(Event:Data, in_msg.Address, cache_entry, tbe);
-        } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) {
-          trigger(Event:Shared_Data, in_msg.Address, cache_entry, tbe);
-        } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
-          trigger(Event:Exclusive_Data, in_msg.Address, cache_entry, tbe);
-        } else {
-          error("Unexpected message");
-        }
-      }
-    }
-  }
-
-  // Nothing from the unblock network
+  // Nothing from the request network
 
   // Mandatory Queue
-  in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...") {
+  in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...", rank=0) {
     if (mandatoryQueue_in.isReady()) {
       peek(mandatoryQueue_in, CacheMsg, block_on="LineAddress") {
 
@@ -999,8 +999,16 @@
     }
   }
 
-  action(zz_recycleMandatoryQueue, "\z", desc="Send the head of the mandatory 
queue to the back of the queue.") {
-    mandatoryQueue_in.recycle();
+  action(zz_stallAndWaitMandatoryQueue, "\z", desc="Send the head of the 
mandatory queue to the back of the queue.") {
+    stall_and_wait(mandatoryQueue_in, address);    
+  }
+
+  action(kd_wakeUpDependents, "kd", desc="wake-up dependents") {
+    wake_up_dependents(address);
+  }
+
+  action(ka_wakeUpAllDependents, "ka", desc="wake-up all dependents") {
+    wake_up_all_dependents();
   }
 
   //*****************************************************
@@ -1009,19 +1017,19 @@
 
   // Transitions for Load/Store/L2_Replacement from transient states
   transition({IM, SM, ISM, OM, IS, SS, OI, MI, II, IT, ST, OT, MT, MMT}, 
{Store, L2_Replacement}) {
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
   }
 
   transition({M_W, MM_W}, {L2_Replacement}) {
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
   }
 
   transition({IM, IS, OI, MI, II, IT, ST, OT, MT, MMT}, {Load, Ifetch}) {
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
   }
 
   transition({IM, SM, ISM, OM, IS, SS, MM_W, M_W, OI, MI, II, IT, ST, OT, MT, 
MMT}, L1_to_L2) {
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
   }
 
   transition({IT, ST, OT, MT, MMT}, {Other_GETX, NC_DMA_GETS, Other_GETS, 
Merged_GETS, Other_GETS_No_Mig, Invalidate}) {
@@ -1035,6 +1043,7 @@
     vv_allocateL2CacheBlock;
     hp_copyFromTBEToL2;
     s_deallocateTBE;
+    ka_wakeUpAllDependents;
   }
 
   transition(I, Trigger_L2_to_L1D, IT) {
@@ -1044,7 +1053,7 @@
     nb_copyFromTBEToL1; // Not really needed for state I
     s_deallocateTBE;
     uu_profileMiss;
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
     ll_L2toL1Transfer;
   }
 
@@ -1055,7 +1064,7 @@
     nb_copyFromTBEToL1;
     s_deallocateTBE;
     uu_profileMiss;
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
     ll_L2toL1Transfer;
   }
 
@@ -1066,7 +1075,7 @@
     nb_copyFromTBEToL1;
     s_deallocateTBE;
     uu_profileMiss;
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
     ll_L2toL1Transfer;
   }
 
@@ -1077,7 +1086,7 @@
     nb_copyFromTBEToL1;
     s_deallocateTBE;
     uu_profileMiss;
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
     ll_L2toL1Transfer;
   }
 
@@ -1088,7 +1097,7 @@
     nb_copyFromTBEToL1;
     s_deallocateTBE;
     uu_profileMiss;
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
     ll_L2toL1Transfer;
   }
 
@@ -1099,7 +1108,7 @@
     nb_copyFromTBEToL1;
     s_deallocateTBE;
     uu_profileMiss;
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
     ll_L2toL1Transfer;
   }
 
@@ -1110,7 +1119,7 @@
     nb_copyFromTBEToL1;
     s_deallocateTBE;
     uu_profileMiss;
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
     ll_L2toL1Transfer;
   }
 
@@ -1121,7 +1130,7 @@
     nb_copyFromTBEToL1;
     s_deallocateTBE;
     uu_profileMiss;
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
     ll_L2toL1Transfer;
   }
 
@@ -1132,7 +1141,7 @@
     nb_copyFromTBEToL1;
     s_deallocateTBE;
     uu_profileMiss;
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
     ll_L2toL1Transfer;
   }
 
@@ -1143,28 +1152,33 @@
     nb_copyFromTBEToL1;
     s_deallocateTBE;
     uu_profileMiss;
-    zz_recycleMandatoryQueue;
+    zz_stallAndWaitMandatoryQueue;
     ll_L2toL1Transfer;
   }
 
   transition(IT, Complete_L2_to_L1, I) {
     j_popTriggerQueue;
+    kd_wakeUpDependents;
   }
 
   transition(ST, Complete_L2_to_L1, S) {
     j_popTriggerQueue;
+    kd_wakeUpDependents;
   }
 
   transition(OT, Complete_L2_to_L1, O) {
     j_popTriggerQueue;
+    kd_wakeUpDependents;
   }
 
   transition(MT, Complete_L2_to_L1, M) {
     j_popTriggerQueue;
+    kd_wakeUpDependents;
   }
 
   transition(MMT, Complete_L2_to_L1, MM) {
     j_popTriggerQueue;
+    kd_wakeUpDependents;
   }
 
   // Transitions from Idle
@@ -1194,6 +1208,7 @@
 
   transition(I, L2_Replacement) {
     rr_deallocateL2CacheBlock;
+    ka_wakeUpAllDependents;
   }
 
   transition(I, {Other_GETX, NC_DMA_GETS, Other_GETS, Other_GETS_No_Mig, 
Invalidate}) {
@@ -1216,6 +1231,7 @@
 
   transition(S, L2_Replacement, I) {
     rr_deallocateL2CacheBlock;
+    ka_wakeUpAllDependents;
   }
 
   transition(S, {Other_GETX, Invalidate}, I) {
@@ -1246,6 +1262,7 @@
     i_allocateTBE;
     d_issuePUT;
     rr_deallocateL2CacheBlock;
+    ka_wakeUpAllDependents;
   }
 
   transition(O, {Other_GETX, Invalidate}, I) {
@@ -1278,6 +1295,7 @@
     i_allocateTBE;
     d_issuePUT;
     rr_deallocateL2CacheBlock;
+    ka_wakeUpAllDependents;
   }
 
   transition(MM, {Other_GETX, Invalidate}, I) {
@@ -1320,6 +1338,7 @@
     i_allocateTBE;
     d_issuePUT;
     rr_deallocateL2CacheBlock;
+    ka_wakeUpAllDependents;
   }
 
   transition(M, {Other_GETX, Invalidate}, I) {
@@ -1368,6 +1387,7 @@
     o_checkForCompletion;
     sx_external_store_hit;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   // Transitions from SM
@@ -1406,6 +1426,7 @@
     gm_sendUnblockM;
     s_deallocateTBE;
     j_popTriggerQueue;
+    kd_wakeUpDependents;
   }
 
   // Transitions from OM
@@ -1437,6 +1458,7 @@
     gm_sendUnblockM;
     s_deallocateTBE;
     j_popTriggerQueue;
+    kd_wakeUpDependents;
   }
 
   // Transitions from IS
@@ -1466,6 +1488,7 @@
     hx_external_load_hit;
     uo_updateCurrentOwner;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   transition(IS, Exclusive_Data, M_W) {
@@ -1474,6 +1497,7 @@
     o_checkForCompletion;
     hx_external_load_hit;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   transition(IS, Shared_Data, SS) {
@@ -1484,6 +1508,7 @@
     hx_external_load_hit;
     uo_updateCurrentOwner;
     n_popResponseQueue;
+    kd_wakeUpDependents;
   }
 
   // Transitions from SS
@@ -1531,6 +1556,7 @@
     gm_sendUnblockM;
     s_deallocateTBE;
     j_popTriggerQueue;
+    kd_wakeUpDependents;
   }
 
   // Transitions from M_W
@@ -1550,6 +1576,7 @@
     gm_sendUnblockM;
     s_deallocateTBE;
     j_popTriggerQueue;
+    kd_wakeUpDependents;
   }
 
   // Transitions from OI/MI
@@ -1573,12 +1600,14 @@
     t_sendExclusiveDataFromTBEToMemory;
     s_deallocateTBE;
     l_popForwardQueue;
+    kd_wakeUpDependents;
   }
 
   transition(OI, Writeback_Ack, I) {
     qq_sendDataFromTBEToMemory;
     s_deallocateTBE;
     l_popForwardQueue;
+    kd_wakeUpDependents;
   }
 
   // Transitions from II
@@ -1591,10 +1620,12 @@
     g_sendUnblock;
     s_deallocateTBE;
     l_popForwardQueue;
+    kd_wakeUpDependents;
   }
 
   transition(II, Writeback_Nack, I) {
     s_deallocateTBE;
     l_popForwardQueue;
+    kd_wakeUpDependents;
   }
 }
diff --git a/src/mem/ruby/buffers/MessageBuffer.cc 
b/src/mem/ruby/buffers/MessageBuffer.cc
--- a/src/mem/ruby/buffers/MessageBuffer.cc
+++ b/src/mem/ruby/buffers/MessageBuffer.cc
@@ -56,6 +56,8 @@
     m_not_avail_count = 0;
     m_priority_rank = 0;
     m_name = name;
+
+    m_stall_msg_map.clear();
 }
 
 int
@@ -337,11 +339,43 @@
 
         m_prio_heap.push_back(msgNode);
         push_heap(m_prio_heap.begin(), m_prio_heap.end(),
-            greater<MessageBufferNode>());
+                  greater<MessageBufferNode>());
 
         g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, 
msgNode.m_time);
         m_stall_msg_map[addr].pop_front();
     }
+    m_stall_msg_map.erase(addr);
+}
+
+void
+MessageBuffer::reanalyzeAllMessages()
+{
+    DPRINTF(RubyQueue, "ReanalyzeAllMessages %s\n", m_name);
+
+    //
+    // Put all stalled messages associated with this address back on the
+    // prio heap
+    //
+    for (StallMsgMapType::iterator map_iter = m_stall_msg_map.begin();
+         map_iter != m_stall_msg_map.end();
+         ++map_iter) {
+
+        while(!(map_iter->second).empty()) {
+            m_msg_counter++;
+            MessageBufferNode msgNode(g_eventQueue_ptr->getTime() + 1,
+                                      m_msg_counter,
+                                      (map_iter->second).front());
+
+            m_prio_heap.push_back(msgNode);
+            push_heap(m_prio_heap.begin(), m_prio_heap.end(),
+                      greater<MessageBufferNode>());
+
+            g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr,
+                                                    msgNode.m_time);
+            (map_iter->second).pop_front();
+        }
+    }
+    m_stall_msg_map.clear();
 }
 
 void
diff --git a/src/mem/ruby/buffers/MessageBuffer.hh 
b/src/mem/ruby/buffers/MessageBuffer.hh
--- a/src/mem/ruby/buffers/MessageBuffer.hh
+++ b/src/mem/ruby/buffers/MessageBuffer.hh
@@ -61,6 +61,7 @@
     }
 
     void reanalyzeMessages(const Address& addr);
+    void reanalyzeAllMessages();
     void stallMessage(const Address& addr);
 
     // TRUE if head of queue timestamp <= SystemTime
diff --git a/src/mem/slicc/ast/__init__.py b/src/mem/slicc/ast/__init__.py
--- a/src/mem/slicc/ast/__init__.py
+++ b/src/mem/slicc/ast/__init__.py
@@ -72,4 +72,5 @@
 from slicc.ast.TypeFieldMemberAST import *
 from slicc.ast.TypeFieldMethodAST import *
 from slicc.ast.VarExprAST import *
+from slicc.ast.WakeUpAllDependentsStatementAST import *
 from slicc.ast.WakeUpDependentsStatementAST import *
diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py
--- a/src/mem/slicc/parser.py
+++ b/src/mem/slicc/parser.py
@@ -159,6 +159,7 @@
         'peek' : 'PEEK',
         'stall_and_wait' : 'STALL_AND_WAIT',
         'wake_up_dependents' : 'WAKE_UP_DEPENDENTS',
+        'wake_up_all_dependents' : 'WAKE_UP_ALL_DEPENDENTS',
         'enqueue' : 'ENQUEUE',
         'copy_head' : 'COPY_HEAD',
         'check_allocate' : 'CHECK_ALLOCATE',
@@ -561,6 +562,10 @@
         "statement : WAKE_UP_DEPENDENTS '(' var ')' SEMI"
         p[0] = ast.WakeUpDependentsStatementAST(self, p[3])
 
+    def p_statement__wake_up_all_dependents(self, p):
+        "statement : WAKE_UP_ALL_DEPENDENTS '(' ')' SEMI"
+        p[0] = ast.WakeUpAllDependentsStatementAST(self)
+
     def p_statement__peek(self, p):
         "statement : PEEK '(' var ',' type pairs ')' statements"
         p[0] = ast.PeekStatementAST(self, p[3], p[5], p[6], p[8], "peek")
diff --git a/src/mem/slicc/symbols/StateMachine.py 
b/src/mem/slicc/symbols/StateMachine.py
--- a/src/mem/slicc/symbols/StateMachine.py
+++ b/src/mem/slicc/symbols/StateMachine.py
@@ -258,6 +258,7 @@
     const MachineType getMachineType() const;
     void stallBuffer(MessageBuffer* buf, Address addr);
     void wakeUpBuffers(Address addr);
+    void wakeUpAllBuffers();
     void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; }
     void print(std::ostream& out) const;
     void printConfig(std::ostream& out) const;
@@ -734,6 +735,37 @@
 }
 
 void
+$c_ident::wakeUpAllBuffers()
+{
+    //
+    // Wake up all possible buffers that could be waiting on any message.
+    //
+
+    std::vector<MsgVecType*> wokeUpMsgVecs;
+
+    for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin();
+         buf_iter != m_waiting_buffers.end();
+         ++buf_iter) {
+         for (MsgVecType::iterator vec_iter = buf_iter->second->begin();
+              vec_iter != buf_iter->second->end();
+              ++vec_iter) {
+              if (*vec_iter != NULL) {
+                  (*vec_iter)->reanalyzeAllMessages();
+              }
+         }
+         wokeUpMsgVecs.push_back(buf_iter->second);
+    }
+
+    for (std::vector<MsgVecType*>::iterator wb_iter = wokeUpMsgVecs.begin();
+         wb_iter != wokeUpMsgVecs.end();
+         ++wb_iter) {
+         delete (*wb_iter);
+    }
+
+    m_waiting_buffers.clear();
+}
+
+void
 $c_ident::blockOnQueue(Address addr, MessageBuffer* port)
 {
     m_is_blocking = true;
_______________________________________________
m5-dev mailing list
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to