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 @@ -153,59 +153,45 @@ TBETable TBEs, template_hack=""; - Entry getCacheEntry(Address addr), return_by_ref="yes" { - if (L2cacheMemory.isTagPresent(addr)) { - return static_cast(Entry, L2cacheMemory[addr]); - } else if (L1DcacheMemory.isTagPresent(addr)) { - return static_cast(Entry, L1DcacheMemory[addr]); - } else { - return static_cast(Entry, L1IcacheMemory[addr]); - } - } + void set_cache_entry(Entry a, AbstractCacheEntry b); + void unset_cache_entry(Entry a); + void set_tbe(TBE b); + void unset_tbe(); + Entry getCacheEntry(Entry a, Entry b, Entry c); - void changePermission(Address addr, AccessPermission permission) { - if (L2cacheMemory.isTagPresent(addr)) { - return L2cacheMemory.changePermission(addr, permission); - } else if (L1DcacheMemory.isTagPresent(addr)) { - return L1DcacheMemory.changePermission(addr, permission); - } else { - return L1IcacheMemory.changePermission(addr, permission); - } - } + State getState(TBE tbe, Entry L1IcacheMemory_entry, Entry L1DcacheMemory_entry, Entry L2cacheMemory_entry, Address addr) { + assert((is_valid_ptr(L1DcacheMemory_entry_ptr) && is_valid_ptr(L1IcacheMemory_entry_ptr)) == false); + assert((is_valid_ptr(L1IcacheMemory_entry_ptr) && is_valid_ptr(L2cacheMemory_entry_ptr)) == false); + assert((is_valid_ptr(L1DcacheMemory_entry_ptr) && is_valid_ptr(L2cacheMemory_entry_ptr)) == false); - bool isCacheTagPresent(Address addr) { - return (L2cacheMemory.isTagPresent(addr) || L1DcacheMemory.isTagPresent(addr) || L1IcacheMemory.isTagPresent(addr)); - } - - State getState(Address addr) { - assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); - assert((L1IcacheMemory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); - assert((L1DcacheMemory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); - - if(TBEs.isPresent(addr)) { - return TBEs[addr].TBEState; - } else if (isCacheTagPresent(addr)) { - return getCacheEntry(addr).CacheState; + if(is_valid_ptr(tbe_ptr)) { + return tbe.TBEState; + } else if (is_valid_ptr(L2cacheMemory_entry_ptr)) { + return L2cacheMemory_entry.CacheState; + } else if (is_valid_ptr(L1DcacheMemory_entry_ptr)) { + return L1DcacheMemory_entry.CacheState; + } else if (is_valid_ptr(L1IcacheMemory_entry_ptr)) { + return L1IcacheMemory_entry.CacheState; } return State:I; } - void setState(Address addr, State state) { - assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); - assert((L1IcacheMemory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); - assert((L1DcacheMemory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); + void setState(TBE tbe, Entry cache_entry, Address addr, State state) { + //assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); + //assert((L1IcacheMemory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); + //assert((L1DcacheMemory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); - if (TBEs.isPresent(addr)) { - TBEs[addr].TBEState := state; + if (is_valid_ptr(tbe_ptr)) { + tbe.TBEState := state; } - if (isCacheTagPresent(addr)) { - getCacheEntry(addr).CacheState := state; + if (is_valid_ptr(cache_entry_ptr)) { + cache_entry.CacheState := state; // Set permission if ((state == State:MM) || (state == State:MM_W)) { - changePermission(addr, AccessPermission:Read_Write); + cache_entry.changePermission(AccessPermission:Read_Write); } else if (state == State:S || state == State:O || state == State:M || @@ -214,9 +200,9 @@ state == State:ISM || state == State:OM || state == State:SS) { - changePermission(addr, AccessPermission:Read_Only); + cache_entry.changePermission(AccessPermission:Read_Only); } else { - changePermission(addr, AccessPermission:Invalid); + cache_entry.changePermission(AccessPermission:Invalid); } } } @@ -244,9 +230,12 @@ } } - GenericMachineType testAndClearLocalHit(Address addr) { - if (getCacheEntry(addr).FromL2) { - getCacheEntry(addr).FromL2 := false; + GenericMachineType testAndClearLocalHit(Entry L1IcacheMemory_entry, Entry L1DcacheMemory_entry) { + if (is_valid_ptr(L1IcacheMemory_entry_ptr) && L1IcacheMemory_entry.FromL2) { + L1IcacheMemory_entry.FromL2 := false; + return GenericMachineType:L2Cache; + } else if (is_valid_ptr(L1DcacheMemory_entry_ptr) && L1DcacheMemory_entry.FromL2) { + L1DcacheMemory_entry.FromL2 := false; return GenericMachineType:L2Cache; } else { return GenericMachineType:L1Cache; @@ -268,6 +257,12 @@ in_port(triggerQueue_in, TriggerMsg, triggerQueue) { if (triggerQueue_in.isReady()) { peek(triggerQueue_in, TriggerMsg) { + + set_cache_entry(L1IcacheMemory_entry_ptr, L1IcacheMemory.lookup(in_msg.Address)); + set_cache_entry(L1DcacheMemory_entry_ptr, L1DcacheMemory.lookup(in_msg.Address)); + set_cache_entry(L2cacheMemory_entry_ptr, L2cacheMemory.lookup(in_msg.Address)); + set_tbe(TBEs[in_msg.Address]); + if (in_msg.Type == TriggerType:L2_to_L1) { trigger(Event:Complete_L2_to_L1, in_msg.Address); } else if (in_msg.Type == TriggerType:ALL_ACKS) { @@ -287,14 +282,20 @@ in_port(forwardToCache_in, RequestMsg, forwardToCache) { if (forwardToCache_in.isReady()) { peek(forwardToCache_in, RequestMsg, block_on="Address") { + + set_cache_entry(L1IcacheMemory_entry_ptr, L1IcacheMemory.lookup(in_msg.Address)); + set_cache_entry(L1DcacheMemory_entry_ptr, L1DcacheMemory.lookup(in_msg.Address)); + set_cache_entry(L2cacheMemory_entry_ptr, L2cacheMemory.lookup(in_msg.Address)); + set_tbe(TBEs[in_msg.Address]); + if (in_msg.Type == CoherenceRequestType:GETX) { trigger(Event:Other_GETX, in_msg.Address); } else if (in_msg.Type == CoherenceRequestType:MERGED_GETS) { trigger(Event:Merged_GETS, in_msg.Address); } else if (in_msg.Type == CoherenceRequestType:GETS) { if (machineCount(MachineType:L1Cache) > 1) { - if (isCacheTagPresent(in_msg.Address)) { - if (getCacheEntry(in_msg.Address).AtomicAccessed && no_mig_atomic) { + if (is_valid_ptr(L1IcacheMemory_entry_ptr) || is_valid_ptr(L1DcacheMemory_entry_ptr) || is_valid_ptr(L2cacheMemory_entry_ptr)) { + if (getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).AtomicAccessed && no_mig_atomic) { trigger(Event:Other_GETS_No_Mig, in_msg.Address); } else { trigger(Event:Other_GETS, in_msg.Address); @@ -322,6 +323,12 @@ in_port(responseToCache_in, ResponseMsg, responseToCache) { if (responseToCache_in.isReady()) { peek(responseToCache_in, ResponseMsg, block_on="Address") { + + set_cache_entry(L1IcacheMemory_entry_ptr, L1IcacheMemory.lookup(in_msg.Address)); + set_cache_entry(L1DcacheMemory_entry_ptr, L1DcacheMemory.lookup(in_msg.Address)); + set_cache_entry(L2cacheMemory_entry_ptr, L2cacheMemory.lookup(in_msg.Address)); + set_tbe(TBEs[in_msg.Address]); + if (in_msg.Type == CoherenceResponseType:ACK) { trigger(Event:Ack, in_msg.Address); } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) { @@ -352,35 +359,50 @@ // ** INSTRUCTION ACCESS *** // Check to see if it is in the OTHER L1 - if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + set_cache_entry(L1DcacheMemory_entry_ptr, L1DcacheMemory.lookup(in_msg.LineAddress)); + if (is_valid_ptr(L1DcacheMemory_entry_ptr)) { // The block is in the wrong L1, try to write it to the L2 if (L2cacheMemory.cacheAvail(in_msg.LineAddress)) { + set_tbe(TBEs[in_msg.LineAddress]); trigger(Event:L1_to_L2, in_msg.LineAddress); } else { + set_cache_entry(L2cacheMemory_entry_ptr, L2cacheMemory.lookup(L2cacheMemory.cacheProbe(in_msg.LineAddress))); + set_tbe(TBEs[L2cacheMemory.cacheProbe(in_msg.LineAddress)]); + unset_cache_entry(L1DcacheMemory_entry_ptr); trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.LineAddress)); } } - if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + set_cache_entry(L1IcacheMemory_entry_ptr, L1IcacheMemory.lookup(in_msg.LineAddress)); + if (is_valid_ptr(L1IcacheMemory_entry_ptr)) { // The tag matches for the L1, so the L1 fetches the line. We know it can't be in the L2 due to exclusion + set_tbe(TBEs[in_msg.LineAddress]); trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); } else { if (L1IcacheMemory.cacheAvail(in_msg.LineAddress)) { // L1 does't have the line, but we have space for it in the L1 - if (L2cacheMemory.isTagPresent(in_msg.LineAddress)) { + + set_cache_entry(L2cacheMemory_entry_ptr, L2cacheMemory.lookup(in_msg.LineAddress)); + if (is_valid_ptr(L2cacheMemory_entry_ptr)) { // L2 has it (maybe not with the right permissions) + set_tbe(TBEs[in_msg.LineAddress]); trigger(Event:Trigger_L2_to_L1I, in_msg.LineAddress); } else { // We have room, the L2 doesn't have it, so the L1 fetches the line + set_tbe(TBEs[in_msg.LineAddress]); trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); } } else { // No room in the L1, so we need to make room if (L2cacheMemory.cacheAvail(L1IcacheMemory.cacheProbe(in_msg.LineAddress))) { // The L2 has room, so we move the line from the L1 to the L2 + set_cache_entry(L1IcacheMemory_entry_ptr, L1IcacheMemory.lookup(L1IcacheMemory.cacheProbe(in_msg.LineAddress))); + set_tbe(TBEs[L1IcacheMemory.cacheProbe(in_msg.LineAddress)]); trigger(Event:L1_to_L2, L1IcacheMemory.cacheProbe(in_msg.LineAddress)); } else { // The L2 does not have room, so we replace a line from the L2 + set_cache_entry(L2cacheMemory_entry_ptr, L2cacheMemory.lookup(L2cacheMemory.cacheProbe(L1IcacheMemory.cacheProbe(in_msg.LineAddress)))); + set_tbe(TBEs[L2cacheMemory.cacheProbe(L1IcacheMemory.cacheProbe(in_msg.LineAddress))]); trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(L1IcacheMemory.cacheProbe(in_msg.LineAddress))); } } @@ -389,35 +411,49 @@ // *** DATA ACCESS *** // Check to see if it is in the OTHER L1 - if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + set_cache_entry(L1IcacheMemory_entry_ptr, L1IcacheMemory.lookup(in_msg.LineAddress)); + if (is_valid_ptr(L1IcacheMemory_entry_ptr)) { // The block is in the wrong L1, try to write it to the L2 if (L2cacheMemory.cacheAvail(in_msg.LineAddress)) { + set_tbe(TBEs[in_msg.LineAddress]); trigger(Event:L1_to_L2, in_msg.LineAddress); } else { + set_cache_entry(L2cacheMemory_entry_ptr, L2cacheMemory.lookup(L2cacheMemory.cacheProbe(in_msg.LineAddress))); + set_tbe(TBEs[L2cacheMemory.cacheProbe(in_msg.LineAddress)]); + unset_cache_entry(L1IcacheMemory_entry_ptr); trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.LineAddress)); } } - if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + set_cache_entry(L1DcacheMemory_entry_ptr, L1DcacheMemory.lookup(in_msg.LineAddress)); + if (is_valid_ptr(L1DcacheMemory_entry_ptr)) { // The tag matches for the L1, so the L1 fetches the line. We know it can't be in the L2 due to exclusion + set_tbe(TBEs[in_msg.LineAddress]); trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); } else { if (L1DcacheMemory.cacheAvail(in_msg.LineAddress)) { // L1 does't have the line, but we have space for it in the L1 - if (L2cacheMemory.isTagPresent(in_msg.LineAddress)) { + set_cache_entry(L2cacheMemory_entry_ptr, L2cacheMemory.lookup(in_msg.LineAddress)); + if (is_valid_ptr(L2cacheMemory_entry_ptr)) { // L2 has it (maybe not with the right permissions) + set_tbe(TBEs[in_msg.LineAddress]); trigger(Event:Trigger_L2_to_L1D, in_msg.LineAddress); } else { // We have room, the L2 doesn't have it, so the L1 fetches the line + set_tbe(TBEs[in_msg.LineAddress]); trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); } } else { // No room in the L1, so we need to make room if (L2cacheMemory.cacheAvail(L1DcacheMemory.cacheProbe(in_msg.LineAddress))) { // The L2 has room, so we move the line from the L1 to the L2 + set_cache_entry(L1DcacheMemory_entry_ptr, L1DcacheMemory.lookup(L1DcacheMemory.cacheProbe(in_msg.LineAddress))); + set_tbe(TBEs[L1DcacheMemory.cacheProbe(in_msg.LineAddress)]); trigger(Event:L1_to_L2, L1DcacheMemory.cacheProbe(in_msg.LineAddress)); } else { // The L2 does not have room, so we replace a line from the L2 + set_cache_entry(L2cacheMemory_entry_ptr, L2cacheMemory.lookup(L2cacheMemory.cacheProbe(L1DcacheMemory.cacheProbe(in_msg.LineAddress)))); + set_tbe(TBEs[L2cacheMemory.cacheProbe(L1DcacheMemory.cacheProbe(in_msg.LineAddress))]); trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(L1DcacheMemory.cacheProbe(in_msg.LineAddress))); } } @@ -437,7 +473,7 @@ out_msg.Destination.add(map_Address_to_Directory(address)); out_msg.MessageSize := MessageSizeType:Request_Control; out_msg.InitialRequestTime := get_time(); - TBEs[address].NumPendingMsgs := machineCount(MachineType:L1Cache); // One from each other cache (n-1) plus the memory (+1) + tbe.NumPendingMsgs := machineCount(MachineType:L1Cache); // One from each other cache (n-1) plus the memory (+1) } } @@ -449,7 +485,7 @@ out_msg.Destination.add(map_Address_to_Directory(address)); out_msg.MessageSize := MessageSizeType:Request_Control; out_msg.InitialRequestTime := get_time(); - TBEs[address].NumPendingMsgs := machineCount(MachineType:L1Cache); // One from each other cache (n-1) plus the memory (+1) + tbe.NumPendingMsgs := machineCount(MachineType:L1Cache); // One from each other cache (n-1) plus the memory (+1) } } @@ -460,8 +496,8 @@ out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getCacheEntry(address).DataBlk; - out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.DataBlk := getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk; + out_msg.Dirty := getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty; if (in_msg.DirectedProbe) { out_msg.Acks := machineCount(MachineType:L1Cache); } else { @@ -491,8 +527,8 @@ out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getCacheEntry(address).DataBlk; - out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.DataBlk := getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk; + out_msg.Dirty := getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty; if (in_msg.DirectedProbe) { out_msg.Acks := machineCount(MachineType:L1Cache); } else { @@ -512,9 +548,9 @@ out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getCacheEntry(address).DataBlk; + out_msg.DataBlk := getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk; + out_msg.Dirty := getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty; DPRINTF(RubySlicc, "%s\n", out_msg.DataBlk); - out_msg.Dirty := getCacheEntry(address).Dirty; if (in_msg.DirectedProbe) { out_msg.Acks := machineCount(MachineType:L1Cache); } else { @@ -534,9 +570,9 @@ out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; out_msg.Destination := in_msg.MergedRequestors; - out_msg.DataBlk := getCacheEntry(address).DataBlk; + out_msg.DataBlk := getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk; + out_msg.Dirty := getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty; DPRINTF(RubySlicc, "%s\n", out_msg.DataBlk); - out_msg.Dirty := getCacheEntry(address).Dirty; out_msg.Acks := machineCount(MachineType:L1Cache); out_msg.MessageSize := MessageSizeType:Response_Data; out_msg.InitialRequestTime := in_msg.InitialRequestTime; @@ -602,84 +638,84 @@ out_msg.Address := address; out_msg.Type := CoherenceResponseType:UNBLOCKS; out_msg.Sender := machineID; - out_msg.CurOwner := TBEs[address].CurOwner; + out_msg.CurOwner := tbe.CurOwner; out_msg.Destination.add(map_Address_to_Directory(address)); out_msg.MessageSize := MessageSizeType:Unblock_Control; } } action(h_load_hit, "h", desc="Notify sequencer the load completed.") { - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); - + DPRINTF(RubySlicc, "%s\n", getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk); + sequencer.readCallback(address, - testAndClearLocalHit(address), - getCacheEntry(address).DataBlk); + testAndClearLocalHit(L1DcacheMemory_entry_ptr, L1IcacheMemory_entry_ptr), + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk); } action(hx_external_load_hit, "hx", desc="load required external msgs") { - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); + DPRINTF(RubySlicc, "%s\n", getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk); peek(responseToCache_in, ResponseMsg) { sequencer.readCallback(address, getNondirectHitMachType(in_msg.Address, in_msg.Sender), - getCacheEntry(address).DataBlk, - TBEs[address].InitialRequestTime, - TBEs[address].ForwardRequestTime, - TBEs[address].FirstResponseTime); + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk, + tbe.InitialRequestTime, + tbe.ForwardRequestTime, + tbe.FirstResponseTime); } } action(hh_store_hit, "\h", desc="Notify sequencer that store completed.") { - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); + DPRINTF(RubySlicc, "%s\n", getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk); peek(mandatoryQueue_in, CacheMsg) { sequencer.writeCallback(address, - testAndClearLocalHit(address), - getCacheEntry(address).DataBlk); + testAndClearLocalHit(L1DcacheMemory_entry_ptr, L1IcacheMemory_entry_ptr), + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk); - getCacheEntry(address).Dirty := true; + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty := true; if (in_msg.Type == CacheRequestType:ATOMIC) { - getCacheEntry(address).AtomicAccessed := true; + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).AtomicAccessed := true; } } } action(sx_external_store_hit, "sx", desc="store required external msgs.") { - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); + DPRINTF(RubySlicc, "%s\n", getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk); peek(responseToCache_in, ResponseMsg) { sequencer.writeCallback(address, getNondirectHitMachType(address, in_msg.Sender), - getCacheEntry(address).DataBlk, - TBEs[address].InitialRequestTime, - TBEs[address].ForwardRequestTime, - TBEs[address].FirstResponseTime); + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk, + tbe.InitialRequestTime, + tbe.ForwardRequestTime, + tbe.FirstResponseTime); } - getCacheEntry(address).Dirty := true; + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty := true; } action(sxt_trig_ext_store_hit, "sxt", desc="store required external msgs.") { - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); + DPRINTF(RubySlicc, "%s\n", getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk); sequencer.writeCallback(address, - getNondirectHitMachType(address, - TBEs[address].LastResponder), - getCacheEntry(address).DataBlk, - TBEs[address].InitialRequestTime, - TBEs[address].ForwardRequestTime, - TBEs[address].FirstResponseTime); + getNondirectHitMachType(address, tbe.LastResponder), + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk, + tbe.InitialRequestTime, + tbe.ForwardRequestTime, + tbe.FirstResponseTime); - getCacheEntry(address).Dirty := true; + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty := true; } action(i_allocateTBE, "i", desc="Allocate TBE") { check_allocate(TBEs); TBEs.allocate(address); - TBEs[address].DataBlk := getCacheEntry(address).DataBlk; // Data only used for writebacks - TBEs[address].Dirty := getCacheEntry(address).Dirty; - TBEs[address].Sharers := false; + set_tbe(TBEs[address]); + tbe.DataBlk := getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk; // Data only used for writebacks + tbe.Dirty := getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty; + tbe.Sharers := false; } action(j_popTriggerQueue, "j", desc="Pop trigger queue.") { @@ -697,30 +733,30 @@ action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") { peek(responseToCache_in, ResponseMsg) { assert(in_msg.Acks > 0); - DPRINTF(RubySlicc, "%d\n", TBEs[address].NumPendingMsgs); - TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - in_msg.Acks; - DPRINTF(RubySlicc, "%d\n", TBEs[address].NumPendingMsgs); - TBEs[address].LastResponder := in_msg.Sender; - if (TBEs[address].InitialRequestTime != zero_time() && in_msg.InitialRequestTime != zero_time()) { - assert(TBEs[address].InitialRequestTime == in_msg.InitialRequestTime); + DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs); + tbe.NumPendingMsgs := tbe.NumPendingMsgs - in_msg.Acks; + DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs); + tbe.LastResponder := in_msg.Sender; + if (tbe.InitialRequestTime != zero_time() && in_msg.InitialRequestTime != zero_time()) { + assert(tbe.InitialRequestTime == in_msg.InitialRequestTime); } if (in_msg.InitialRequestTime != zero_time()) { - TBEs[address].InitialRequestTime := in_msg.InitialRequestTime; + tbe.InitialRequestTime := in_msg.InitialRequestTime; } - if (TBEs[address].ForwardRequestTime != zero_time() && in_msg.ForwardRequestTime != zero_time()) { - assert(TBEs[address].ForwardRequestTime == in_msg.ForwardRequestTime); + if (tbe.ForwardRequestTime != zero_time() && in_msg.ForwardRequestTime != zero_time()) { + assert(tbe.ForwardRequestTime == in_msg.ForwardRequestTime); } if (in_msg.ForwardRequestTime != zero_time()) { - TBEs[address].ForwardRequestTime := in_msg.ForwardRequestTime; + tbe.ForwardRequestTime := in_msg.ForwardRequestTime; } - if (TBEs[address].FirstResponseTime == zero_time()) { - TBEs[address].FirstResponseTime := get_time(); + if (tbe.FirstResponseTime == zero_time()) { + tbe.FirstResponseTime := get_time(); } } } action(uo_updateCurrentOwner, "uo", desc="When moving SS state, update current owner.") { peek(responseToCache_in, ResponseMsg) { - TBEs[address].CurOwner := in_msg.Sender; + tbe.CurOwner := in_msg.Sender; } } @@ -736,10 +772,10 @@ } action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") { - if (TBEs[address].NumPendingMsgs == 0) { + if (tbe.NumPendingMsgs == 0) { enqueue(triggerQueue_out, TriggerMsg) { out_msg.Address := address; - if (TBEs[address].Sharers) { + if (tbe.Sharers) { out_msg.Type := TriggerType:ALL_ACKS; } else { out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS; @@ -749,11 +785,11 @@ } action(p_decrementNumberOfMessagesByOne, "p", desc="Decrement the number of messages for which we're waiting by one") { - TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - 1; + tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1; } action(pp_incrementNumberOfMessagesByOne, "\p", desc="Increment the number of messages for which we're waiting by one") { - TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs + 1; + tbe.NumPendingMsgs := tbe.NumPendingMsgs + 1; } action(q_sendDataFromTBEToCache, "q", desc="Send data from TBE to cache") { @@ -764,8 +800,8 @@ out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); DPRINTF(RubySlicc, "%s\n", out_msg.Destination); - out_msg.DataBlk := TBEs[address].DataBlk; - out_msg.Dirty := TBEs[address].Dirty; + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; if (in_msg.DirectedProbe) { out_msg.Acks := machineCount(MachineType:L1Cache); } else { @@ -786,8 +822,8 @@ out_msg.Sender := machineID; out_msg.Destination := in_msg.MergedRequestors; DPRINTF(RubySlicc, "%s\n", out_msg.Destination); - out_msg.DataBlk := TBEs[address].DataBlk; - out_msg.Dirty := TBEs[address].Dirty; + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; out_msg.Acks := machineCount(MachineType:L1Cache); out_msg.MessageSize := MessageSizeType:Response_Data; out_msg.InitialRequestTime := in_msg.InitialRequestTime; @@ -801,27 +837,28 @@ out_msg.Address := address; out_msg.Sender := machineID; out_msg.Destination.add(map_Address_to_Directory(address)); - out_msg.Dirty := TBEs[address].Dirty; - if (TBEs[address].Dirty) { + out_msg.Dirty := tbe.Dirty; + if (tbe.Dirty) { out_msg.Type := CoherenceResponseType:WB_DIRTY; - out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.DataBlk := tbe.DataBlk; out_msg.MessageSize := MessageSizeType:Writeback_Data; } else { out_msg.Type := CoherenceResponseType:WB_CLEAN; // NOTE: in a real system this would not send data. We send // data here only so we can check it at the memory - out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.DataBlk := tbe.DataBlk; out_msg.MessageSize := MessageSizeType:Writeback_Control; } } } action(r_setSharerBit, "r", desc="We saw other sharers") { - TBEs[address].Sharers := true; + tbe.Sharers := true; } action(s_deallocateTBE, "s", desc="Deallocate TBE") { TBEs.deallocate(address); + unset_tbe(); } action(t_sendExclusiveDataFromTBEToMemory, "t", desc="Send exclusive data from TBE to memory") { @@ -829,17 +866,17 @@ out_msg.Address := address; out_msg.Sender := machineID; out_msg.Destination.add(map_Address_to_Directory(address)); - out_msg.DataBlk := TBEs[address].DataBlk; - out_msg.Dirty := TBEs[address].Dirty; - if (TBEs[address].Dirty) { + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; + if (tbe.Dirty) { out_msg.Type := CoherenceResponseType:WB_EXCLUSIVE_DIRTY; - out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.DataBlk := tbe.DataBlk; out_msg.MessageSize := MessageSizeType:Writeback_Data; } else { out_msg.Type := CoherenceResponseType:WB_EXCLUSIVE_CLEAN; // NOTE: in a real system this would not send data. We send // data here only so we can check it at the memory - out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.DataBlk := tbe.DataBlk; out_msg.MessageSize := MessageSizeType:Writeback_Control; } } @@ -847,79 +884,86 @@ action(u_writeDataToCache, "u", desc="Write data to cache") { peek(responseToCache_in, ResponseMsg) { - getCacheEntry(address).DataBlk := in_msg.DataBlk; - getCacheEntry(address).Dirty := in_msg.Dirty; + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk := in_msg.DataBlk; + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty := in_msg.Dirty; } } action(v_writeDataToCacheVerify, "v", desc="Write data to cache, assert it was same as before") { peek(responseToCache_in, ResponseMsg) { DPRINTF(RubySlicc, "Cached Data Block: %s, Msg Data Block: %s\n", - getCacheEntry(address).DataBlk, in_msg.DataBlk); - assert(getCacheEntry(address).DataBlk == in_msg.DataBlk); - getCacheEntry(address).DataBlk := in_msg.DataBlk; - getCacheEntry(address).Dirty := in_msg.Dirty || getCacheEntry(address).Dirty; + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk, in_msg.DataBlk); + assert(getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk == in_msg.DataBlk); + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).DataBlk := in_msg.DataBlk; + getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty := in_msg.Dirty || getCacheEntry(L1IcacheMemory_entry_ptr, L1DcacheMemory_entry_ptr, L2cacheMemory_entry_ptr).Dirty; } } action(gg_deallocateL1CacheBlock, "\g", desc="Deallocate cache block. Sets the cache to invalid, allowing a replacement in parallel with a fetch.") { - if (L1DcacheMemory.isTagPresent(address)) { + if (is_valid_ptr(L1DcacheMemory_entry_ptr)) { L1DcacheMemory.deallocate(address); + unset_cache_entry(L1DcacheMemory_entry_ptr); } else { L1IcacheMemory.deallocate(address); + unset_cache_entry(L1IcacheMemory_entry_ptr); } } action(ii_allocateL1DCacheBlock, "\i", desc="Set L1 D-cache tag equal to tag of block B.") { - if (L1DcacheMemory.isTagPresent(address) == false) { - L1DcacheMemory.allocate(address, new Entry); + if (is_valid_ptr(L1DcacheMemory_entry_ptr)) { + } else { + set_cache_entry(L1DcacheMemory_entry_ptr, L1DcacheMemory.allocate(address, new Entry)); } } action(jj_allocateL1ICacheBlock, "\j", desc="Set L1 I-cache tag equal to tag of block B.") { - if (L1IcacheMemory.isTagPresent(address) == false) { - L1IcacheMemory.allocate(address, new Entry); + if (is_valid_ptr(L1IcacheMemory_entry_ptr)) { + } else { + set_cache_entry(L1IcacheMemory_entry_ptr, L1IcacheMemory.allocate(address, new Entry)); } } action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") { - L2cacheMemory.allocate(address, new Entry); + set_cache_entry(L2cacheMemory_entry_ptr, L2cacheMemory.allocate(address, new Entry)); } action(rr_deallocateL2CacheBlock, "\r", desc="Deallocate L2 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") { L2cacheMemory.deallocate(address); + unset_cache_entry(L2cacheMemory_entry_ptr); } action(ss_copyFromL1toL2, "\s", desc="Copy data block from L1 (I or D) to L2") { - if (L1DcacheMemory.isTagPresent(address)) { - static_cast(Entry, L2cacheMemory[address]).Dirty := static_cast(Entry, L1DcacheMemory[address]).Dirty; - static_cast(Entry, L2cacheMemory[address]).DataBlk := static_cast(Entry, L1DcacheMemory[address]).DataBlk; + if(is_valid_ptr(L1DcacheMemory_entry_ptr)) { + L2cacheMemory_entry.Dirty := L1DcacheMemory_entry.Dirty; + L2cacheMemory_entry.DataBlk := L1DcacheMemory_entry.DataBlk; } else { - static_cast(Entry, L2cacheMemory[address]).Dirty := static_cast(Entry, L1IcacheMemory[address]).Dirty; - static_cast(Entry, L2cacheMemory[address]).DataBlk := static_cast(Entry, L1IcacheMemory[address]).DataBlk; + L2cacheMemory_entry.Dirty := L1IcacheMemory_entry.Dirty; + L2cacheMemory_entry.DataBlk := L1IcacheMemory_entry.DataBlk; } } action(tt_copyFromL2toL1, "\t", desc="Copy data block from L2 to L1 (I or D)") { - if (L1DcacheMemory.isTagPresent(address)) { - static_cast(Entry, L1DcacheMemory[address]).Dirty := static_cast(Entry, L2cacheMemory[address]).Dirty; - static_cast(Entry, L1DcacheMemory[address]).DataBlk := static_cast(Entry, L2cacheMemory[address]).DataBlk; - static_cast(Entry, L1DcacheMemory[address]).FromL2 := true; + if(is_valid_ptr(L1DcacheMemory_entry_ptr)) { + L1DcacheMemory_entry.Dirty := L2cacheMemory_entry.Dirty; + L1DcacheMemory_entry.DataBlk := L2cacheMemory_entry.DataBlk; + L1DcacheMemory_entry.FromL2 := true; } else { - static_cast(Entry, L1IcacheMemory[address]).Dirty := static_cast(Entry, L2cacheMemory[address]).Dirty; - static_cast(Entry, L1IcacheMemory[address]).DataBlk := static_cast(Entry, L2cacheMemory[address]).DataBlk; - static_cast(Entry, L1IcacheMemory[address]).FromL2 := true; + L1IcacheMemory_entry.Dirty := L2cacheMemory_entry.Dirty; + L1IcacheMemory_entry.DataBlk := L2cacheMemory_entry.DataBlk; + L1IcacheMemory_entry.FromL2 := true; } } action(uu_profileMiss, "\u", desc="Profile the demand miss") { peek(mandatoryQueue_in, CacheMsg) { - if (L1IcacheMemory.isTagPresent(address)) { + if (is_valid_ptr(L1IcacheMemory_entry_ptr)) { L1IcacheMemory.profileMiss(in_msg); - } else if (L1DcacheMemory.isTagPresent(address)) { + } else if (is_valid_ptr(L1DcacheMemory_entry_ptr)) { L1DcacheMemory.profileMiss(in_msg); } - if (L2cacheMemory.isTagPresent(address) == false) { + + if (is_valid_ptr(L2cacheMemory_entry_ptr)) { + } else { L2cacheMemory.profileMiss(in_msg); } } @@ -1502,4 +1546,3 @@ l_popForwardQueue; } } - diff --git a/src/mem/protocol/MOESI_hammer-dir.sm b/src/mem/protocol/MOESI_hammer-dir.sm --- a/src/mem/protocol/MOESI_hammer-dir.sm +++ b/src/mem/protocol/MOESI_hammer-dir.sm @@ -166,6 +166,10 @@ bool isPresent(Address); } + void set_cache_entry(PfEntry a, AbstractCacheEntry b); + void set_tbe(TBE a); + void unset_tbe(); + // ** OBJECTS ** TBETable TBEs, template_hack=""; @@ -174,17 +178,13 @@ return static_cast(Entry, directory[addr]); } - PfEntry getPfEntry(Address addr), return_by_ref="yes" { - return static_cast(PfEntry, probeFilter[addr]); - } - - State getState(Address addr) { - if (TBEs.isPresent(addr)) { - return TBEs[addr].TBEState; + State getState(TBE tbe, PfEntry pf_entry, Address addr) { + if (is_valid_ptr(tbe_ptr)) { + return tbe.TBEState; } else { if (probe_filter_enabled) { - if (probeFilter.isTagPresent(addr)) { - assert(getPfEntry(addr).PfState == getDirectoryEntry(addr).DirectoryState); + if (is_valid_ptr(pf_entry_ptr)) { + assert(pf_entry.PfState == getDirectoryEntry(addr).DirectoryState); } else { assert(getDirectoryEntry(addr).DirectoryState == State:E); } @@ -193,21 +193,21 @@ } } - void setState(Address addr, State state) { - if (TBEs.isPresent(addr)) { - TBEs[addr].TBEState := state; + void setState(TBE tbe, PfEntry pf_entry, Address addr, State state) { + if (is_valid_ptr(tbe_ptr)) { + tbe.TBEState := state; } if (probe_filter_enabled) { - if (probeFilter.isTagPresent(addr)) { - getPfEntry(addr).PfState := state; + if (is_valid_ptr(pf_entry_ptr)) { + pf_entry.PfState := state; } if (state == State:NX || state == State:NO || state == State:S || state == State:O) { - assert(probeFilter.isTagPresent(addr)); + assert(is_valid_ptr(pf_entry_ptr)); } } if (state == State:E || state == State:NX || state == State:NO || state == State:S || state == State:O) { - assert(TBEs.isPresent(addr) == false); + assert(is_valid_ptr(tbe_ptr) == false); } getDirectoryEntry(addr).DirectoryState := state; } @@ -242,6 +242,10 @@ in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=5) { if (triggerQueue_in.isReady()) { peek(triggerQueue_in, TriggerMsg) { + if(probe_filter_enabled) { + set_cache_entry(probeFilter_entry_ptr, probeFilter.lookup(in_msg.Address)); + } + set_tbe(TBEs[in_msg.Address]); if (in_msg.Type == TriggerType:ALL_ACKS) { trigger(Event:All_acks_and_owner_data, in_msg.Address); } else if (in_msg.Type == TriggerType:ALL_ACKS_OWNER_EXISTS) { @@ -260,6 +264,10 @@ in_port(unblockNetwork_in, ResponseMsg, unblockToDir, rank=4) { if (unblockNetwork_in.isReady()) { peek(unblockNetwork_in, ResponseMsg) { + if(probe_filter_enabled) { + set_cache_entry(probeFilter_entry_ptr, probeFilter.lookup(in_msg.Address)); + } + set_tbe(TBEs[in_msg.Address]); if (in_msg.Type == CoherenceResponseType:UNBLOCK) { trigger(Event:Unblock, in_msg.Address); } else if (in_msg.Type == CoherenceResponseType:UNBLOCKS) { @@ -285,6 +293,10 @@ in_port(responseToDir_in, ResponseMsg, responseToDir, rank=3) { if (responseToDir_in.isReady()) { peek(responseToDir_in, ResponseMsg) { + if(probe_filter_enabled) { + set_cache_entry(probeFilter_entry_ptr, probeFilter.lookup(in_msg.Address)); + } + set_tbe(TBEs[in_msg.Address]); if (in_msg.Type == CoherenceResponseType:ACK) { trigger(Event:Ack, in_msg.Address); } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) { @@ -306,6 +318,10 @@ in_port(memQueue_in, MemoryMsg, memBuffer, rank=2) { if (memQueue_in.isReady()) { peek(memQueue_in, MemoryMsg) { + if(probe_filter_enabled) { + set_cache_entry(probeFilter_entry_ptr, probeFilter.lookup(in_msg.Address)); + } + set_tbe(TBEs[in_msg.Address]); if (in_msg.Type == MemoryRequestType:MEMORY_READ) { trigger(Event:Memory_Data, in_msg.Address); } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { @@ -321,16 +337,22 @@ in_port(requestQueue_in, RequestMsg, requestToDir, rank=1) { if (requestQueue_in.isReady()) { peek(requestQueue_in, RequestMsg) { + if(probe_filter_enabled) { + set_cache_entry(probeFilter_entry_ptr, probeFilter.lookup(in_msg.Address)); + } + set_tbe(TBEs[in_msg.Address]); if (in_msg.Type == CoherenceRequestType:PUT) { trigger(Event:PUT, in_msg.Address); } else { if (probe_filter_enabled) { - if (probeFilter.isTagPresent(in_msg.Address)) { + if (is_valid_ptr(probeFilter_entry_ptr)) { trigger(cache_request_to_event(in_msg.Type), in_msg.Address); } else { if (probeFilter.cacheAvail(in_msg.Address)) { trigger(cache_request_to_event(in_msg.Type), in_msg.Address); } else { + set_cache_entry(probeFilter_entry_ptr, probeFilter.lookup(probeFilter.cacheProbe(in_msg.Address))); + set_tbe(TBEs[probeFilter.cacheProbe(in_msg.Address)]); trigger(Event:Pf_Replacement, probeFilter.cacheProbe(in_msg.Address)); } } @@ -345,6 +367,10 @@ in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir, rank=0) { if (dmaRequestQueue_in.isReady()) { peek(dmaRequestQueue_in, DMARequestMsg) { + if(probe_filter_enabled) { + set_cache_entry(probeFilter_entry_ptr, probeFilter.lookup(in_msg.LineAddress)); + } + set_tbe(TBEs[in_msg.LineAddress]); if (in_msg.Type == DMARequestType:READ) { trigger(Event:DMA_READ, in_msg.LineAddress); } else if (in_msg.Type == DMARequestType:WRITE) { @@ -360,25 +386,25 @@ action(r_setMRU, "\rr", desc="manually set the MRU bit for pf entry" ) { if (probe_filter_enabled) { - assert(probeFilter.isTagPresent(address)); + assert(is_valid_ptr(probeFilter_entry_ptr)); probeFilter.setMRU(address); } } action(auno_assertUnblockerNotOwner, "auno", desc="assert unblocker not owner") { if (probe_filter_enabled) { - assert(probeFilter.isTagPresent(address)); + assert(is_valid_ptr(probeFilter_entry_ptr)); peek(unblockNetwork_in, ResponseMsg) { - assert(getPfEntry(address).Owner != in_msg.Sender); + assert(probeFilter_entry.Owner != in_msg.Sender); } } } action(uo_updateOwnerIfPf, "uo", desc="update owner") { if (probe_filter_enabled) { - assert(probeFilter.isTagPresent(address)); + assert(is_valid_ptr(probeFilter_entry_ptr)); peek(unblockNetwork_in, ResponseMsg) { - getPfEntry(address).Owner := in_msg.Sender; + probeFilter_entry.Owner := in_msg.Sender; } } } @@ -410,8 +436,8 @@ action(pfa_probeFilterAllocate, "pfa", desc="Allocate ProbeFilterEntry") { if (probe_filter_enabled) { peek(requestQueue_in, RequestMsg) { - probeFilter.allocate(address, new PfEntry); - getPfEntry(in_msg.Address).Owner := in_msg.Requestor; + set_cache_entry(probeFilter_entry_ptr, probeFilter.allocate(address, new PfEntry)); + probeFilter_entry.Owner := in_msg.Requestor; } } } @@ -423,7 +449,7 @@ } action(ppfd_possibleProbeFilterDeallocate, "ppfd", desc="Deallocate ProbeFilterEntry") { - if (probe_filter_enabled && probeFilter.isTagPresent(address)) { + if (probe_filter_enabled && is_valid_ptr(probeFilter_entry_ptr)) { probeFilter.deallocate(address); } } @@ -431,80 +457,83 @@ action(v_allocateTBE, "v", desc="Allocate TBE") { peek(requestQueue_in, RequestMsg) { TBEs.allocate(address); - TBEs[address].PhysicalAddress := address; - TBEs[address].ResponseType := CoherenceResponseType:NULL; + set_tbe(TBEs[address]); + tbe.PhysicalAddress := address; + tbe.ResponseType := CoherenceResponseType:NULL; } } action(vd_allocateDmaRequestInTBE, "vd", desc="Record Data in TBE") { peek(dmaRequestQueue_in, DMARequestMsg) { TBEs.allocate(address); - TBEs[address].DmaDataBlk := in_msg.DataBlk; - TBEs[address].PhysicalAddress := in_msg.PhysicalAddress; - TBEs[address].Len := in_msg.Len; - TBEs[address].DmaRequestor := in_msg.Requestor; - TBEs[address].ResponseType := CoherenceResponseType:DATA_EXCLUSIVE; + set_tbe(TBEs[address]); + tbe.DmaDataBlk := in_msg.DataBlk; + tbe.PhysicalAddress := in_msg.PhysicalAddress; + tbe.Len := in_msg.Len; + tbe.DmaRequestor := in_msg.Requestor; + tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE; // // One ack for each last-level cache // - TBEs[address].NumPendingMsgs := machineCount(MachineType:L1Cache); + tbe.NumPendingMsgs := machineCount(MachineType:L1Cache); // // Assume initially that the caches store a clean copy and that memory // will provide the data // - TBEs[address].CacheDirty := false; + tbe.CacheDirty := false; } } action(pa_setPendingMsgsToAll, "pa", desc="set pending msgs to all") { - TBEs[address].NumPendingMsgs := machineCount(MachineType:L1Cache); + tbe.NumPendingMsgs := machineCount(MachineType:L1Cache); } action(po_setPendingMsgsToOne, "po", desc="set pending msgs to one") { - TBEs[address].NumPendingMsgs := 1; + tbe.NumPendingMsgs := 1; } action(w_deallocateTBE, "w", desc="Deallocate TBE") { TBEs.deallocate(address); + unset_tbe(); } action(sa_setAcksToOne, "sa", desc="Forwarded request, set the ack amount to one") { - TBEs[address].Acks := 1; + tbe.Acks := 1; } action(saa_setAcksToAllIfPF, "saa", desc="Non-forwarded request, set the ack amount to all") { if (probe_filter_enabled) { - TBEs[address].Acks := machineCount(MachineType:L1Cache); + tbe.Acks := machineCount(MachineType:L1Cache); } else { - TBEs[address].Acks := 1; + tbe.Acks := 1; } } action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") { peek(responseToDir_in, ResponseMsg) { assert(in_msg.Acks > 0); - DPRINTF(RubySlicc, "%d\n", TBEs[address].NumPendingMsgs); + DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs); // // Note that cache data responses will have an ack count of 2. However, // directory DMA requests must wait for acks from all LLC caches, so // only decrement by 1. // - TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - 1; - DPRINTF(RubySlicc, "%d\n", TBEs[address].NumPendingMsgs); + tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1; + DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs); } } action(mu_decrementNumberOfUnblocks, "mu", desc="Decrement the number of messages for which we're waiting") { peek(unblockNetwork_in, ResponseMsg) { assert(in_msg.Type == CoherenceResponseType:UNBLOCKS); - DPRINTF(RubySlicc, "%d\n", TBEs[address].NumPendingMsgs); + DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs); // // Note that cache data responses will have an ack count of 2. However, // directory DMA requests must wait for acks from all LLC caches, so // only decrement by 1. // - TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - 1; - DPRINTF(RubySlicc, "%d\n", TBEs[address].NumPendingMsgs); + tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1; + DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs); } } @@ -513,11 +542,11 @@ } action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") { - if (TBEs[address].NumPendingMsgs == 0) { + if (tbe.NumPendingMsgs == 0) { enqueue(triggerQueue_out, TriggerMsg) { out_msg.Address := address; - if (TBEs[address].Sharers) { - if (TBEs[address].Owned) { + if (tbe.Sharers) { + if (tbe.Owned) { out_msg.Type := TriggerType:ALL_ACKS_OWNER_EXISTS; } else { out_msg.Type := TriggerType:ALL_ACKS; @@ -530,7 +559,7 @@ } action(os_checkForMergedGetSCompletion, "os", desc="Check for merged GETS completion") { - if (TBEs[address].NumPendingMsgs == 0) { + if (tbe.NumPendingMsgs == 0) { enqueue(triggerQueue_out, TriggerMsg) { out_msg.Address := address; out_msg.Type := TriggerType:ALL_UNBLOCKS; @@ -539,17 +568,17 @@ } action(sp_setPendingMsgsToMergedSharers, "sp", desc="Set pending messages to waiting sharers") { - TBEs[address].NumPendingMsgs := TBEs[address].GetSRequestors.count(); + tbe.NumPendingMsgs := tbe.GetSRequestors.count(); } action(spa_setPendingAcksToZeroIfPF, "spa", desc="if probe filter, no need to wait for acks") { if (probe_filter_enabled) { - TBEs[address].NumPendingMsgs := 0; + tbe.NumPendingMsgs := 0; } } action(sc_signalCompletionIfPF, "sc", desc="indicate that we should skip waiting for cpu acks") { - if (TBEs[address].NumPendingMsgs == 0) { + if (tbe.NumPendingMsgs == 0) { assert(probe_filter_enabled); enqueue(triggerQueue_out, TriggerMsg) { out_msg.Address := address; @@ -562,13 +591,13 @@ peek(memQueue_in, MemoryMsg) { enqueue(responseNetwork_out, ResponseMsg, latency="1") { out_msg.Address := address; - out_msg.Type := TBEs[address].ResponseType; + out_msg.Type := tbe.ResponseType; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.OriginalRequestorMachId); out_msg.DataBlk := in_msg.DataBlk; DPRINTF(RubySlicc, "%s\n", out_msg.DataBlk); out_msg.Dirty := false; // By definition, the block is now clean - out_msg.Acks := TBEs[address].Acks; + out_msg.Acks := tbe.Acks; DPRINTF(RubySlicc, "%d\n", out_msg.Acks); assert(out_msg.Acks > 0); out_msg.MessageSize := MessageSizeType:Response_Data; @@ -587,7 +616,7 @@ // split it up if need be // out_msg.DataBlk := in_msg.DataBlk; - out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.Destination.add(tbe.DmaRequestor); out_msg.MessageSize := MessageSizeType:Response_Data; } } @@ -603,8 +632,8 @@ // we send the entire data block and rely on the dma controller to // split it up if need be // - out_msg.DataBlk := TBEs[address].DataBlk; - out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.DataBlk := tbe.DataBlk; + out_msg.Destination.add(tbe.DmaRequestor); out_msg.MessageSize := MessageSizeType:Response_Data; } } @@ -615,36 +644,36 @@ out_msg.PhysicalAddress := address; out_msg.LineAddress := address; out_msg.Type := DMAResponseType:ACK; - out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.Destination.add(tbe.DmaRequestor); out_msg.MessageSize := MessageSizeType:Writeback_Control; } } action(rx_recordExclusiveInTBE, "rx", desc="Record Exclusive in TBE") { peek(requestQueue_in, RequestMsg) { - TBEs[address].ResponseType := CoherenceResponseType:DATA_EXCLUSIVE; + tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE; } } action(r_recordDataInTBE, "rt", desc="Record Data in TBE") { peek(requestQueue_in, RequestMsg) { - TBEs[address].ResponseType := CoherenceResponseType:DATA; + tbe.ResponseType := CoherenceResponseType:DATA; } } action(rs_recordGetSRequestor, "rs", desc="Record GETS requestor in TBE") { peek(requestQueue_in, RequestMsg) { - TBEs[address].GetSRequestors.add(in_msg.Requestor); + tbe.GetSRequestors.add(in_msg.Requestor); } } action(r_setSharerBit, "r", desc="We saw other sharers") { - TBEs[address].Sharers := true; + tbe.Sharers := true; } action(so_setOwnerBit, "so", desc="We saw other sharers") { - TBEs[address].Sharers := true; - TBEs[address].Owned := true; + tbe.Sharers := true; + tbe.Owned := true; } action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") { @@ -676,7 +705,7 @@ } action(fn_forwardRequestIfNecessary, "fn", desc="Forward requests if necessary") { - if ((machineCount(MachineType:L1Cache) > 1) && (TBEs[address].Acks <= 1)) { + if ((machineCount(MachineType:L1Cache) > 1) && (tbe.Acks <= 1)) { peek(requestQueue_in, RequestMsg) { enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { out_msg.Address := address; @@ -710,7 +739,7 @@ out_msg.Address := address; out_msg.Type := CoherenceRequestType:INV; out_msg.Requestor := machineID; - out_msg.Destination.add(getPfEntry(address).Owner); + out_msg.Destination.add(probeFilter_entry.Owner); out_msg.MessageSize := MessageSizeType:Request_Control; out_msg.DirectedProbe := true; } @@ -744,7 +773,7 @@ enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { out_msg.Address := address; out_msg.Type := CoherenceRequestType:MERGED_GETS; - out_msg.MergedRequestors := TBEs[address].GetSRequestors; + out_msg.MergedRequestors := tbe.GetSRequestors; if (in_msg.Type == CoherenceResponseType:UNBLOCKS) { out_msg.Destination.add(in_msg.CurOwner); } else { @@ -765,7 +794,7 @@ out_msg.Address := address; out_msg.Type := in_msg.Type; out_msg.Requestor := in_msg.Requestor; - out_msg.Destination.add(getPfEntry(address).Owner); + out_msg.Destination.add(probeFilter_entry.Owner); out_msg.MessageSize := MessageSizeType:Request_Control; out_msg.DirectedProbe := true; out_msg.InitialRequestTime := in_msg.InitialRequestTime; @@ -789,7 +818,7 @@ } action(f_forwardWriteFromDma, "fw", desc="Forward requests") { - if (TBEs[address].NumPendingMsgs > 0) { + if (tbe.NumPendingMsgs > 0) { peek(dmaRequestQueue_in, DMARequestMsg) { enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { out_msg.Address := address; @@ -807,7 +836,7 @@ } action(f_forwardReadFromDma, "fr", desc="Forward requests") { - if (TBEs[address].NumPendingMsgs > 0) { + if (tbe.NumPendingMsgs > 0) { peek(dmaRequestQueue_in, DMARequestMsg) { enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { out_msg.Address := address; @@ -860,16 +889,16 @@ action(r_recordMemoryData, "rd", desc="record data from memory to TBE") { peek(memQueue_in, MemoryMsg) { - if (TBEs[address].CacheDirty == false) { - TBEs[address].DataBlk := in_msg.DataBlk; + if (tbe.CacheDirty == false) { + tbe.DataBlk := in_msg.DataBlk; } } } action(r_recordCacheData, "rc", desc="record data from cache response to TBE") { peek(responseToDir_in, ResponseMsg) { - TBEs[address].CacheDirty := true; - TBEs[address].DataBlk := in_msg.DataBlk; + tbe.CacheDirty := true; + tbe.DataBlk := in_msg.DataBlk; } } @@ -893,26 +922,26 @@ action(dwt_writeDmaDataFromTBE, "dwt", desc="DMA Write data to memory from TBE") { DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk); - getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk; + getDirectoryEntry(address).DataBlk := tbe.DataBlk; DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk); - getDirectoryEntry(address).DataBlk.copyPartial(TBEs[address].DmaDataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + getDirectoryEntry(address).DataBlk.copyPartial(tbe.DmaDataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len); DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk); } action(wdt_writeDataFromTBE, "wdt", desc="DMA Write data to memory from TBE") { DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk); - getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk; + getDirectoryEntry(address).DataBlk := tbe.DataBlk; DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk); } action(a_assertCacheData, "ac", desc="Assert that a cache provided the data") { - assert(TBEs[address].CacheDirty); + assert(tbe.CacheDirty); } action(ano_assertNotOwner, "ano", desc="Assert that request is not current owner") { if (probe_filter_enabled) { peek(requestQueue_in, RequestMsg) { - assert(getPfEntry(address).Owner != in_msg.Requestor); + assert(probeFilter_entry.Owner != in_msg.Requestor); } } } @@ -932,9 +961,9 @@ out_msg.Address := address; out_msg.Type := MemoryRequestType:MEMORY_WB; // first, initialize the data blk to the current version of system memory - out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.DataBlk := tbe.DataBlk; // then add the dma write data - out_msg.DataBlk.copyPartial(TBEs[address].DmaDataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + out_msg.DataBlk.copyPartial(tbe.DmaDataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len); DPRINTF(RubySlicc, "%s\n", out_msg); } }