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