diff options
Diffstat (limited to 'src/mem/protocol')
-rw-r--r-- | src/mem/protocol/MESI_CMP_directory-L1cache.sm | 230 | ||||
-rw-r--r-- | src/mem/protocol/MESI_CMP_directory-L2cache.sm | 308 | ||||
-rw-r--r-- | src/mem/protocol/MESI_CMP_directory-dir.sm | 49 | ||||
-rw-r--r-- | src/mem/protocol/MI_example-cache.sm | 112 | ||||
-rw-r--r-- | src/mem/protocol/MI_example-dir.sm | 72 | ||||
-rw-r--r-- | src/mem/protocol/MOESI_CMP_directory-L1cache.sm | 313 | ||||
-rw-r--r-- | src/mem/protocol/MOESI_CMP_directory-L2cache.sm | 570 | ||||
-rw-r--r-- | src/mem/protocol/MOESI_CMP_directory-dir.sm | 72 | ||||
-rw-r--r-- | src/mem/protocol/MOESI_CMP_directory-dma.sm | 40 | ||||
-rw-r--r-- | src/mem/protocol/MOESI_CMP_token-L1cache.sm | 573 | ||||
-rw-r--r-- | src/mem/protocol/MOESI_CMP_token-L2cache.sm | 325 | ||||
-rw-r--r-- | src/mem/protocol/MOESI_CMP_token-dir.sm | 119 | ||||
-rw-r--r-- | src/mem/protocol/MOESI_hammer-cache.sm | 424 | ||||
-rw-r--r-- | src/mem/protocol/MOESI_hammer-dir.sm | 279 | ||||
-rw-r--r-- | src/mem/protocol/RubySlicc_Types.sm | 7 |
15 files changed, 1981 insertions, 1512 deletions
diff --git a/src/mem/protocol/MESI_CMP_directory-L1cache.sm b/src/mem/protocol/MESI_CMP_directory-L1cache.sm index 50e0c3662..8744a7122 100644 --- a/src/mem/protocol/MESI_CMP_directory-L1cache.sm +++ b/src/mem/protocol/MESI_CMP_directory-L1cache.sm @@ -36,8 +36,6 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") int l1_response_latency = 2, int to_l2_latency = 1 { - - // NODE L1 CACHE // From this node's L1 cache TO the network // a local L1 -> this L2 bank, currently ordered with directory forwarded requests @@ -135,65 +133,63 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") int cache_state_to_int(State state); int l2_select_low_bit, default="RubySystem::getBlockSizeBits()"; + void set_cache_entry(AbstractCacheEntry a); + void unset_cache_entry(); + void set_tbe(TBE a); + void unset_tbe(); + // inclusive cache returns L1 entries only - Entry getL1CacheEntry(Address addr), return_by_ref="yes" { - if (L1DcacheMemory.isTagPresent(addr)) { - return static_cast(Entry, L1DcacheMemory[addr]); - } else { - return static_cast(Entry, L1IcacheMemory[addr]); + Entry getCacheEntry(Address addr), return_by_pointer="yes" { + Entry L1Dcache_entry := static_cast(Entry, "pointer", L1DcacheMemory[addr]); + if(is_valid(L1Dcache_entry)) { + return L1Dcache_entry; } + + Entry L1Icache_entry := static_cast(Entry, "pointer", L1IcacheMemory[addr]); + return L1Icache_entry; } - void changeL1Permission(Address addr, AccessPermission permission) { - if (L1DcacheMemory.isTagPresent(addr)) { - return L1DcacheMemory.changePermission(addr, permission); - } else if(L1IcacheMemory.isTagPresent(addr)) { - return L1IcacheMemory.changePermission(addr, permission); - } else { - error("cannot change permission, L1 block not present"); - } + Entry getL1DCacheEntry(Address addr), return_by_pointer="yes" { + Entry L1Dcache_entry := static_cast(Entry, "pointer", L1DcacheMemory[addr]); + return L1Dcache_entry; } - bool isL1CacheTagPresent(Address addr) { - return (L1DcacheMemory.isTagPresent(addr) || L1IcacheMemory.isTagPresent(addr)); + Entry getL1ICacheEntry(Address addr), return_by_pointer="yes" { + Entry L1Icache_entry := static_cast(Entry, "pointer", L1IcacheMemory[addr]); + return L1Icache_entry; } - State getState(Address addr) { -// if((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == true){ -// DEBUG_EXPR(id); -// DEBUG_EXPR(addr); -// } + State getState(TBE tbe, Entry cache_entry, Address addr) { assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); - if(L1_TBEs.isPresent(addr)) { - return L1_TBEs[addr].TBEState; - } else if (isL1CacheTagPresent(addr)) { - return getL1CacheEntry(addr).CacheState; + if(is_valid(tbe)) { + return tbe.TBEState; + } else if (is_valid(cache_entry)) { + return cache_entry.CacheState; } return State:NP; } - - void setState(Address addr, State state) { + void setState(TBE tbe, Entry cache_entry, Address addr, State state) { assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); // MUST CHANGE - if(L1_TBEs.isPresent(addr)) { - L1_TBEs[addr].TBEState := state; + if(is_valid(tbe)) { + tbe.TBEState := state; } - if (isL1CacheTagPresent(addr)) { - getL1CacheEntry(addr).CacheState := state; + if (is_valid(cache_entry)) { + cache_entry.CacheState := state; // Set permission if (state == State:I) { - changeL1Permission(addr, AccessPermission:Invalid); + cache_entry.changePermission(AccessPermission:Invalid); } else if (state == State:S || state == State:E) { - changeL1Permission(addr, AccessPermission:Read_Only); + cache_entry.changePermission(AccessPermission:Read_Only); } else if (state == State:M) { - changeL1Permission(addr, AccessPermission:Read_Write); + cache_entry.changePermission(AccessPermission:Read_Write); } else { - changeL1Permission(addr, AccessPermission:Busy); + cache_entry.changePermission(AccessPermission:Busy); } } } @@ -210,6 +206,9 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") } } + int getPendingAcks(TBE tbe) { + return tbe.pendingAcks; + } out_port(requestIntraChipL1Network_out, RequestMsg, requestFromL1Cache); out_port(responseIntraChipL1Network_out, ResponseMsg, responseFromL1Cache); @@ -220,27 +219,32 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") if (responseIntraChipL1Network_in.isReady()) { peek(responseIntraChipL1Network_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]; + if(in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) { - trigger(Event:Data_Exclusive, in_msg.Address); + trigger(Event:Data_Exclusive, in_msg.Address, cache_entry, tbe); } else if(in_msg.Type == CoherenceResponseType:DATA) { - if ( (getState(in_msg.Address) == State:IS || getState(in_msg.Address) == State:IS_I) && - machineIDToMachineType(in_msg.Sender) == MachineType:L1Cache ) { + if ((getState(tbe, cache_entry, in_msg.Address) == State:IS || + getState(tbe, cache_entry, in_msg.Address) == State:IS_I) && + machineIDToMachineType(in_msg.Sender) == MachineType:L1Cache) { - trigger(Event:DataS_fromL1, in_msg.Address); + trigger(Event:DataS_fromL1, in_msg.Address, cache_entry, tbe); - } else if ( (L1_TBEs[in_msg.Address].pendingAcks - in_msg.AckCount) == 0 ) { - trigger(Event:Data_all_Acks, in_msg.Address); + } else if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) { + trigger(Event:Data_all_Acks, in_msg.Address, cache_entry, tbe); } else { - trigger(Event:Data, in_msg.Address); + trigger(Event:Data, in_msg.Address, cache_entry, tbe); } } else if (in_msg.Type == CoherenceResponseType:ACK) { - if ( (L1_TBEs[in_msg.Address].pendingAcks - in_msg.AckCount) == 0 ) { - trigger(Event:Ack_all, in_msg.Address); + if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) { + trigger(Event:Ack_all, in_msg.Address, cache_entry, tbe); } else { - trigger(Event:Ack, in_msg.Address); + trigger(Event:Ack, in_msg.Address, cache_entry, tbe); } } else if (in_msg.Type == CoherenceResponseType:WB_ACK) { - trigger(Event:WB_Ack, in_msg.Address); + trigger(Event:WB_Ack, in_msg.Address, cache_entry, tbe); } else { error("Invalid L1 response type"); } @@ -253,15 +257,19 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") if(requestIntraChipL1Network_in.isReady()) { peek(requestIntraChipL1Network_in, RequestMsg, block_on="Address") { assert(in_msg.Destination.isElement(machineID)); + + Entry cache_entry := getCacheEntry(in_msg.Address); + TBE tbe := L1_TBEs[in_msg.Address]; + if (in_msg.Type == CoherenceRequestType:INV) { - trigger(Event:Inv, in_msg.Address); + trigger(Event:Inv, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestType:UPGRADE) { // upgrade transforms to GETX due to race - trigger(Event:Fwd_GETX, in_msg.Address); + trigger(Event:Fwd_GETX, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceRequestType:GETS) { - trigger(Event:Fwd_GETS, in_msg.Address); + trigger(Event:Fwd_GETS, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceRequestType:GET_INSTR) { - trigger(Event:Fwd_GET_INSTR, in_msg.Address); + trigger(Event:Fwd_GET_INSTR, in_msg.Address, cache_entry, tbe); } else { error("Invalid forwarded request type"); } @@ -280,40 +288,55 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") // ** INSTRUCTION ACCESS *** // Check to see if it is in the OTHER L1 - if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); + if (is_valid(L1Dcache_entry)) { // The block is in the wrong L1, put the request on the queue to the shared L2 - trigger(Event:L1_Replacement, in_msg.LineAddress); + trigger(Event:L1_Replacement, in_msg.LineAddress, + L1Dcache_entry, L1_TBEs[in_msg.LineAddress]); } - if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + + Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); + if (is_valid(L1Icache_entry)) { // The tag matches for the L1, so the L1 asks the L2 for it. - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, + L1Icache_entry, L1_TBEs[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 so let's see if the L2 has it - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, + L1Icache_entry, L1_TBEs[in_msg.LineAddress]); } else { // No room in the L1, so we need to make room in the L1 - trigger(Event:L1_Replacement, L1IcacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:L1_Replacement, L1IcacheMemory.cacheProbe(in_msg.LineAddress), + getL1ICacheEntry(L1IcacheMemory.cacheProbe(in_msg.LineAddress)), + L1_TBEs[L1IcacheMemory.cacheProbe(in_msg.LineAddress)]); } } } else { // *** DATA ACCESS *** - // Check to see if it is in the OTHER L1 - if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); + if (is_valid(L1Icache_entry)) { // The block is in the wrong L1, put the request on the queue to the shared L2 - trigger(Event:L1_Replacement, in_msg.LineAddress); + trigger(Event:L1_Replacement, in_msg.LineAddress, + L1Icache_entry, L1_TBEs[in_msg.LineAddress]); } - if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + + Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); + if (is_valid(L1Dcache_entry)) { // The tag matches for the L1, so the L1 ask the L2 for it - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, + L1Dcache_entry, L1_TBEs[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 let's see if the L2 has it - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, + L1Dcache_entry, L1_TBEs[in_msg.LineAddress]); } else { // No room in the L1, so we need to make room in the L1 - trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.LineAddress), + getL1DCacheEntry(L1DcacheMemory.cacheProbe(in_msg.LineAddress)), + L1_TBEs[L1DcacheMemory.cacheProbe(in_msg.LineAddress)]); } } } @@ -395,10 +418,11 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") action(d_sendDataToRequestor, "d", desc="send data to requestor") { peek(requestIntraChipL1Network_in, RequestMsg) { enqueue(responseIntraChipL1Network_out, ResponseMsg, latency=l1_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; - out_msg.DataBlk := getL1CacheEntry(address).DataBlk; - out_msg.Dirty := getL1CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); out_msg.MessageSize := MessageSizeType:Response_Data; @@ -408,10 +432,11 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") action(d2_sendDataToL2, "d2", desc="send data to the L2 cache because of M downgrade") { enqueue(responseIntraChipL1Network_out, ResponseMsg, latency=l1_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; - out_msg.DataBlk := getL1CacheEntry(address).DataBlk; - out_msg.Dirty := getL1CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.Sender := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, l2_select_low_bit, l2_select_num_bits)); @@ -422,10 +447,11 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") action(dt_sendDataToRequestor_fromTBE, "dt", desc="send data to requestor") { peek(requestIntraChipL1Network_in, RequestMsg) { enqueue(responseIntraChipL1Network_out, ResponseMsg, latency=l1_response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; - out_msg.DataBlk := L1_TBEs[address].DataBlk; - out_msg.Dirty := L1_TBEs[address].Dirty; + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); out_msg.MessageSize := MessageSizeType:Response_Data; @@ -435,10 +461,11 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") action(d2t_sendDataToL2_fromTBE, "d2t", desc="send data to the L2 cache") { enqueue(responseIntraChipL1Network_out, ResponseMsg, latency=l1_response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; - out_msg.DataBlk := L1_TBEs[address].DataBlk; - out_msg.Dirty := L1_TBEs[address].Dirty; + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; out_msg.Sender := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, l2_select_low_bit, l2_select_num_bits)); @@ -460,10 +487,11 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") action(f_sendDataToL2, "f", desc="send data to the L2 cache") { enqueue(responseIntraChipL1Network_out, ResponseMsg, latency=l1_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; - out_msg.DataBlk := getL1CacheEntry(address).DataBlk; - out_msg.Dirty := getL1CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.Sender := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, l2_select_low_bit, l2_select_num_bits)); @@ -473,10 +501,11 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") action(ft_sendDataToL2_fromTBE, "ft", desc="send data to the L2 cache") { enqueue(responseIntraChipL1Network_out, ResponseMsg, latency=l1_response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; - out_msg.DataBlk := L1_TBEs[address].DataBlk; - out_msg.Dirty := L1_TBEs[address].Dirty; + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; out_msg.Sender := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, l2_select_low_bit, l2_select_num_bits)); @@ -500,14 +529,15 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") action(g_issuePUTX, "g", desc="send data to the L2 cache") { enqueue(requestIntraChipL1Network_out, RequestMsg, latency=l1_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceRequestType:PUTX; - out_msg.DataBlk := getL1CacheEntry(address).DataBlk; - out_msg.Dirty := getL1CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.Requestor:= machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, l2_select_low_bit, l2_select_num_bits)); - if (getL1CacheEntry(address).Dirty) { + if (cache_entry.Dirty) { out_msg.MessageSize := MessageSizeType:Writeback_Data; } else { out_msg.MessageSize := MessageSizeType:Writeback_Control; @@ -541,25 +571,27 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") } } - - action(h_load_hit, "h", desc="If not prefetch, notify sequencer the load completed.") { - DPRINTF(RubySlicc, "%s\n", getL1CacheEntry(address).DataBlk); - sequencer.readCallback(address, getL1CacheEntry(address).DataBlk); + assert(is_valid(cache_entry)); + DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); + sequencer.readCallback(address, cache_entry.DataBlk); } action(hh_store_hit, "\h", desc="If not prefetch, notify sequencer that store completed.") { - DPRINTF(RubySlicc, "%s\n", getL1CacheEntry(address).DataBlk); - sequencer.writeCallback(address, getL1CacheEntry(address).DataBlk); - getL1CacheEntry(address).Dirty := true; + assert(is_valid(cache_entry)); + DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); + sequencer.writeCallback(address, cache_entry.DataBlk); + cache_entry.Dirty := true; } action(i_allocateTBE, "i", desc="Allocate TBE (isPrefetch=0, number of invalidates=0)") { check_allocate(L1_TBEs); + assert(is_valid(cache_entry)); L1_TBEs.allocate(address); - L1_TBEs[address].isPrefetch := false; - L1_TBEs[address].Dirty := getL1CacheEntry(address).Dirty; - L1_TBEs[address].DataBlk := getL1CacheEntry(address).DataBlk; + set_tbe(L1_TBEs[address]); + tbe.isPrefetch := false; + tbe.Dirty := cache_entry.Dirty; + tbe.DataBlk := cache_entry.DataBlk; } action(k_popMandatoryQueue, "k", desc="Pop mandatory queue.") { @@ -576,21 +608,24 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") action(s_deallocateTBE, "s", desc="Deallocate TBE") { L1_TBEs.deallocate(address); + unset_tbe(); } action(u_writeDataToL1Cache, "u", desc="Write data to cache") { peek(responseIntraChipL1Network_in, ResponseMsg) { - getL1CacheEntry(address).DataBlk := in_msg.DataBlk; - getL1CacheEntry(address).Dirty := in_msg.Dirty; + assert(is_valid(cache_entry)); + cache_entry.DataBlk := in_msg.DataBlk; + cache_entry.Dirty := in_msg.Dirty; } } action(q_updateAckCount, "q", desc="Update ack count") { peek(responseIntraChipL1Network_in, ResponseMsg) { - L1_TBEs[address].pendingAcks := L1_TBEs[address].pendingAcks - in_msg.AckCount; + assert(is_valid(tbe)); + tbe.pendingAcks := tbe.pendingAcks - in_msg.AckCount; APPEND_TRANSITION_COMMENT(in_msg.AckCount); APPEND_TRANSITION_COMMENT(" p: "); - APPEND_TRANSITION_COMMENT(L1_TBEs[address].pendingAcks); + APPEND_TRANSITION_COMMENT(tbe.pendingAcks); } } @@ -603,17 +638,18 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") } else { L1IcacheMemory.deallocate(address); } + unset_cache_entry(); } action(oo_allocateL1DCacheBlock, "\o", desc="Set L1 D-cache tag equal to tag of block B.") { - if (L1DcacheMemory.isTagPresent(address) == false) { - L1DcacheMemory.allocate(address, new Entry); + if (is_invalid(cache_entry)) { + set_cache_entry(L1DcacheMemory.allocate(address, new Entry)); } } action(pp_allocateL1ICacheBlock, "\p", desc="Set L1 I-cache tag equal to tag of block B.") { - if (L1IcacheMemory.isTagPresent(address) == false) { - L1IcacheMemory.allocate(address, new Entry); + if (is_invalid(cache_entry)) { + set_cache_entry(L1IcacheMemory.allocate(address, new Entry)); } } diff --git a/src/mem/protocol/MESI_CMP_directory-L2cache.sm b/src/mem/protocol/MESI_CMP_directory-L2cache.sm index cc8db3335..94dd949c5 100644 --- a/src/mem/protocol/MESI_CMP_directory-L2cache.sm +++ b/src/mem/protocol/MESI_CMP_directory-L2cache.sm @@ -38,7 +38,6 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") int l2_response_latency = 2, int to_l1_latency = 1 { - // L2 BANK QUEUES // From local bank of L2 cache TO the network MessageBuffer DirRequestFromL2Cache, network="To", virtual_network="0", ordered="false"; // this L2 bank -> Memory @@ -155,82 +154,80 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") TBETable L2_TBEs, template_hack="<L2Cache_TBE>"; - // inclusive cache, returns L2 entries only - Entry getL2CacheEntry(Address addr), return_by_ref="yes" { - return static_cast(Entry, L2cacheMemory[addr]); - } + void set_cache_entry(AbstractCacheEntry a); + void unset_cache_entry(); + void set_tbe(TBE a); + void unset_tbe(); - void changeL2Permission(Address addr, AccessPermission permission) { - if (L2cacheMemory.isTagPresent(addr)) { - return L2cacheMemory.changePermission(addr, permission); - } + // inclusive cache, returns L2 entries only + Entry getCacheEntry(Address addr), return_by_pointer="yes" { + return static_cast(Entry, "pointer", L2cacheMemory[addr]); } std::string getCoherenceRequestTypeStr(CoherenceRequestType type) { return CoherenceRequestType_to_string(type); } - bool isL2CacheTagPresent(Address addr) { - return (L2cacheMemory.isTagPresent(addr)); - } - - bool isOneSharerLeft(Address addr, MachineID requestor) { - assert(getL2CacheEntry(addr).Sharers.isElement(requestor)); - return (getL2CacheEntry(addr).Sharers.count() == 1); + bool isOneSharerLeft(Address addr, MachineID requestor, Entry cache_entry) { + assert(is_valid(cache_entry)); + assert(cache_entry.Sharers.isElement(requestor)); + return (cache_entry.Sharers.count() == 1); } - bool isSharer(Address addr, MachineID requestor) { - if (L2cacheMemory.isTagPresent(addr)) { - return getL2CacheEntry(addr).Sharers.isElement(requestor); + bool isSharer(Address addr, MachineID requestor, Entry cache_entry) { + if (is_valid(cache_entry)) { + return cache_entry.Sharers.isElement(requestor); } else { return false; } } - void addSharer(Address addr, MachineID requestor) { + void addSharer(Address addr, MachineID requestor, Entry cache_entry) { + assert(is_valid(cache_entry)); DPRINTF(RubySlicc, "machineID: %s, requestor: %s, address: %s\n", machineID, requestor, addr); - getL2CacheEntry(addr).Sharers.add(requestor); + cache_entry.Sharers.add(requestor); } - State getState(Address addr) { - if(L2_TBEs.isPresent(addr)) { - return L2_TBEs[addr].TBEState; - } else if (isL2CacheTagPresent(addr)) { - return getL2CacheEntry(addr).CacheState; + State getState(TBE tbe, Entry cache_entry, Address addr) { + if(is_valid(tbe)) { + return tbe.TBEState; + } else if (is_valid(cache_entry)) { + return cache_entry.CacheState; } return State:NP; } - std::string getStateStr(Address addr) { - return L2Cache_State_to_string(getState(addr)); + std::string getStateStr(TBE tbe, Entry cache_entry, Address addr) { + return L2Cache_State_to_string(getState(tbe, cache_entry, addr)); } // when is this called - void setState(Address addr, State state) { + void setState(TBE tbe, Entry cache_entry, Address addr, State state) { // MUST CHANGE - if (L2_TBEs.isPresent(addr)) { - L2_TBEs[addr].TBEState := state; + if (is_valid(tbe)) { + tbe.TBEState := state; } - if (isL2CacheTagPresent(addr)) { - getL2CacheEntry(addr).CacheState := state; + if (is_valid(cache_entry)) { + cache_entry.CacheState := state; // Set permission if (state == State:SS ) { - changeL2Permission(addr, AccessPermission:Read_Only); + cache_entry.changePermission(AccessPermission:Read_Only); } else if (state == State:M) { - changeL2Permission(addr, AccessPermission:Read_Write); + cache_entry.changePermission(AccessPermission:Read_Write); } else if (state == State:MT) { - changeL2Permission(addr, AccessPermission:Stale); + cache_entry.changePermission(AccessPermission:Stale); } else { - changeL2Permission(addr, AccessPermission:Busy); + cache_entry.changePermission(AccessPermission:Busy); } } } - Event L1Cache_request_type_to_event(CoherenceRequestType type, Address addr, MachineID requestor) { + Event L1Cache_request_type_to_event(CoherenceRequestType type, Address addr, + MachineID requestor, Entry cache_entry) { if(type == CoherenceRequestType:GETS) { return Event:L1_GETS; } else if(type == CoherenceRequestType:GET_INSTR) { @@ -238,13 +235,13 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") } else if (type == CoherenceRequestType:GETX) { return Event:L1_GETX; } else if (type == CoherenceRequestType:UPGRADE) { - if ( isL2CacheTagPresent(addr) && getL2CacheEntry(addr).Sharers.isElement(requestor) ) { + if ( is_valid(cache_entry) && cache_entry.Sharers.isElement(requestor) ) { return Event:L1_UPGRADE; } else { return Event:L1_GETX; } } else if (type == CoherenceRequestType:PUTX) { - if (isSharer(addr, requestor)) { + if (isSharer(addr, requestor, cache_entry)) { return Event:L1_PUTX; } else { return Event:L1_PUTX_old; @@ -255,6 +252,15 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") } } + int getPendingAcks(TBE tbe) { + return tbe.pendingAcks; + } + + bool isDirty(Entry cache_entry) { + assert(is_valid(cache_entry)); + return cache_entry.Dirty; + } + // ** OUT_PORTS ** out_port(L1RequestIntraChipL2Network_out, RequestMsg, L1RequestFromL2Cache); @@ -265,15 +271,17 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") in_port(L1unblockNetwork_in, ResponseMsg, unblockToL2Cache) { if(L1unblockNetwork_in.isReady()) { peek(L1unblockNetwork_in, ResponseMsg) { + Entry cache_entry := getCacheEntry(in_msg.Address); + TBE tbe := L2_TBEs[in_msg.Address]; DPRINTF(RubySlicc, "Addr: %s State: %s Sender: %s Type: %s Dest: %s\n", - in_msg.Address, getState(in_msg.Address), in_msg.Sender, - in_msg.Type, in_msg.Destination); + in_msg.Address, getState(tbe, cache_entry, in_msg.Address), + in_msg.Sender, in_msg.Type, in_msg.Destination); assert(in_msg.Destination.isElement(machineID)); if (in_msg.Type == CoherenceResponseType:EXCLUSIVE_UNBLOCK) { - trigger(Event:Exclusive_Unblock, in_msg.Address); + trigger(Event:Exclusive_Unblock, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:UNBLOCK) { - trigger(Event:Unblock, in_msg.Address); + trigger(Event:Unblock, in_msg.Address, cache_entry, tbe); } else { error("unknown unblock message"); } @@ -281,26 +289,27 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") } } - - // Response IntraChip L2 Network - response msg to this particular L2 bank in_port(responseIntraChipL2Network_in, ResponseMsg, responseToL2Cache) { if (responseIntraChipL2Network_in.isReady()) { peek(responseIntraChipL2Network_in, ResponseMsg) { // test wether it's from a local L1 or an off chip source assert(in_msg.Destination.isElement(machineID)); + Entry cache_entry := getCacheEntry(in_msg.Address); + TBE tbe := L2_TBEs[in_msg.Address]; + if(machineIDToMachineType(in_msg.Sender) == MachineType:L1Cache) { if(in_msg.Type == CoherenceResponseType:DATA) { if (in_msg.Dirty) { - trigger(Event:WB_Data, in_msg.Address); + trigger(Event:WB_Data, in_msg.Address, cache_entry, tbe); } else { - trigger(Event:WB_Data_clean, in_msg.Address); + trigger(Event:WB_Data_clean, in_msg.Address, cache_entry, tbe); } } else if (in_msg.Type == CoherenceResponseType:ACK) { - if ((L2_TBEs[in_msg.Address].pendingAcks - in_msg.AckCount) == 0) { - trigger(Event:Ack_all, in_msg.Address); + if ((getPendingAcks(tbe) - in_msg.AckCount) == 0) { + trigger(Event:Ack_all, in_msg.Address, cache_entry, tbe); } else { - trigger(Event:Ack, in_msg.Address); + trigger(Event:Ack, in_msg.Address, cache_entry, tbe); } } else { error("unknown message type"); @@ -308,11 +317,14 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") } else { // external message if(in_msg.Type == CoherenceResponseType:MEMORY_DATA) { - trigger(Event:Mem_Data, in_msg.Address); // L2 now has data and all off-chip acks + // L2 now has data and all off-chip acks + trigger(Event:Mem_Data, in_msg.Address, cache_entry, tbe); } else if(in_msg.Type == CoherenceResponseType:MEMORY_ACK) { - trigger(Event:Mem_Ack, in_msg.Address); // L2 now has data and all off-chip acks + // L2 now has data and all off-chip acks + trigger(Event:Mem_Ack, in_msg.Address, cache_entry, tbe); } else if(in_msg.Type == CoherenceResponseType:INV) { - trigger(Event:MEM_Inv, in_msg.Address); // L2 now has data and all off-chip acks + // L2 now has data and all off-chip acks + trigger(Event:MEM_Inv, in_msg.Address, cache_entry, tbe); } else { error("unknown message type"); } @@ -325,24 +337,36 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") in_port(L1RequestIntraChipL2Network_in, RequestMsg, L1RequestToL2Cache) { if(L1RequestIntraChipL2Network_in.isReady()) { peek(L1RequestIntraChipL2Network_in, RequestMsg) { + Entry cache_entry := getCacheEntry(in_msg.Address); + TBE tbe := L2_TBEs[in_msg.Address]; + DPRINTF(RubySlicc, "Addr: %s State: %s Req: %s Type: %s Dest: %s\n", - in_msg.Address, getState(in_msg.Address), in_msg.Requestor, - in_msg.Type, in_msg.Destination); + in_msg.Address, getState(tbe, cache_entry, in_msg.Address), + in_msg.Requestor, in_msg.Type, in_msg.Destination); + assert(machineIDToMachineType(in_msg.Requestor) == MachineType:L1Cache); assert(in_msg.Destination.isElement(machineID)); - if (L2cacheMemory.isTagPresent(in_msg.Address)) { + + if (is_valid(cache_entry)) { // The L2 contains the block, so proceeded with handling the request - trigger(L1Cache_request_type_to_event(in_msg.Type, in_msg.Address, in_msg.Requestor), in_msg.Address); + trigger(L1Cache_request_type_to_event(in_msg.Type, in_msg.Address, + in_msg.Requestor, cache_entry), + in_msg.Address, cache_entry, tbe); } else { if (L2cacheMemory.cacheAvail(in_msg.Address)) { // L2 does't have the line, but we have space for it in the L2 - trigger(L1Cache_request_type_to_event(in_msg.Type, in_msg.Address, in_msg.Requestor), in_msg.Address); + trigger(L1Cache_request_type_to_event(in_msg.Type, in_msg.Address, + in_msg.Requestor, cache_entry), + in_msg.Address, cache_entry, tbe); } else { // No room in the L2, so we need to make room before handling the request - if (getL2CacheEntry( L2cacheMemory.cacheProbe(in_msg.Address) ).Dirty ) { - trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address)); + Entry L2cache_entry := getCacheEntry(L2cacheMemory.cacheProbe(in_msg.Address)); + if (isDirty(L2cache_entry)) { + trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address), + L2cache_entry, L2_TBEs[L2cacheMemory.cacheProbe(in_msg.Address)]); } else { - trigger(Event:L2_Replacement_clean, L2cacheMemory.cacheProbe(in_msg.Address)); + trigger(Event:L2_Replacement_clean, L2cacheMemory.cacheProbe(in_msg.Address), + L2cache_entry, L2_TBEs[L2cacheMemory.cacheProbe(in_msg.Address)]); } } } @@ -368,10 +392,11 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") action(b_forwardRequestToExclusive, "b", desc="Forward request to the exclusive L1") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { enqueue(L1RequestIntraChipL2Network_out, RequestMsg, latency=to_l1_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := in_msg.Type; out_msg.Requestor := in_msg.Requestor; - out_msg.Destination.add(getL2CacheEntry(address).Exclusive); + out_msg.Destination.add(cache_entry.Exclusive); out_msg.MessageSize := MessageSizeType:Request_Control; } } @@ -379,12 +404,13 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") action(c_exclusiveReplacement, "c", desc="Send data to memory") { enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:MEMORY_DATA; out_msg.Sender := machineID; out_msg.Destination.add(map_Address_to_Directory(address)); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } } @@ -399,33 +425,33 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") } } - action(ct_exclusiveReplacementFromTBE, "ct", desc="Send data to memory") { enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:MEMORY_DATA; out_msg.Sender := machineID; out_msg.Destination.add(map_Address_to_Directory(address)); - out_msg.DataBlk := L2_TBEs[address].DataBlk; - out_msg.Dirty := L2_TBEs[address].Dirty; + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } } - action(d_sendDataToRequestor, "d", desc="Send data from cache to reqeustor") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; - out_msg.AckCount := 0 - getL2CacheEntry(address).Sharers.count(); - if (getL2CacheEntry(address).Sharers.isElement(in_msg.Requestor)) { + out_msg.AckCount := 0 - cache_entry.Sharers.count(); + if (cache_entry.Sharers.isElement(in_msg.Requestor)) { out_msg.AckCount := out_msg.AckCount + 1; } } @@ -435,16 +461,17 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") action(dd_sendExclusiveDataToRequestor, "dd", desc="Send data from cache to reqeustor") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; - out_msg.AckCount := 0 - getL2CacheEntry(address).Sharers.count(); - if (getL2CacheEntry(address).Sharers.isElement(in_msg.Requestor)) { + out_msg.AckCount := 0 - cache_entry.Sharers.count(); + if (cache_entry.Sharers.isElement(in_msg.Requestor)) { out_msg.AckCount := out_msg.AckCount + 1; } } @@ -454,12 +481,13 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") action(ds_sendSharedDataToRequestor, "ds", desc="Send data from cache to reqeustor") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; out_msg.AckCount := 0; } @@ -467,54 +495,59 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") } action(e_sendDataToGetSRequestors, "e", desc="Send data from cache to all GetS IDs") { - assert(L2_TBEs[address].L1_GetS_IDs.count() > 0); + assert(is_valid(tbe)); + assert(tbe.L1_GetS_IDs.count() > 0); enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=to_l1_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; - out_msg.Destination := L2_TBEs[address].L1_GetS_IDs; // internal nodes - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.Destination := tbe.L1_GetS_IDs; // internal nodes + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } } action(ex_sendExclusiveDataToGetSRequestors, "ex", desc="Send data from cache to all GetS IDs") { - assert(L2_TBEs[address].L1_GetS_IDs.count() == 1); + assert(is_valid(tbe)); + assert(tbe.L1_GetS_IDs.count() == 1); enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=to_l1_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; - out_msg.Destination := L2_TBEs[address].L1_GetS_IDs; // internal nodes - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.Destination := tbe.L1_GetS_IDs; // internal nodes + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } } - action(ee_sendDataToGetXRequestor, "ee", desc="Send data from cache to GetX ID") { enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=to_l1_latency) { + assert(is_valid(tbe)); + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; - out_msg.Destination.add(L2_TBEs[address].L1_GetX_ID); + out_msg.Destination.add(tbe.L1_GetX_ID); DPRINTF(RubySlicc, "%s\n", out_msg.Destination); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; DPRINTF(RubySlicc, "Address: %s, Destination: %s, DataBlock: %s\n", out_msg.Address, out_msg.Destination, out_msg.DataBlk); out_msg.MessageSize := MessageSizeType:Response_Data; } } - action(f_sendInvToSharers, "f", desc="invalidate sharers for L2 replacement") { enqueue(L1RequestIntraChipL2Network_out, RequestMsg, latency=to_l1_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceRequestType:INV; out_msg.Requestor := machineID; - out_msg.Destination := getL2CacheEntry(address).Sharers; + out_msg.Destination := cache_entry.Sharers; out_msg.MessageSize := MessageSizeType:Request_Control; } } @@ -522,23 +555,24 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") action(fw_sendFwdInvToSharers, "fw", desc="invalidate sharers for request") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { enqueue(L1RequestIntraChipL2Network_out, RequestMsg, latency=to_l1_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceRequestType:INV; out_msg.Requestor := in_msg.Requestor; - out_msg.Destination := getL2CacheEntry(address).Sharers; + out_msg.Destination := cache_entry.Sharers; out_msg.MessageSize := MessageSizeType:Request_Control; } } } - action(fwm_sendFwdInvToSharersMinusRequestor, "fwm", desc="invalidate sharers for request, requestor is sharer") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { enqueue(L1RequestIntraChipL2Network_out, RequestMsg, latency=to_l1_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceRequestType:INV; out_msg.Requestor := in_msg.Requestor; - out_msg.Destination := getL2CacheEntry(address).Sharers; + out_msg.Destination := cache_entry.Sharers; out_msg.Destination.remove(in_msg.Requestor); out_msg.MessageSize := MessageSizeType:Request_Control; } @@ -548,11 +582,13 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") // OTHER ACTIONS action(i_allocateTBE, "i", desc="Allocate TBE for internal/external request(isPrefetch=0, number of invalidates=0)") { check_allocate(L2_TBEs); + assert(is_valid(cache_entry)); L2_TBEs.allocate(address); - L2_TBEs[address].L1_GetS_IDs.clear(); - L2_TBEs[address].DataBlk := getL2CacheEntry(address).DataBlk; - L2_TBEs[address].Dirty := getL2CacheEntry(address).Dirty; - L2_TBEs[address].pendingAcks := getL2CacheEntry(address).Sharers.count(); + set_tbe(L2_TBEs[address]); + tbe.L1_GetS_IDs.clear(); + tbe.DataBlk := cache_entry.DataBlk; + tbe.Dirty := cache_entry.Dirty; + tbe.pendingAcks := cache_entry.Sharers.count(); } action(s_deallocateTBE, "s", desc="Deallocate external TBE") { @@ -567,56 +603,58 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") profileMsgDelay(0, L1unblockNetwork_in.dequeue_getDelayCycles()); } - action(o_popIncomingResponseQueue, "o", desc="Pop Incoming Response queue") { profileMsgDelay(3, responseIntraChipL2Network_in.dequeue_getDelayCycles()); } - action(m_writeDataToCache, "m", desc="Write data from response queue to cache") { peek(responseIntraChipL2Network_in, ResponseMsg) { - getL2CacheEntry(address).DataBlk := in_msg.DataBlk; - getL2CacheEntry(address).Dirty := in_msg.Dirty; + assert(is_valid(cache_entry)); + cache_entry.DataBlk := in_msg.DataBlk; + cache_entry.Dirty := in_msg.Dirty; } } action(mr_writeDataToCacheFromRequest, "mr", desc="Write data from response queue to cache") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { - getL2CacheEntry(address).DataBlk := in_msg.DataBlk; - getL2CacheEntry(address).Dirty := in_msg.Dirty; + assert(is_valid(cache_entry)); + cache_entry.DataBlk := in_msg.DataBlk; + cache_entry.Dirty := in_msg.Dirty; } } action(q_updateAck, "q", desc="update pending ack count") { peek(responseIntraChipL2Network_in, ResponseMsg) { - L2_TBEs[address].pendingAcks := L2_TBEs[address].pendingAcks - in_msg.AckCount; + assert(is_valid(tbe)); + tbe.pendingAcks := tbe.pendingAcks - in_msg.AckCount; APPEND_TRANSITION_COMMENT(in_msg.AckCount); APPEND_TRANSITION_COMMENT(" p: "); - APPEND_TRANSITION_COMMENT(L2_TBEs[address].pendingAcks); + APPEND_TRANSITION_COMMENT(tbe.pendingAcks); } } action(qq_writeDataToTBE, "\qq", desc="Write data from response queue to TBE") { peek(responseIntraChipL2Network_in, ResponseMsg) { - L2_TBEs[address].DataBlk := in_msg.DataBlk; - L2_TBEs[address].Dirty := in_msg.Dirty; + assert(is_valid(tbe)); + tbe.DataBlk := in_msg.DataBlk; + tbe.Dirty := in_msg.Dirty; } } - action(z_stall, "z", desc="Stall") { } - action(ss_recordGetSL1ID, "\s", desc="Record L1 GetS for load response") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { - L2_TBEs[address].L1_GetS_IDs.add(in_msg.Requestor); + assert(is_valid(tbe)); + tbe.L1_GetS_IDs.add(in_msg.Requestor); } } action(xx_recordGetXL1ID, "\x", desc="Record L1 GetX for store response") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { - L2_TBEs[address].L1_GetX_ID := in_msg.Requestor; + assert(is_valid(tbe)); + tbe.L1_GetX_ID := in_msg.Requestor; } } @@ -625,13 +663,14 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") } action(qq_allocateL2CacheBlock, "\q", desc="Set L2 cache tag equal to tag of block B.") { - if (L2cacheMemory.isTagPresent(address) == false) { - L2cacheMemory.allocate(address, new Entry); + if (is_invalid(cache_entry)) { + set_cache_entry(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(); } action(t_sendWBAck, "t", desc="Send writeback ACK") { @@ -649,13 +688,14 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") action(ts_sendInvAckToUpgrader, "ts", desc="Send ACK to upgrader") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=to_l1_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); out_msg.MessageSize := MessageSizeType:Response_Control; // upgrader doesn't get ack from itself, hence the + 1 - out_msg.AckCount := 0 - getL2CacheEntry(address).Sharers.count() + 1; + out_msg.AckCount := 0 - cache_entry.Sharers.count() + 1; } } } @@ -672,47 +712,50 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") } } - - action(nn_addSharer, "\n", desc="Add L1 sharer to list") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { - addSharer(address, in_msg.Requestor); - APPEND_TRANSITION_COMMENT( getL2CacheEntry(address).Sharers ); + assert(is_valid(cache_entry)); + addSharer(address, in_msg.Requestor, cache_entry); + APPEND_TRANSITION_COMMENT( cache_entry.Sharers ); } } action(nnu_addSharerFromUnblock, "\nu", desc="Add L1 sharer to list") { peek(L1unblockNetwork_in, ResponseMsg) { - addSharer(address, in_msg.Sender); + assert(is_valid(cache_entry)); + addSharer(address, in_msg.Sender, cache_entry); } } - action(kk_removeRequestSharer, "\k", desc="Remove L1 Request sharer from list") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { - getL2CacheEntry(address).Sharers.remove(in_msg.Requestor); + assert(is_valid(cache_entry)); + cache_entry.Sharers.remove(in_msg.Requestor); } } action(ll_clearSharers, "\l", desc="Remove all L1 sharers from list") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { - getL2CacheEntry(address).Sharers.clear(); + assert(is_valid(cache_entry)); + cache_entry.Sharers.clear(); } } action(mm_markExclusive, "\m", desc="set the exclusive owner") { peek(L1RequestIntraChipL2Network_in, RequestMsg) { - getL2CacheEntry(address).Sharers.clear(); - getL2CacheEntry(address).Exclusive := in_msg.Requestor; - addSharer(address, in_msg.Requestor); + assert(is_valid(cache_entry)); + cache_entry.Sharers.clear(); + cache_entry.Exclusive := in_msg.Requestor; + addSharer(address, in_msg.Requestor, cache_entry); } } action(mmu_markExclusiveFromUnblock, "\mu", desc="set the exclusive owner") { peek(L1unblockNetwork_in, ResponseMsg) { - getL2CacheEntry(address).Sharers.clear(); - getL2CacheEntry(address).Exclusive := in_msg.Sender; - addSharer(address, in_msg.Sender); + assert(is_valid(cache_entry)); + cache_entry.Sharers.clear(); + cache_entry.Exclusive := in_msg.Sender; + addSharer(address, in_msg.Sender, cache_entry); } } @@ -1060,6 +1103,3 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") o_popIncomingResponseQueue; } } - - - diff --git a/src/mem/protocol/MESI_CMP_directory-dir.sm b/src/mem/protocol/MESI_CMP_directory-dir.sm index 8fa8eedc5..0c3532fbf 100644 --- a/src/mem/protocol/MESI_CMP_directory-dir.sm +++ b/src/mem/protocol/MESI_CMP_directory-dir.sm @@ -106,14 +106,17 @@ machine(Directory, "MESI_CMP_filter_directory protocol") // ** OBJECTS ** TBETable TBEs, template_hack="<Directory_TBE>"; + + void set_tbe(TBE tbe); + void unset_tbe(); Entry getDirectoryEntry(Address addr), return_by_ref="yes" { return static_cast(Entry, directory[addr]); } - State getState(Address addr) { - if (TBEs.isPresent(addr)) { - return TBEs[addr].TBEState; + State getState(TBE tbe, Address addr) { + if (is_valid(tbe)) { + return tbe.TBEState; } else if (directory.isPresent(addr)) { return getDirectoryEntry(addr).DirectoryState; } else { @@ -122,10 +125,10 @@ machine(Directory, "MESI_CMP_filter_directory protocol") } - void setState(Address addr, State state) { + void setState(TBE tbe, Address addr, State state) { - if (TBEs.isPresent(addr)) { - TBEs[addr].TBEState := state; + if (is_valid(tbe)) { + tbe.TBEState := state; } if (directory.isPresent(addr)) { @@ -161,11 +164,13 @@ machine(Directory, "MESI_CMP_filter_directory protocol") peek(requestNetwork_in, RequestMsg) { assert(in_msg.Destination.isElement(machineID)); if (isGETRequest(in_msg.Type)) { - trigger(Event:Fetch, in_msg.Address); + trigger(Event:Fetch, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:DMA_READ) { - trigger(Event:DMA_READ, makeLineAddress(in_msg.Address)); + trigger(Event:DMA_READ, makeLineAddress(in_msg.Address), + TBEs[makeLineAddress(in_msg.Address)]); } else if (in_msg.Type == CoherenceRequestType:DMA_WRITE) { - trigger(Event:DMA_WRITE, makeLineAddress(in_msg.Address)); + trigger(Event:DMA_WRITE, makeLineAddress(in_msg.Address), + TBEs[makeLineAddress(in_msg.Address)]); } else { DPRINTF(RubySlicc, "%s\n", in_msg); error("Invalid message"); @@ -179,9 +184,9 @@ machine(Directory, "MESI_CMP_filter_directory protocol") peek(responseNetwork_in, ResponseMsg) { assert(in_msg.Destination.isElement(machineID)); if (in_msg.Type == CoherenceResponseType:MEMORY_DATA) { - trigger(Event:Data, in_msg.Address); + trigger(Event:Data, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:ACK) { - trigger(Event:CleanReplacement, in_msg.Address); + trigger(Event:CleanReplacement, in_msg.Address, TBEs[in_msg.Address]); } else { DPRINTF(RubySlicc, "%s\n", in_msg.Type); error("Invalid message"); @@ -195,9 +200,9 @@ machine(Directory, "MESI_CMP_filter_directory protocol") if (memQueue_in.isReady()) { peek(memQueue_in, MemoryMsg) { if (in_msg.Type == MemoryRequestType:MEMORY_READ) { - trigger(Event:Memory_Data, in_msg.Address); + trigger(Event:Memory_Data, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { - trigger(Event:Memory_Ack, in_msg.Address); + trigger(Event:Memory_Ack, in_msg.Address, TBEs[in_msg.Address]); } else { DPRINTF(RubySlicc, "%s\n", in_msg.Type); error("Invalid message"); @@ -412,15 +417,17 @@ machine(Directory, "MESI_CMP_filter_directory protocol") action(v_allocateTBE, "v", desc="Allocate TBE") { peek(requestNetwork_in, RequestMsg) { TBEs.allocate(address); - TBEs[address].DataBlk := in_msg.DataBlk; - TBEs[address].PhysicalAddress := in_msg.Address; - TBEs[address].Len := in_msg.Len; + set_tbe(TBEs[address]); + tbe.DataBlk := in_msg.DataBlk; + tbe.PhysicalAddress := in_msg.Address; + tbe.Len := in_msg.Len; } } action(dwt_writeDMADataFromTBE, "dwt", desc="DMA Write data to memory from TBE") { - //getDirectoryEntry(address).DataBlk.copyPartial(TBEs[address].DataBlk, TBEs[address].Offset, TBEs[address].Len); - getDirectoryEntry(address).DataBlk.copyPartial(TBEs[address].DataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + assert(is_valid(tbe)); + //getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, tbe.Offset, tbe.Len); + getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len); } @@ -429,12 +436,13 @@ machine(Directory, "MESI_CMP_filter_directory protocol") action(qw_queueMemoryWBRequest_partialTBE, "qwt", desc="Queue off-chip writeback request") { peek(responseNetwork_in, ResponseMsg) { enqueue(memQueue_out, MemoryMsg, latency=to_mem_ctrl_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := MemoryRequestType:MEMORY_WB; out_msg.OriginalRequestorMachId := in_msg.Sender; //out_msg.DataBlk := in_msg.DataBlk; - //out_msg.DataBlk.copyPartial(TBEs[address].DataBlk, TBEs[address].Offset, TBEs[address].Len); - out_msg.DataBlk.copyPartial(TBEs[address].DataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + //out_msg.DataBlk.copyPartial(tbe.DataBlk, tbe.Offset, tbe.Len); + out_msg.DataBlk.copyPartial(tbe.DataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len); out_msg.MessageSize := in_msg.MessageSize; //out_msg.Prefetch := in_msg.Prefetch; @@ -446,6 +454,7 @@ machine(Directory, "MESI_CMP_filter_directory protocol") action(w_deallocateTBE, "w", desc="Deallocate TBE") { TBEs.deallocate(address); + unset_tbe(); } diff --git a/src/mem/protocol/MI_example-cache.sm b/src/mem/protocol/MI_example-cache.sm index 8232e93e1..96b7ab826 100644 --- a/src/mem/protocol/MI_example-cache.sm +++ b/src/mem/protocol/MI_example-cache.sm @@ -73,7 +73,15 @@ machine(L1Cache, "MI Example L1 Cache") TBETable TBEs, template_hack="<L1Cache_TBE>"; + // PROTOTYPES + void set_cache_entry(AbstractCacheEntry a); + void unset_cache_entry(); + void set_tbe(TBE b); + void unset_tbe(); + Entry getCacheEntry(Address address), return_by_pointer="yes" { + return static_cast(Entry, "pointer", cacheMemory.lookup(address)); + } // FUNCTIONS Event mandatory_request_type_to_event(CacheRequestType type) { @@ -88,35 +96,31 @@ machine(L1Cache, "MI Example L1 Cache") } } - Entry getCacheEntry(Address addr), return_by_ref="yes" { - return static_cast(Entry, cacheMemory[addr]); - } - - State getState(Address addr) { + State getState(TBE tbe, Entry cache_entry, Address addr) { - if (TBEs.isPresent(addr)) { - return TBEs[addr].TBEState; + if (is_valid(tbe)) { + return tbe.TBEState; } - else if (cacheMemory.isTagPresent(addr)) { - return getCacheEntry(addr).CacheState; + else if (is_valid(cache_entry)) { + return cache_entry.CacheState; } else { return State:I; } } - void setState(Address addr, State state) { + void setState(TBE tbe, Entry cache_entry, Address addr, State state) { - if (TBEs.isPresent(addr)) { - TBEs[addr].TBEState := state; + if (is_valid(tbe)) { + tbe.TBEState := state; } - if (cacheMemory.isTagPresent(addr)) { - getCacheEntry(addr).CacheState := state; + if (is_valid(cache_entry)) { + cache_entry.CacheState := state; if (state == State:M) { - cacheMemory.changePermission(addr, AccessPermission:Read_Write); + cache_entry.changePermission(AccessPermission:Read_Write); } else { - cacheMemory.changePermission(addr, AccessPermission:Invalid); + cache_entry.changePermission(AccessPermission:Invalid); } } } @@ -141,17 +145,21 @@ machine(L1Cache, "MI Example L1 Cache") in_port(forwardRequestNetwork_in, RequestMsg, forwardToCache) { if (forwardRequestNetwork_in.isReady()) { peek(forwardRequestNetwork_in, RequestMsg, block_on="Address") { + + Entry cache_entry := getCacheEntry(in_msg.Address); + TBE tbe := TBEs[in_msg.Address]; + if (in_msg.Type == CoherenceRequestType:GETX) { - trigger(Event:Fwd_GETX, in_msg.Address); + trigger(Event:Fwd_GETX, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceRequestType:WB_ACK) { - trigger(Event:Writeback_Ack, in_msg.Address); + trigger(Event:Writeback_Ack, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceRequestType:WB_NACK) { - trigger(Event:Writeback_Nack, in_msg.Address); + trigger(Event:Writeback_Nack, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceRequestType:INV) { - trigger(Event:Inv, in_msg.Address); + trigger(Event:Inv, in_msg.Address, cache_entry, tbe); } else { error("Unexpected message"); @@ -163,8 +171,12 @@ machine(L1Cache, "MI Example L1 Cache") in_port(responseNetwork_in, ResponseMsg, responseToCache) { if (responseNetwork_in.isReady()) { peek(responseNetwork_in, ResponseMsg, block_on="Address") { + + Entry cache_entry := getCacheEntry(in_msg.Address); + TBE tbe := TBEs[in_msg.Address]; + if (in_msg.Type == CoherenceResponseType:DATA) { - trigger(Event:Data, in_msg.Address); + trigger(Event:Data, in_msg.Address, cache_entry, tbe); } else { error("Unexpected message"); @@ -178,14 +190,17 @@ machine(L1Cache, "MI Example L1 Cache") if (mandatoryQueue_in.isReady()) { peek(mandatoryQueue_in, CacheMsg, block_on="LineAddress") { - - if (cacheMemory.isTagPresent(in_msg.LineAddress) == false && + Entry cache_entry := getCacheEntry(in_msg.LineAddress); + if (is_invalid(cache_entry) && cacheMemory.cacheAvail(in_msg.LineAddress) == false ) { // make room for the block - trigger(Event:Replacement, cacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:Replacement, cacheMemory.cacheProbe(in_msg.LineAddress), + getCacheEntry(cacheMemory.cacheProbe(in_msg.LineAddress)), + TBEs[cacheMemory.cacheProbe(in_msg.LineAddress)]); } else { - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, + cache_entry, TBEs[in_msg.LineAddress]); } } } @@ -205,11 +220,12 @@ machine(L1Cache, "MI Example L1 Cache") action(b_issuePUT, "b", desc="Issue a PUT request") { enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceRequestType:PUTX; out_msg.Requestor := machineID; out_msg.Destination.add(map_Address_to_Directory(address)); - out_msg.DataBlk := getCacheEntry(address).DataBlk; + out_msg.DataBlk := cache_entry.DataBlk; out_msg.MessageSize := MessageSizeType:Data; } } @@ -218,11 +234,12 @@ machine(L1Cache, "MI Example L1 Cache") action(e_sendData, "e", desc="Send data from cache to requestor") { peek(forwardRequestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getCacheEntry(address).DataBlk; + out_msg.DataBlk := cache_entry.DataBlk; out_msg.MessageSize := MessageSizeType:Response_Data; } } @@ -231,26 +248,28 @@ machine(L1Cache, "MI Example L1 Cache") action(ee_sendDataFromTBE, "\e", desc="Send data from TBE to requestor") { peek(forwardRequestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.DataBlk := tbe.DataBlk; out_msg.MessageSize := MessageSizeType:Response_Data; } } } - action(i_allocateL1CacheBlock, "i", desc="Allocate a cache block") { - if (cacheMemory.isTagPresent(address) == false) { - cacheMemory.allocate(address, new Entry); + if (is_valid(cache_entry)) { + } else { + set_cache_entry(cacheMemory.allocate(address, new Entry)); } } action(h_deallocateL1CacheBlock, "h", desc="deallocate a cache block") { - if (cacheMemory.isTagPresent(address) == true) { + if (is_valid(cache_entry)) { cacheMemory.deallocate(address); + unset_cache_entry(); } } @@ -273,55 +292,64 @@ machine(L1Cache, "MI Example L1 Cache") } action(r_load_hit, "r", desc="Notify sequencer the load completed.") { - DPRINTF(RubySlicc,"%s\n", getCacheEntry(address).DataBlk); + assert(is_valid(cache_entry)); + DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk); sequencer.readCallback(address, GenericMachineType:L1Cache, - getCacheEntry(address).DataBlk); + cache_entry.DataBlk); } action(rx_load_hit, "rx", desc="External load completed.") { peek(responseNetwork_in, ResponseMsg) { - DPRINTF(RubySlicc,"%s\n", getCacheEntry(address).DataBlk); + assert(is_valid(cache_entry)); + DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk); sequencer.readCallback(address, getNondirectHitMachType(in_msg.Sender), - getCacheEntry(address).DataBlk); + cache_entry.DataBlk); } } action(s_store_hit, "s", desc="Notify sequencer that store completed.") { - DPRINTF(RubySlicc,"%s\n", getCacheEntry(address).DataBlk); + assert(is_valid(cache_entry)); + DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk); sequencer.writeCallback(address, GenericMachineType:L1Cache, - getCacheEntry(address).DataBlk); + cache_entry.DataBlk); } action(sx_store_hit, "sx", desc="External store completed.") { peek(responseNetwork_in, ResponseMsg) { - DPRINTF(RubySlicc,"%s\n", getCacheEntry(address).DataBlk); + assert(is_valid(cache_entry)); + DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk); sequencer.writeCallback(address, getNondirectHitMachType(in_msg.Sender), - getCacheEntry(address).DataBlk); + cache_entry.DataBlk); } } action(u_writeDataToCache, "u", desc="Write data to the cache") { peek(responseNetwork_in, ResponseMsg) { - getCacheEntry(address).DataBlk := in_msg.DataBlk; + assert(is_valid(cache_entry)); + cache_entry.DataBlk := in_msg.DataBlk; } } action(v_allocateTBE, "v", desc="Allocate TBE") { TBEs.allocate(address); + set_tbe(TBEs[address]); } action(w_deallocateTBE, "w", desc="Deallocate TBE") { TBEs.deallocate(address); + unset_tbe(); } action(x_copyDataFromCacheToTBE, "x", desc="Copy data from cache to TBE") { - TBEs[address].DataBlk := getCacheEntry(address).DataBlk; + assert(is_valid(cache_entry)); + assert(is_valid(tbe)); + tbe.DataBlk := cache_entry.DataBlk; } action(z_stall, "z", desc="stall") { diff --git a/src/mem/protocol/MI_example-dir.sm b/src/mem/protocol/MI_example-dir.sm index dfb95aedd..30720e433 100644 --- a/src/mem/protocol/MI_example-dir.sm +++ b/src/mem/protocol/MI_example-dir.sm @@ -76,13 +76,16 @@ machine(Directory, "Directory protocol") // ** OBJECTS ** TBETable TBEs, template_hack="<Directory_TBE>"; + void set_tbe(TBE b); + void unset_tbe(); + Entry getDirectoryEntry(Address addr), return_by_ref="yes" { return static_cast(Entry, directory[addr]); } - State getState(Address addr) { - if (TBEs.isPresent(addr)) { - return TBEs[addr].TBEState; + State getState(TBE tbe, Address addr) { + if (is_valid(tbe)) { + return tbe.TBEState; } else if (directory.isPresent(addr)) { return getDirectoryEntry(addr).DirectoryState; } else { @@ -90,10 +93,10 @@ machine(Directory, "Directory protocol") } } - void setState(Address addr, State state) { + void setState(TBE tbe, Address addr, State state) { - if (TBEs.isPresent(addr)) { - TBEs[addr].TBEState := state; + if (is_valid(tbe)) { + tbe.TBEState := state; } if (directory.isPresent(addr)) { @@ -126,10 +129,11 @@ machine(Directory, "Directory protocol") in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir) { if (dmaRequestQueue_in.isReady()) { peek(dmaRequestQueue_in, DMARequestMsg) { + TBE tbe := TBEs[in_msg.LineAddress]; if (in_msg.Type == DMARequestType:READ) { - trigger(Event:DMA_READ, in_msg.LineAddress); + trigger(Event:DMA_READ, in_msg.LineAddress, tbe); } else if (in_msg.Type == DMARequestType:WRITE) { - trigger(Event:DMA_WRITE, in_msg.LineAddress); + trigger(Event:DMA_WRITE, in_msg.LineAddress, tbe); } else { error("Invalid message"); } @@ -140,15 +144,16 @@ machine(Directory, "Directory protocol") in_port(requestQueue_in, RequestMsg, requestToDir) { if (requestQueue_in.isReady()) { peek(requestQueue_in, RequestMsg) { + TBE tbe := TBEs[in_msg.Address]; if (in_msg.Type == CoherenceRequestType:GETS) { - trigger(Event:GETS, in_msg.Address); + trigger(Event:GETS, in_msg.Address, tbe); } else if (in_msg.Type == CoherenceRequestType:GETX) { - trigger(Event:GETX, in_msg.Address); + trigger(Event:GETX, in_msg.Address, tbe); } else if (in_msg.Type == CoherenceRequestType:PUTX) { if (getDirectoryEntry(in_msg.Address).Owner.isElement(in_msg.Requestor)) { - trigger(Event:PUTX, in_msg.Address); + trigger(Event:PUTX, in_msg.Address, tbe); } else { - trigger(Event:PUTX_NotOwner, in_msg.Address); + trigger(Event:PUTX_NotOwner, in_msg.Address, tbe); } } else { error("Invalid message"); @@ -162,10 +167,11 @@ machine(Directory, "Directory protocol") in_port(memQueue_in, MemoryMsg, memBuffer) { if (memQueue_in.isReady()) { peek(memQueue_in, MemoryMsg) { + TBE tbe := TBEs[in_msg.Address]; if (in_msg.Type == MemoryRequestType:MEMORY_READ) { - trigger(Event:Memory_Data, in_msg.Address); + trigger(Event:Memory_Data, in_msg.Address, tbe); } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { - trigger(Event:Memory_Ack, in_msg.Address); + trigger(Event:Memory_Ack, in_msg.Address, tbe); } else { DPRINTF(RubySlicc,"%s\n", in_msg.Type); error("Invalid message"); @@ -232,11 +238,12 @@ machine(Directory, "Directory protocol") action(dr_sendDMAData, "dr", desc="Send Data to DMA controller from directory") { peek(memQueue_in, MemoryMsg) { enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + assert(is_valid(tbe)); out_msg.PhysicalAddress := address; out_msg.LineAddress := address; out_msg.Type := DMAResponseType:DATA; out_msg.DataBlk := in_msg.DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be - out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.Destination.add(tbe.DmaRequestor); out_msg.MessageSize := MessageSizeType:Response_Data; } } @@ -247,11 +254,12 @@ machine(Directory, "Directory protocol") action(drp_sendDMAData, "drp", desc="Send Data to DMA controller from incoming PUTX") { peek(requestQueue_in, RequestMsg) { enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + assert(is_valid(tbe)); out_msg.PhysicalAddress := address; out_msg.LineAddress := address; out_msg.Type := DMAResponseType:DATA; out_msg.DataBlk := in_msg.DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be - out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.Destination.add(tbe.DmaRequestor); out_msg.MessageSize := MessageSizeType:Response_Data; } } @@ -259,10 +267,11 @@ machine(Directory, "Directory protocol") action(da_sendDMAAck, "da", desc="Send Ack to DMA controller") { enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + assert(is_valid(tbe)); 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; } } @@ -320,35 +329,40 @@ machine(Directory, "Directory protocol") } action(dwt_writeDMADataFromTBE, "dwt", desc="DMA Write data to memory from TBE") { - getDirectoryEntry(address).DataBlk.copyPartial(TBEs[address].DataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + assert(is_valid(tbe)); + getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len); } action(v_allocateTBE, "v", desc="Allocate TBE") { peek(dmaRequestQueue_in, DMARequestMsg) { TBEs.allocate(address); - TBEs[address].DataBlk := in_msg.DataBlk; - TBEs[address].PhysicalAddress := in_msg.PhysicalAddress; - TBEs[address].Len := in_msg.Len; - TBEs[address].DmaRequestor := in_msg.Requestor; + set_tbe(TBEs[address]); + tbe.DataBlk := in_msg.DataBlk; + tbe.PhysicalAddress := in_msg.PhysicalAddress; + tbe.Len := in_msg.Len; + tbe.DmaRequestor := in_msg.Requestor; } } action(r_allocateTbeForDmaRead, "\r", desc="Allocate TBE for DMA Read") { peek(dmaRequestQueue_in, DMARequestMsg) { TBEs.allocate(address); - TBEs[address].DmaRequestor := in_msg.Requestor; + set_tbe(TBEs[address]); + tbe.DmaRequestor := in_msg.Requestor; } } action(v_allocateTBEFromRequestNet, "\v", desc="Allocate TBE") { peek(requestQueue_in, RequestMsg) { TBEs.allocate(address); - TBEs[address].DataBlk := in_msg.DataBlk; + set_tbe(TBEs[address]); + tbe.DataBlk := in_msg.DataBlk; } } action(w_deallocateTBE, "w", desc="Deallocate TBE") { TBEs.deallocate(address); + unset_tbe(); } action(z_recycleRequestQueue, "z", desc="recycle request queue") { @@ -407,12 +421,13 @@ machine(Directory, "Directory protocol") action(qw_queueMemoryWBRequest_partialTBE, "qwt", desc="Queue off-chip writeback request") { peek(requestQueue_in, RequestMsg) { enqueue(memQueue_out, MemoryMsg, latency="1") { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := MemoryRequestType:MEMORY_WB; out_msg.OriginalRequestorMachId := in_msg.Requestor; // get incoming data // out_msg.DataBlk := in_msg.DataBlk; - out_msg.DataBlk.copyPartial(TBEs[address].DataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + out_msg.DataBlk.copyPartial(tbe.DataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len); out_msg.MessageSize := in_msg.MessageSize; //out_msg.Prefetch := in_msg.Prefetch; @@ -445,9 +460,10 @@ machine(Directory, "Directory protocol") action(w_writeDataToMemoryFromTBE, "\w", desc="Write date to directory memory from TBE") { //getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk; - getDirectoryEntry(address).DataBlk.copyPartial(TBEs[address].DataBlk, - addressOffset(TBEs[address].PhysicalAddress), - TBEs[address].Len); + assert(is_valid(tbe)); + getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, + addressOffset(tbe.PhysicalAddress), + tbe.Len); } diff --git a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm index 31de269a9..4082f23c9 100644 --- a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm +++ b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm @@ -136,6 +136,10 @@ machine(L1Cache, "Directory protocol") bool isPresent(Address); } + void set_cache_entry(AbstractCacheEntry b); + void unset_cache_entry(); + void set_tbe(TBE b); + void unset_tbe(); MessageBuffer mandatoryQueue, ordered="false", abstract_chip_ptr="true"; @@ -143,102 +147,69 @@ machine(L1Cache, "Directory protocol") TimerTable useTimerTable; int l2_select_low_bit, default="RubySystem::getBlockSizeBits()"; - Entry getCacheEntry(Address addr), return_by_ref="yes" { - if (L1DcacheMemory.isTagPresent(addr)) { - return static_cast(Entry, L1DcacheMemory[addr]); - } else { - return static_cast(Entry, L1IcacheMemory[addr]); + Entry getCacheEntry(Address addr), return_by_pointer="yes" { + Entry L1Dcache_entry := static_cast(Entry, "pointer", L1DcacheMemory.lookup(addr)); + if(is_valid(L1Dcache_entry)) { + return L1Dcache_entry; } - } - void changePermission(Address addr, AccessPermission permission) { - if (L1DcacheMemory.isTagPresent(addr)) { - return L1DcacheMemory.changePermission(addr, permission); - } else { - return L1IcacheMemory.changePermission(addr, permission); - } + Entry L1Icache_entry := static_cast(Entry, "pointer", L1IcacheMemory.lookup(addr)); + return L1Icache_entry; } - bool isCacheTagPresent(Address addr) { - return (L1DcacheMemory.isTagPresent(addr) || L1IcacheMemory.isTagPresent(addr)); + Entry getL1DCacheEntry(Address addr), return_by_pointer="yes" { + return static_cast(Entry, "pointer", L1DcacheMemory.lookup(addr)); } - State getState(Address addr) { - assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); + Entry getL1ICacheEntry(Address addr), return_by_pointer="yes" { + return static_cast(Entry, "pointer", L1IcacheMemory.lookup(addr)); + } - if(TBEs.isPresent(addr)) { - return TBEs[addr].TBEState; - } else if (isCacheTagPresent(addr)) { - return getCacheEntry(addr).CacheState; + State getState(TBE tbe, Entry cache_entry, Address addr) { + if(is_valid(tbe)) { + return tbe.TBEState; + } else if (is_valid(cache_entry)) { + return cache_entry.CacheState; } return State:I; } - void setState(Address addr, State state) { + void setState(TBE tbe, Entry cache_entry, Address addr, State state) { assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); - if (TBEs.isPresent(addr)) { - TBEs[addr].TBEState := state; + if (is_valid(tbe)) { + tbe.TBEState := state; } - if (isCacheTagPresent(addr)) { - if ( ((getCacheEntry(addr).CacheState != State:M) && (state == State:M)) || - ((getCacheEntry(addr).CacheState != State:MM) && (state == State:MM)) || - ((getCacheEntry(addr).CacheState != State:S) && (state == State:S)) || - ((getCacheEntry(addr).CacheState != State:O) && (state == State:O)) ) { + if (is_valid(cache_entry)) { + if ( ((cache_entry.CacheState != State:M) && (state == State:M)) || + ((cache_entry.CacheState != State:MM) && (state == State:MM)) || + ((cache_entry.CacheState != State:S) && (state == State:S)) || + ((cache_entry.CacheState != State:O) && (state == State:O)) ) { - getCacheEntry(addr).CacheState := state; + cache_entry.CacheState := state; sequencer.checkCoherence(addr); } else { - getCacheEntry(addr).CacheState := state; + 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) || (state == State:M_W) || (state == State:SM) || (state == State:OM)) { - changePermission(addr, AccessPermission:Read_Only); + cache_entry.changePermission(AccessPermission:Read_Only); } else { - changePermission(addr, AccessPermission:Invalid); + cache_entry.changePermission(AccessPermission:Invalid); } } } - bool isBlockExclusive(Address addr) { - - if (isCacheTagPresent(addr)) { - if ( (getCacheEntry(addr).CacheState == State:M) || (getCacheEntry(addr).CacheState == State:MM) - || (getCacheEntry(addr).CacheState == State:MI) || (getCacheEntry(addr).CacheState == State:MM_W) - ) { - return true; - } - } - - return false; - } - - bool isBlockShared(Address addr) { - if (isCacheTagPresent(addr)) { - if ( (getCacheEntry(addr).CacheState == State:S) || (getCacheEntry(addr).CacheState == State:O) - || (getCacheEntry(addr).CacheState == State:SM) - || (getCacheEntry(addr).CacheState == State:OI) - || (getCacheEntry(addr).CacheState == State:SI) - || (getCacheEntry(addr).CacheState == State:OM) - ) { - return true; - } - } - - return false; - } - - Event mandatory_request_type_to_event(CacheRequestType type) { if (type == CacheRequestType:LD) { return Event:Load; @@ -265,7 +236,9 @@ machine(L1Cache, "Directory protocol") // Use Timer in_port(useTimerTable_in, Address, useTimerTable) { if (useTimerTable_in.isReady()) { - trigger(Event:Use_Timeout, useTimerTable.readyAddress()); + trigger(Event:Use_Timeout, useTimerTable.readyAddress(), + getCacheEntry(useTimerTable.readyAddress()), + TBEs[useTimerTable.readyAddress()]); } } @@ -283,7 +256,8 @@ machine(L1Cache, "Directory protocol") if (triggerQueue_in.isReady()) { peek(triggerQueue_in, TriggerMsg) { if (in_msg.Type == TriggerType:ALL_ACKS) { - trigger(Event:All_acks, in_msg.Address); + trigger(Event:All_acks, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else { error("Unexpected message"); } @@ -299,24 +273,33 @@ machine(L1Cache, "Directory protocol") peek(requestNetwork_in, RequestMsg, block_on="Address") { assert(in_msg.Destination.isElement(machineID)); DPRINTF(RubySlicc, "L1 received: %s\n", in_msg.Type); -if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestType:DMA_WRITE) { + + if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestType:DMA_WRITE) { if (in_msg.Requestor == machineID && in_msg.RequestorMachine == MachineType:L1Cache) { - trigger(Event:Own_GETX, in_msg.Address); + trigger(Event:Own_GETX, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else { - trigger(Event:Fwd_GETX, in_msg.Address); + trigger(Event:Fwd_GETX, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } } else if (in_msg.Type == CoherenceRequestType:GETS) { - trigger(Event:Fwd_GETS, in_msg.Address); + trigger(Event:Fwd_GETS, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:DMA_READ) { - trigger(Event:Fwd_DMA, in_msg.Address); + trigger(Event:Fwd_DMA, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:WB_ACK) { - trigger(Event:Writeback_Ack, in_msg.Address); + trigger(Event:Writeback_Ack, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:WB_ACK_DATA) { - trigger(Event:Writeback_Ack_Data, in_msg.Address); + trigger(Event:Writeback_Ack_Data, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:WB_NACK) { - trigger(Event:Writeback_Nack, in_msg.Address); + trigger(Event:Writeback_Nack, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:INV) { - trigger(Event:Inv, in_msg.Address); + trigger(Event:Inv, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else { error("Unexpected message"); } @@ -329,11 +312,14 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT if (responseToL1Cache_in.isReady()) { peek(responseToL1Cache_in, ResponseMsg, block_on="Address") { if (in_msg.Type == CoherenceResponseType:ACK) { - trigger(Event:Ack, in_msg.Address); + trigger(Event:Ack, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:DATA) { - trigger(Event:Data, in_msg.Address); + trigger(Event:Data, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) { - trigger(Event:Exclusive_Data, in_msg.Address); + trigger(Event:Exclusive_Data, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else { error("Unexpected message"); } @@ -352,41 +338,63 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT if (in_msg.Type == CacheRequestType:IFETCH) { // ** INSTRUCTION ACCESS *** + Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); // Check to see if it is in the OTHER L1 - if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + if (is_valid(L1Dcache_entry)) { // The block is in the wrong L1, put the request on the queue to the shared L2 - trigger(Event:L1_Replacement, in_msg.LineAddress); + trigger(Event:L1_Replacement, in_msg.LineAddress, L1Dcache_entry, + TBEs[in_msg.LineAddress]); } - if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + + Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); + if (is_valid(L1Icache_entry)) { // The tag matches for the L1, so the L1 asks the L2 for it. - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Icache_entry, + TBEs[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 so let's see if the L2 has it - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Icache_entry, + TBEs[in_msg.LineAddress]); } else { // No room in the L1, so we need to make room in the L1 - trigger(Event:L1_Replacement, L1IcacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:L1_Replacement, + L1IcacheMemory.cacheProbe(in_msg.LineAddress), + getL1ICacheEntry(L1IcacheMemory.cacheProbe(in_msg.LineAddress)), + TBEs[L1IcacheMemory.cacheProbe(in_msg.LineAddress)]); } } } else { // *** DATA ACCESS *** + Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); // Check to see if it is in the OTHER L1 - if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + if (is_valid(L1Icache_entry)) { // The block is in the wrong L1, put the request on the queue to the shared L2 - trigger(Event:L1_Replacement, in_msg.LineAddress); + trigger(Event:L1_Replacement, in_msg.LineAddress, + L1Icache_entry, TBEs[in_msg.LineAddress]); } - if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + + Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); + if (is_valid(L1Dcache_entry)) { // The tag matches for the L1, so the L1 ask the L2 for it - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Dcache_entry, + TBEs[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 let's see if the L2 has it - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Dcache_entry, + TBEs[in_msg.LineAddress]); } else { // No room in the L1, so we need to make room in the L1 - trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:L1_Replacement, + L1DcacheMemory.cacheProbe(in_msg.LineAddress), + getL1DCacheEntry(L1DcacheMemory.cacheProbe(in_msg.LineAddress)), + TBEs[L1DcacheMemory.cacheProbe(in_msg.LineAddress)]); } } } @@ -404,7 +412,7 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Type := CoherenceRequestType:GETS; out_msg.Requestor := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); + l2_select_low_bit, l2_select_num_bits)); out_msg.MessageSize := MessageSizeType:Request_Control; out_msg.AccessMode := in_msg.AccessMode; out_msg.Prefetch := in_msg.Prefetch; @@ -418,8 +426,9 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Address := address; out_msg.Type := CoherenceRequestType:GETX; out_msg.Requestor := machineID; + out_msg.RequestorMachine := MachineType:L1Cache; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); + l2_select_low_bit, l2_select_num_bits)); out_msg.MessageSize := MessageSizeType:Request_Control; out_msg.AccessMode := in_msg.AccessMode; out_msg.Prefetch := in_msg.Prefetch; @@ -433,8 +442,9 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Address := address; out_msg.Type := CoherenceRequestType:PUTX; out_msg.Requestor := machineID; + out_msg.RequestorMachine := MachineType:L1Cache; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); + l2_select_low_bit, l2_select_num_bits)); out_msg.MessageSize := MessageSizeType:Writeback_Control; } } @@ -446,7 +456,7 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Type := CoherenceRequestType:PUTO; out_msg.Requestor := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); + l2_select_low_bit, l2_select_num_bits)); out_msg.MessageSize := MessageSizeType:Writeback_Control; } } @@ -458,22 +468,23 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Type := CoherenceRequestType:PUTS; out_msg.Requestor := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); + l2_select_low_bit, l2_select_num_bits)); out_msg.MessageSize := MessageSizeType:Writeback_Control; } } action(e_sendData, "e", desc="Send data from cache to requestor") { peek(requestNetwork_in, RequestMsg) { + assert(is_valid(cache_entry)); if (in_msg.RequestorMachine == MachineType:L2Cache) { enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); - out_msg.DataBlk := getCacheEntry(address).DataBlk; - // out_msg.Dirty := getCacheEntry(address).Dirty; + l2_select_low_bit, l2_select_num_bits)); + out_msg.DataBlk := cache_entry.DataBlk; + // out_msg.Dirty := cache_entry.Dirty; out_msg.Dirty := false; out_msg.Acks := in_msg.Acks; out_msg.MessageSize := MessageSizeType:Response_Data; @@ -486,8 +497,8 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT 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 := cache_entry.DataBlk; + // out_msg.Dirty := cache_entry.Dirty; out_msg.Dirty := false; out_msg.Acks := in_msg.Acks; out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; @@ -499,13 +510,14 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT action(e_sendDataToL2, "ee", desc="Send data from cache to requestor") { enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); - out_msg.DataBlk := getCacheEntry(address).DataBlk; - out_msg.Dirty := getCacheEntry(address).Dirty; + l2_select_low_bit, l2_select_num_bits)); + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.Acks := 0; // irrelevant out_msg.MessageSize := MessageSizeType:Response_Data; } @@ -514,6 +526,7 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT action(ee_sendDataExclusive, "\e", desc="Send data from cache to requestor, don't keep a shared copy") { peek(requestNetwork_in, RequestMsg) { + assert(is_valid(cache_entry)); if (in_msg.RequestorMachine == MachineType:L2Cache) { enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) { out_msg.Address := address; @@ -521,9 +534,9 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L1Cache; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); - out_msg.DataBlk := getCacheEntry(address).DataBlk; - out_msg.Dirty := getCacheEntry(address).Dirty; + l2_select_low_bit, l2_select_num_bits)); + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.Acks := in_msg.Acks; out_msg.MessageSize := MessageSizeType:Response_Data; } @@ -536,8 +549,8 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L1Cache; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getCacheEntry(address).DataBlk; - out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.Acks := in_msg.Acks; out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; } @@ -566,7 +579,7 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L1Cache; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); + l2_select_low_bit, l2_select_num_bits)); out_msg.Acks := 0 - 1; // -1 out_msg.MessageSize := MessageSizeType:Response_Control; } @@ -580,7 +593,7 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Type := CoherenceResponseType:UNBLOCK; out_msg.Sender := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); + l2_select_low_bit, l2_select_num_bits)); out_msg.MessageSize := MessageSizeType:Unblock_Control; } } @@ -590,28 +603,33 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Address := address; out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE; out_msg.Sender := machineID; + out_msg.SenderMachine := MachineType:L1Cache; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); + l2_select_low_bit, l2_select_num_bits)); out_msg.MessageSize := MessageSizeType:Unblock_Control; } } action(h_load_hit, "h", desc="Notify sequencer the load completed.") { - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); - sequencer.readCallback(address, getCacheEntry(address).DataBlk); + assert(is_valid(cache_entry)); + DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); + sequencer.readCallback(address, cache_entry.DataBlk); } action(hh_store_hit, "\h", desc="Notify sequencer that store completed.") { - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); - sequencer.writeCallback(address, getCacheEntry(address).DataBlk); - getCacheEntry(address).Dirty := true; + assert(is_valid(cache_entry)); + DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); + sequencer.writeCallback(address, cache_entry.DataBlk); + cache_entry.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; + set_tbe(TBEs[address]); + assert(is_valid(cache_entry)); + tbe.DataBlk := cache_entry.DataBlk; // Data only used for writebacks + tbe.Dirty := cache_entry.Dirty; } action(j_popTriggerQueue, "j", desc="Pop trigger queue.") { @@ -632,14 +650,16 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") { peek(responseToL1Cache_in, ResponseMsg) { + assert(is_valid(tbe)); DPRINTF(RubySlicc, "L1 decrementNumberOfMessages: %d\n", in_msg.Acks); - TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - in_msg.Acks; + tbe.NumPendingMsgs := tbe.NumPendingMsgs - in_msg.Acks; } } action(mm_decrementNumberOfMessages, "\m", desc="Decrement the number of messages for which we're waiting") { peek(requestNetwork_in, RequestMsg) { - TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - in_msg.Acks; + assert(is_valid(tbe)); + tbe.NumPendingMsgs := tbe.NumPendingMsgs - in_msg.Acks; } } @@ -648,7 +668,8 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT } action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") { - if (TBEs[address].NumPendingMsgs == 0) { + assert(is_valid(tbe)); + if (tbe.NumPendingMsgs == 0) { enqueue(triggerQueue_out, TriggerMsg) { out_msg.Address := address; out_msg.Type := TriggerType:ALL_ACKS; @@ -663,14 +684,15 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT action(q_sendDataFromTBEToCache, "q", desc="Send data from TBE to cache") { peek(requestNetwork_in, RequestMsg) { + assert(is_valid(tbe)); if (in_msg.RequestorMachine == MachineType:L1Cache) { enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := TBEs[address].DataBlk; - // out_msg.Dirty := TBEs[address].Dirty; + out_msg.DataBlk := tbe.DataBlk; + // out_msg.Dirty := tbe.Dirty; out_msg.Dirty := false; out_msg.Acks := in_msg.Acks; out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; @@ -682,9 +704,9 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); - out_msg.DataBlk := TBEs[address].DataBlk; - // out_msg.Dirty := TBEs[address].Dirty; + l2_select_low_bit, l2_select_num_bits)); + out_msg.DataBlk := tbe.DataBlk; + // out_msg.Dirty := tbe.Dirty; out_msg.Dirty := false; out_msg.Acks := in_msg.Acks; out_msg.MessageSize := MessageSizeType:Response_Data; @@ -695,14 +717,15 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT action(q_sendExclusiveDataFromTBEToCache, "qq", desc="Send data from TBE to cache") { peek(requestNetwork_in, RequestMsg) { + assert(is_valid(tbe)); if (in_msg.RequestorMachine == MachineType:L1Cache) { enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - 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 := in_msg.Acks; out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; } @@ -713,9 +736,9 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); - out_msg.DataBlk := TBEs[address].DataBlk; - out_msg.Dirty := TBEs[address].Dirty; + l2_select_low_bit, l2_select_num_bits)); + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; out_msg.Acks := in_msg.Acks; out_msg.MessageSize := MessageSizeType:Response_Data; } @@ -727,30 +750,33 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT // L2 will usually request data for a writeback action(qq_sendWBDataFromTBEToL2, "\q", desc="Send data from TBE to L2") { enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L1Cache; out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, - l2_select_low_bit, l2_select_num_bits)); - out_msg.Dirty := TBEs[address].Dirty; - if (TBEs[address].Dirty) { + l2_select_low_bit, l2_select_num_bits)); + out_msg.Dirty := tbe.Dirty; + if (tbe.Dirty) { out_msg.Type := CoherenceResponseType:WRITEBACK_DIRTY_DATA; } else { out_msg.Type := CoherenceResponseType:WRITEBACK_CLEAN_DATA; } - out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.DataBlk := tbe.DataBlk; out_msg.MessageSize := MessageSizeType:Writeback_Data; } } action(s_deallocateTBE, "s", desc="Deallocate TBE") { TBEs.deallocate(address); + unset_tbe(); } action(u_writeDataToCache, "u", desc="Write data to cache") { peek(responseToL1Cache_in, ResponseMsg) { - getCacheEntry(address).DataBlk := in_msg.DataBlk; - getCacheEntry(address).Dirty := in_msg.Dirty; + assert(is_valid(cache_entry)); + cache_entry.DataBlk := in_msg.DataBlk; + cache_entry.Dirty := in_msg.Dirty; if (in_msg.Type == CoherenceResponseType:DATA) { //assert(in_msg.Dirty == false); @@ -761,9 +787,10 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT action(v_writeDataToCacheVerify, "v", desc="Write data to cache, assert it was same as before") { peek(responseToL1Cache_in, ResponseMsg) { - assert(getCacheEntry(address).DataBlk == in_msg.DataBlk); - getCacheEntry(address).DataBlk := in_msg.DataBlk; - getCacheEntry(address).Dirty := in_msg.Dirty; + assert(is_valid(cache_entry)); + assert(cache_entry.DataBlk == in_msg.DataBlk); + cache_entry.DataBlk := in_msg.DataBlk; + cache_entry.Dirty := in_msg.Dirty; } } @@ -773,17 +800,18 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT } else { L1IcacheMemory.deallocate(address); } + unset_cache_entry(); } 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_invalid(cache_entry))) { + set_cache_entry(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_invalid(cache_entry))) { + set_cache_entry(L1IcacheMemory.allocate(address, new Entry)); } } @@ -1173,4 +1201,3 @@ if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestT l_popForwardQueue; } } - diff --git a/src/mem/protocol/MOESI_CMP_directory-L2cache.sm b/src/mem/protocol/MOESI_CMP_directory-L2cache.sm index 7c6021bae..a638b171f 100644 --- a/src/mem/protocol/MOESI_CMP_directory-L2cache.sm +++ b/src/mem/protocol/MOESI_CMP_directory-L2cache.sm @@ -218,40 +218,30 @@ machine(L2Cache, "Token protocol") } - TBETable L2_TBEs, template_hack="<L2Cache_TBE>"; + TBETable TBEs, template_hack="<L2Cache_TBE>"; PerfectCacheMemory localDirectory, template_hack="<L2Cache_DirEntry>"; + void set_cache_entry(AbstractCacheEntry b); + void unset_cache_entry(); + void set_tbe(TBE b); + void unset_tbe(); - Entry getL2CacheEntry(Address addr), return_by_ref="yes" { - if (L2cacheMemory.isTagPresent(addr)) { - return static_cast(Entry, L2cacheMemory[addr]); - } else { - return static_cast(Entry, L2cacheMemory[addr]); - } - } - - void changePermission(Address addr, AccessPermission permission) { - if (L2cacheMemory.isTagPresent(addr)) { - return L2cacheMemory.changePermission(addr, permission); - } - } - - bool isCacheTagPresent(Address addr) { - return (L2cacheMemory.isTagPresent(addr) ); + Entry getCacheEntry(Address address), return_by_pointer="yes" { + return static_cast(Entry, "pointer", L2cacheMemory[address]); } bool isDirTagPresent(Address addr) { return (localDirectory.isTagPresent(addr) ); } - bool isOnlySharer(Address addr, MachineID shar_id) { - if (isCacheTagPresent(addr)) { + bool isOnlySharer(Entry cache_entry, Address addr, MachineID shar_id) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - if (getL2CacheEntry(addr).Sharers.count() > 1) { + if (cache_entry.Sharers.count() > 1) { return false; } - else if (getL2CacheEntry(addr).Sharers.count() == 1) { - if (getL2CacheEntry(addr).Sharers.isElement(shar_id)) { + else if (cache_entry.Sharers.count() == 1) { + if (cache_entry.Sharers.isElement(shar_id)) { return true; } else { @@ -285,27 +275,29 @@ machine(L2Cache, "Token protocol") } } - void copyCacheStateToDir(Address addr) { + void copyCacheStateToDir(Entry cache_entry, Address addr) { assert(localDirectory.isTagPresent(addr) == false); + assert(is_valid(cache_entry)); localDirectory.allocate(addr); - localDirectory[addr].DirState := getL2CacheEntry(addr).CacheState; - localDirectory[addr].Sharers := getL2CacheEntry(addr).Sharers; - localDirectory[addr].Owner := getL2CacheEntry(addr).Owner; - localDirectory[addr].OwnerValid := getL2CacheEntry(addr).OwnerValid; + localDirectory[addr].DirState := cache_entry.CacheState; + localDirectory[addr].Sharers := cache_entry.Sharers; + localDirectory[addr].Owner := cache_entry.Owner; + localDirectory[addr].OwnerValid := cache_entry.OwnerValid; } - void copyDirToCache(Address addr) { - getL2CacheEntry(addr).Sharers := localDirectory[addr].Sharers; - getL2CacheEntry(addr).Owner := localDirectory[addr].Owner; - getL2CacheEntry(addr).OwnerValid := localDirectory[addr].OwnerValid; + void copyDirToCache(Entry cache_entry, Address addr) { + assert(is_valid(cache_entry)); + cache_entry.Sharers := localDirectory[addr].Sharers; + cache_entry.Owner := localDirectory[addr].Owner; + cache_entry.OwnerValid := localDirectory[addr].OwnerValid; } - void recordLocalSharerInDir(Address addr, MachineID shar_id) { - if (isCacheTagPresent(addr)) { + void recordLocalSharerInDir(Entry cache_entry, Address addr, MachineID shar_id) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - getL2CacheEntry(addr).Sharers.add(shar_id); + cache_entry.Sharers.add(shar_id); } else { if (localDirectory.isTagPresent(addr) == false) { @@ -317,13 +309,13 @@ machine(L2Cache, "Token protocol") } } - void recordNewLocalExclusiveInDir(Address addr, MachineID exc_id) { + void recordNewLocalExclusiveInDir(Entry cache_entry, Address addr, MachineID exc_id) { - if (isCacheTagPresent(addr)) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - getL2CacheEntry(addr).Sharers.clear(); - getL2CacheEntry(addr).OwnerValid := true; - getL2CacheEntry(addr).Owner := exc_id; + cache_entry.Sharers.clear(); + cache_entry.OwnerValid := true; + cache_entry.Owner := exc_id; } else { if (localDirectory.isTagPresent(addr) == false) { @@ -335,12 +327,11 @@ machine(L2Cache, "Token protocol") } } - - void removeAllLocalSharersFromDir(Address addr) { - if (isCacheTagPresent(addr)) { + void removeAllLocalSharersFromDir(Entry cache_entry, Address addr) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - getL2CacheEntry(addr).Sharers.clear(); - getL2CacheEntry(addr).OwnerValid := false; + cache_entry.Sharers.clear(); + cache_entry.OwnerValid := false; } else { localDirectory[addr].Sharers.clear(); @@ -348,88 +339,84 @@ machine(L2Cache, "Token protocol") } } - void removeSharerFromDir(Address addr, MachineID sender) { - if (isCacheTagPresent(addr)) { + void removeSharerFromDir(Entry cache_entry, Address addr, MachineID sender) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - getL2CacheEntry(addr).Sharers.remove(sender); + cache_entry.Sharers.remove(sender); } else { localDirectory[addr].Sharers.remove(sender); } } - void removeOwnerFromDir(Address addr, MachineID sender) { - if (isCacheTagPresent(addr)) { + void removeOwnerFromDir(Entry cache_entry, Address addr, MachineID sender) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - getL2CacheEntry(addr).OwnerValid := false; + cache_entry.OwnerValid := false; } else { localDirectory[addr].OwnerValid := false; } } - bool isLocalSharer(Address addr, MachineID shar_id) { - if (isCacheTagPresent(addr)) { + bool isLocalSharer(Entry cache_entry, Address addr, MachineID shar_id) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - return getL2CacheEntry(addr).Sharers.isElement(shar_id); + return cache_entry.Sharers.isElement(shar_id); } else { return localDirectory[addr].Sharers.isElement(shar_id); } - } - NetDest getLocalSharers(Address addr) { - if (isCacheTagPresent(addr)) { + NetDest getLocalSharers(Entry cache_entry, Address addr) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - return getL2CacheEntry(addr).Sharers; + return cache_entry.Sharers; } else { return localDirectory[addr].Sharers; } - } - MachineID getLocalOwner(Address addr) { - if (isCacheTagPresent(addr)) { + MachineID getLocalOwner(Entry cache_entry, Address addr) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - return getL2CacheEntry(addr).Owner; + return cache_entry.Owner; } else { return localDirectory[addr].Owner; } - } - - int countLocalSharers(Address addr) { - if (isCacheTagPresent(addr)) { + int countLocalSharers(Entry cache_entry, Address addr) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - return getL2CacheEntry(addr).Sharers.count(); + return cache_entry.Sharers.count(); } else { return localDirectory[addr].Sharers.count(); } } - bool isLocalOwnerValid(Address addr) { - if (isCacheTagPresent(addr)) { + bool isLocalOwnerValid(Entry cache_entry, Address addr) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - return getL2CacheEntry(addr).OwnerValid; + return cache_entry.OwnerValid; } else { return localDirectory[addr].OwnerValid; } } - int countLocalSharersExceptRequestor(Address addr, MachineID requestor) { - if (isCacheTagPresent(addr)) { + int countLocalSharersExceptRequestor(Entry cache_entry, Address addr, MachineID requestor) { + if (is_valid(cache_entry)) { assert (localDirectory.isTagPresent(addr) == false); - if (getL2CacheEntry(addr).Sharers.isElement(requestor)) { - return ( getL2CacheEntry(addr).Sharers.count() - 1 ); + if (cache_entry.Sharers.isElement(requestor)) { + return ( cache_entry.Sharers.count() - 1 ); } else { - return getL2CacheEntry(addr).Sharers.count(); + return cache_entry.Sharers.count(); } } else { @@ -442,14 +429,12 @@ machine(L2Cache, "Token protocol") } } + State getState(TBE tbe, Entry cache_entry, Address addr) { - - State getState(Address addr) { - - if (L2_TBEs.isPresent(addr)) { - return L2_TBEs[addr].TBEState; - } else if (isCacheTagPresent(addr)) { - return getL2CacheEntry(addr).CacheState; + if (is_valid(tbe)) { + return tbe.TBEState; + } else if (is_valid(cache_entry)) { + return cache_entry.CacheState; } else if (isDirTagPresent(addr)) { return localDirectory[addr].DirState; } else { @@ -457,20 +442,15 @@ machine(L2Cache, "Token protocol") } } - std::string getStateStr(Address addr) { - return L2Cache_State_to_string(getState(addr)); - } - std::string getCoherenceRequestTypeStr(CoherenceRequestType type) { return CoherenceRequestType_to_string(type); } - - void setState(Address addr, State state) { + void setState(TBE tbe, Entry cache_entry, Address addr, State state) { assert((localDirectory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); - if (L2_TBEs.isPresent(addr)) { - L2_TBEs[addr].TBEState := state; + if (is_valid(tbe)) { + tbe.TBEState := state; } if ( @@ -482,7 +462,7 @@ machine(L2Cache, "Token protocol") (state == State:OLSX) || (state == State:SLS) ) { - assert(isCacheTagPresent(addr)); + assert(is_valid(cache_entry)); } else if ( (state == State:ILS) || @@ -495,53 +475,24 @@ machine(L2Cache, "Token protocol") // assert(isCacheTagPresent(addr) == false); } - - - if (isCacheTagPresent(addr)) { - if ( ((getL2CacheEntry(addr).CacheState != State:M) && (state == State:M)) || - ((getL2CacheEntry(addr).CacheState != State:S) && (state == State:S)) || - ((getL2CacheEntry(addr).CacheState != State:O) && (state == State:O)) ) { - getL2CacheEntry(addr).CacheState := state; + if (is_valid(cache_entry)) { + if ( ((cache_entry.CacheState != State:M) && (state == State:M)) || + ((cache_entry.CacheState != State:S) && (state == State:S)) || + ((cache_entry.CacheState != State:O) && (state == State:O)) ) { + cache_entry.CacheState := state; // disable Coherence Checker for now // sequencer.checkCoherence(addr); } else { - getL2CacheEntry(addr).CacheState := state; + cache_entry.CacheState := state; } // Set permission - changePermission(addr, AccessPermission:Read_Only); + cache_entry.changePermission(AccessPermission:Read_Only); } else if (localDirectory.isTagPresent(addr)) { localDirectory[addr].DirState := state; } - - } - - - bool isBlockExclusive(Address addr) { - if (isCacheTagPresent(addr)) { - // the list of exclusive states below is likely incomplete - if ( (getL2CacheEntry(addr).CacheState == State:M) || - (getL2CacheEntry(addr).CacheState == State:MI) ) { - return true; - } - } - - return false; - } - - bool isBlockShared(Address addr) { - if (isCacheTagPresent(addr)) { - // the list of shared states below is likely incomplete - if ( (getL2CacheEntry(addr).CacheState == State:S) || - (getL2CacheEntry(addr).CacheState == State:O) || - (getL2CacheEntry(addr).CacheState == State:OI) || - (getL2CacheEntry(addr).CacheState == State:OXW) ) { - return true; - } - } - return false; } MessageBuffer triggerQueue, ordered="true"; @@ -553,7 +504,6 @@ machine(L2Cache, "Token protocol") out_port(triggerQueue_out, TriggerMsg, triggerQueue); - // ** IN_PORTS ** // Trigger Queue @@ -561,7 +511,8 @@ machine(L2Cache, "Token protocol") if (triggerQueue_in.isReady()) { peek(triggerQueue_in, TriggerMsg) { if (in_msg.Type == TriggerType:ALL_ACKS) { - trigger(Event:All_Acks, in_msg.Address); + trigger(Event:All_Acks, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else { error("Unexpected message"); } @@ -576,20 +527,27 @@ machine(L2Cache, "Token protocol") peek(requestNetwork_in, RequestMsg) { if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestType:DMA_WRITE) { if (in_msg.Requestor == machineID) { - trigger(Event:Own_GETX, in_msg.Address); + trigger(Event:Own_GETX, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else { - trigger(Event:Fwd_GETX, in_msg.Address); + trigger(Event:Fwd_GETX, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } } else if (in_msg.Type == CoherenceRequestType:GETS) { - trigger(Event:Fwd_GETS, in_msg.Address); + trigger(Event:Fwd_GETS, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if(in_msg.Type == CoherenceRequestType:DMA_READ) { - trigger(Event:Fwd_DMA, in_msg.Address); + trigger(Event:Fwd_DMA, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:INV) { - trigger(Event:Inv, in_msg.Address); + trigger(Event:Inv, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:WB_ACK) { - trigger(Event:Writeback_Ack, in_msg.Address); + trigger(Event:Writeback_Ack, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:WB_NACK) { - trigger(Event:Writeback_Nack, in_msg.Address); + trigger(Event:Writeback_Nack, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else { error("Unexpected message"); } @@ -602,19 +560,26 @@ machine(L2Cache, "Token protocol") peek(L1requestNetwork_in, RequestMsg) { assert(in_msg.Destination.isElement(machineID)); if (in_msg.Type == CoherenceRequestType:GETX) { - trigger(Event:L1_GETX, in_msg.Address); + trigger(Event:L1_GETX, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:GETS) { - trigger(Event:L1_GETS, in_msg.Address); + trigger(Event:L1_GETS, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:PUTO) { - trigger(Event:L1_PUTO, in_msg.Address); + trigger(Event:L1_PUTO, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:PUTX) { - trigger(Event:L1_PUTX, in_msg.Address); + trigger(Event:L1_PUTX, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:PUTS) { - if (isOnlySharer(in_msg.Address, in_msg.Requestor)) { - trigger(Event:L1_PUTS_only, in_msg.Address); + Entry cache_entry := getCacheEntry(in_msg.Address); + if (isOnlySharer(cache_entry, in_msg.Address, in_msg.Requestor)) { + trigger(Event:L1_PUTS_only, in_msg.Address, + cache_entry, TBEs[in_msg.Address]); } else { - trigger(Event:L1_PUTS, in_msg.Address); + trigger(Event:L1_PUTS, in_msg.Address, + cache_entry, TBEs[in_msg.Address]); } } else { error("Unexpected message"); @@ -631,34 +596,48 @@ machine(L2Cache, "Token protocol") assert(in_msg.Destination.isElement(machineID)); if (in_msg.Type == CoherenceResponseType:ACK) { if (in_msg.SenderMachine == MachineType:L2Cache) { - trigger(Event:ExtAck, in_msg.Address); + trigger(Event:ExtAck, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else { - trigger(Event:IntAck, in_msg.Address); + trigger(Event:IntAck, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } } else if (in_msg.Type == CoherenceResponseType:DATA) { - trigger(Event:Data, in_msg.Address); + trigger(Event:Data, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) { - trigger(Event:Data_Exclusive, in_msg.Address); + trigger(Event:Data_Exclusive, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:UNBLOCK) { - trigger(Event:Unblock, in_msg.Address); + trigger(Event:Unblock, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:UNBLOCK_EXCLUSIVE) { - trigger(Event:Exclusive_Unblock, in_msg.Address); + trigger(Event:Exclusive_Unblock, in_msg.Address, + getCacheEntry(in_msg.Address), TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:WRITEBACK_DIRTY_DATA) { - if (L2cacheMemory.isTagPresent(in_msg.Address) == false && + Entry cache_entry := getCacheEntry(in_msg.Address); + if (is_invalid(cache_entry) && L2cacheMemory.cacheAvail(in_msg.Address) == false) { - trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address)); + trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address), + getCacheEntry(L2cacheMemory.cacheProbe(in_msg.Address)), + TBEs[L2cacheMemory.cacheProbe(in_msg.Address)]); } else { - trigger(Event:L1_WBDIRTYDATA, in_msg.Address); + trigger(Event:L1_WBDIRTYDATA, in_msg.Address, + cache_entry, TBEs[in_msg.Address]); } } else if (in_msg.Type == CoherenceResponseType:WRITEBACK_CLEAN_DATA) { - if (L2cacheMemory.isTagPresent(in_msg.Address) == false && + Entry cache_entry := getCacheEntry(in_msg.Address); + if (is_invalid(cache_entry) && L2cacheMemory.cacheAvail(in_msg.Address) == false) { - trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address)); + trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address), + getCacheEntry(L2cacheMemory.cacheProbe(in_msg.Address)), + TBEs[L2cacheMemory.cacheProbe(in_msg.Address)]); } else { - trigger(Event:L1_WBCLEANDATA, in_msg.Address); + trigger(Event:L1_WBCLEANDATA, in_msg.Address, + cache_entry, TBEs[in_msg.Address]); } } else { error("Unexpected message"); @@ -731,134 +710,144 @@ machine(L2Cache, "Token protocol") } action(c_sendDataFromTBEToL1GETS, "c", desc="Send data from TBE to L1 requestors in TBE") { + assert(is_valid(tbe)); enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; - out_msg.Destination.addNetDest(L2_TBEs[address].L1_GetS_IDs); - out_msg.DataBlk := L2_TBEs[address].DataBlk; - // out_msg.Dirty := L2_TBEs[address].Dirty; + out_msg.Destination.addNetDest(tbe.L1_GetS_IDs); + out_msg.DataBlk := tbe.DataBlk; + // out_msg.Dirty := tbe.Dirty; // shared data should be clean out_msg.Dirty := false; out_msg.MessageSize := MessageSizeType:Response_Data; } DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, L2_TBEs[address].DataBlk); + address, tbe.DataBlk); } action(c_sendDataFromTBEToL1GETX, "\c", desc="Send data from TBE to L1 requestors in TBE") { + assert(is_valid(tbe)); enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; - out_msg.Destination.add(L2_TBEs[address].L1_GetX_ID); - out_msg.DataBlk := L2_TBEs[address].DataBlk; - out_msg.Dirty := L2_TBEs[address].Dirty; - out_msg.Acks := L2_TBEs[address].Local_GETX_IntAcks; + out_msg.Destination.add(tbe.L1_GetX_ID); + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; + out_msg.Acks := tbe.Local_GETX_IntAcks; out_msg.MessageSize := MessageSizeType:Response_Data; } DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, L2_TBEs[address].DataBlk); + address, tbe.DataBlk); } action(c_sendExclusiveDataFromTBEToL1GETS, "\cc", desc="Send data from TBE to L1 requestors in TBE") { + assert(is_valid(tbe)); enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; - out_msg.Destination.addNetDest(L2_TBEs[address].L1_GetS_IDs); - out_msg.DataBlk := L2_TBEs[address].DataBlk; - out_msg.Dirty := L2_TBEs[address].Dirty; + out_msg.Destination.addNetDest(tbe.L1_GetS_IDs); + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } } action(c_sendDataFromTBEToFwdGETX, "cc", desc="Send data from TBE to external GETX") { + assert(is_valid(tbe)); enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; - out_msg.Destination.add(L2_TBEs[address].Fwd_GetX_ID); - out_msg.DataBlk := L2_TBEs[address].DataBlk; - out_msg.Dirty := L2_TBEs[address].Dirty; - out_msg.Acks := L2_TBEs[address].Fwd_GETX_ExtAcks; + out_msg.Destination.add(tbe.Fwd_GetX_ID); + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; + out_msg.Acks := tbe.Fwd_GETX_ExtAcks; out_msg.MessageSize := MessageSizeType:Response_Data; } } action(c_sendDataFromTBEToFwdGETS, "ccc", desc="Send data from TBE to external GETX") { + assert(is_valid(tbe)); enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; - out_msg.Destination.addNetDest(L2_TBEs[address].Fwd_GetS_IDs); - out_msg.DataBlk := L2_TBEs[address].DataBlk; - // out_msg.Dirty := L2_TBEs[address].Dirty; + out_msg.Destination.addNetDest(tbe.Fwd_GetS_IDs); + out_msg.DataBlk := tbe.DataBlk; + // out_msg.Dirty := tbe.Dirty; // shared data should be clean out_msg.Dirty := false; - out_msg.Acks := L2_TBEs[address].Fwd_GETX_ExtAcks; + out_msg.Acks := tbe.Fwd_GETX_ExtAcks; out_msg.MessageSize := MessageSizeType:Response_Data; } DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, L2_TBEs[address].DataBlk); + address, tbe.DataBlk); } action(c_sendExclusiveDataFromTBEToFwdGETS, "\ccc", desc="Send data from TBE to external GETX") { + assert(is_valid(tbe)); enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; - out_msg.Destination.addNetDest(L2_TBEs[address].Fwd_GetS_IDs); - out_msg.DataBlk := L2_TBEs[address].DataBlk; - out_msg.Dirty := L2_TBEs[address].Dirty; - out_msg.Acks := L2_TBEs[address].Fwd_GETX_ExtAcks; + out_msg.Destination.addNetDest(tbe.Fwd_GetS_IDs); + out_msg.DataBlk := tbe.DataBlk; + out_msg.Dirty := tbe.Dirty; + out_msg.Acks := tbe.Fwd_GETX_ExtAcks; out_msg.MessageSize := MessageSizeType:Response_Data; } DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, L2_TBEs[address].DataBlk); + address, tbe.DataBlk); } action(d_sendDataToL1GETS, "d", desc="Send data directly to L1 requestor") { + assert(is_valid(cache_entry)); peek(L1requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - // out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + // out_msg.Dirty := cache_entry.Dirty; // shared data should be clean out_msg.Dirty := false; out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data; } } DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, getL2CacheEntry(address).DataBlk); + address, cache_entry.DataBlk); } action(d_sendDataToL1GETX, "\d", desc="Send data and a token from TBE to L1 requestor") { + assert(is_valid(cache_entry)); peek(L1requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data; - out_msg.Acks := L2_TBEs[address].Local_GETX_IntAcks; + out_msg.Acks := tbe.Local_GETX_IntAcks; } } DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, getL2CacheEntry(address).DataBlk); + address, cache_entry.DataBlk); } action(dd_sendDataToFwdGETX, "dd", desc="send data") { + assert(is_valid(cache_entry)); peek(requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { out_msg.Address := address; @@ -866,44 +855,46 @@ machine(L2Cache, "Token protocol") out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; out_msg.Acks := in_msg.Acks; } } DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, getL2CacheEntry(address).DataBlk); + address, cache_entry.DataBlk); } action(dd_sendDataToFwdGETS, "\dd", desc="send data") { + assert(is_valid(cache_entry)); peek(requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - // out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + // out_msg.Dirty := cache_entry.Dirty; // shared data should be clean out_msg.Dirty := false; out_msg.MessageSize := MessageSizeType:Response_Data; } } DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, getL2CacheEntry(address).DataBlk); + address, cache_entry.DataBlk); } action(dd_sendExclusiveDataToFwdGETS, "\d\d", desc="send data") { + assert(is_valid(cache_entry)); peek(requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } } @@ -911,12 +902,13 @@ machine(L2Cache, "Token protocol") action(e_sendAck, "e", desc="Send ack with the tokens we've collected thus far.") { enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; - out_msg.Destination.add( L2_TBEs[address].Fwd_GetX_ID); + out_msg.Destination.add( tbe.Fwd_GetX_ID); out_msg.Acks := 0 - 1; out_msg.MessageSize := MessageSizeType:Response_Control; } @@ -938,24 +930,26 @@ machine(L2Cache, "Token protocol") action(e_sendAckToL1RequestorFromTBE, "eee", desc="Send ack with the tokens we've collected thus far.") { enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; - out_msg.Destination.add(L2_TBEs[address].L1_GetX_ID); + out_msg.Destination.add(tbe.L1_GetX_ID); out_msg.Acks := 0 - 1; out_msg.MessageSize := MessageSizeType:Response_Control; } } action(ee_sendLocalInv, "\ee", desc="Send local invalidates") { - L2_TBEs[address].NumIntPendingAcks := countLocalSharers(address); + assert(is_valid(tbe)); + tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address); DPRINTF(RubySlicc, "Address: %s, Local Sharers: %s, Pending Acks: %d\n", - address, getLocalSharers(address), - L2_TBEs[address].NumIntPendingAcks); - if (isLocalOwnerValid(address)) { - L2_TBEs[address].NumIntPendingAcks := L2_TBEs[address].NumIntPendingAcks + 1; - DPRINTF(RubySlicc, "%s\n", getLocalOwner(address)); + address, getLocalSharers(cache_entry, address), + tbe.NumIntPendingAcks); + if (isLocalOwnerValid(cache_entry, address)) { + tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + 1; + DPRINTF(RubySlicc, "%s\n", getLocalOwner(cache_entry, address)); } enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) { @@ -963,10 +957,10 @@ machine(L2Cache, "Token protocol") out_msg.Type := CoherenceRequestType:INV; out_msg.Requestor := machineID; out_msg.RequestorMachine := MachineType:L2Cache; - out_msg.Destination.addNetDest(getLocalSharers(address)); - if (isLocalOwnerValid(address)) + out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address)); + if (isLocalOwnerValid(cache_entry, address)) { - out_msg.Destination.add(getLocalOwner(address)); + out_msg.Destination.add(getLocalOwner(cache_entry, address)); } out_msg.MessageSize := MessageSizeType:Invalidate_Control; } @@ -975,38 +969,40 @@ machine(L2Cache, "Token protocol") action(ee_sendLocalInvSharersOnly, "\eee", desc="Send local invalidates to sharers if they exist") { // assert(countLocalSharers(address) > 0); - L2_TBEs[address].NumIntPendingAcks := countLocalSharers(address); + assert(is_valid(tbe)); + tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address); - if (countLocalSharers(address) > 0) { + if (countLocalSharers(cache_entry, address) > 0) { enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) { out_msg.Address := address; out_msg.Type := CoherenceRequestType:INV; out_msg.Requestor := machineID; out_msg.RequestorMachine := MachineType:L2Cache; - out_msg.Destination.addNetDest(getLocalSharers(address)); + out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address)); out_msg.MessageSize := MessageSizeType:Invalidate_Control; } } } action(ee_addLocalIntAck, "e\ee", desc="add a local ack to wait for") { - L2_TBEs[address].NumIntPendingAcks := L2_TBEs[address].NumIntPendingAcks + 1; + assert(is_valid(tbe)); + tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + 1; } action(ee_issueLocalInvExceptL1Requestor, "\eeee", desc="Send local invalidates to sharers if they exist") { peek(L1requestNetwork_in, RequestMsg) { // assert(countLocalSharers(address) > 0); - if (countLocalSharers(address) == 0) { - L2_TBEs[address].NumIntPendingAcks := 0; + if (countLocalSharers(cache_entry, address) == 0) { + tbe.NumIntPendingAcks := 0; } else { - if (isLocalSharer(address, in_msg.Requestor)) { - L2_TBEs[address].NumIntPendingAcks := countLocalSharers(address) - 1; + if (isLocalSharer(cache_entry, address, in_msg.Requestor)) { + tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address) - 1; } else { - L2_TBEs[address].NumIntPendingAcks := countLocalSharers(address); + tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address); } enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) { @@ -1014,7 +1010,7 @@ machine(L2Cache, "Token protocol") out_msg.Type := CoherenceRequestType:INV; out_msg.Requestor := in_msg.Requestor; out_msg.RequestorMachine := MachineType:L1Cache; - out_msg.Destination.addNetDest(getLocalSharers(address)); + out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address)); out_msg.Destination.remove(in_msg.Requestor); out_msg.MessageSize := MessageSizeType:Invalidate_Control; } @@ -1023,24 +1019,25 @@ machine(L2Cache, "Token protocol") } action(ee_issueLocalInvExceptL1RequestorInTBE, "\eeeeee", desc="Send local invalidates to sharers if they exist") { - if (countLocalSharers(address) == 0) { - L2_TBEs[address].NumIntPendingAcks := 0; + assert(is_valid(tbe)); + if (countLocalSharers(cache_entry, address) == 0) { + tbe.NumIntPendingAcks := 0; } else { - if (isLocalSharer(address, L2_TBEs[address].L1_GetX_ID)) { - L2_TBEs[address].NumIntPendingAcks := countLocalSharers(address) - 1; + if (isLocalSharer(cache_entry, address, tbe.L1_GetX_ID)) { + tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address) - 1; } else { - L2_TBEs[address].NumIntPendingAcks := countLocalSharers(address); + tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address); } } enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) { out_msg.Address := address; out_msg.Type := CoherenceRequestType:INV; - out_msg.Requestor := L2_TBEs[address].L1_GetX_ID; + out_msg.Requestor := tbe.L1_GetX_ID; out_msg.RequestorMachine := MachineType:L1Cache; - out_msg.Destination.addNetDest(getLocalSharers(address)); - out_msg.Destination.remove(L2_TBEs[address].L1_GetX_ID); + out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address)); + out_msg.Destination.remove(tbe.L1_GetX_ID); out_msg.MessageSize := MessageSizeType:Invalidate_Control; } } @@ -1072,64 +1069,69 @@ machine(L2Cache, "Token protocol") action(g_recordLocalSharer, "g", desc="Record new local sharer from unblock message") { peek(responseNetwork_in, ResponseMsg) { - recordLocalSharerInDir(in_msg.Address, in_msg.Sender); + recordLocalSharerInDir(cache_entry, in_msg.Address, in_msg.Sender); } } action(g_recordLocalExclusive, "\g", desc="Record new local exclusive sharer from unblock message") { peek(responseNetwork_in, ResponseMsg) { - recordNewLocalExclusiveInDir(address, in_msg.Sender); + recordNewLocalExclusiveInDir(cache_entry, address, in_msg.Sender); } } action(gg_clearLocalSharers, "gg", desc="Clear local sharers") { - removeAllLocalSharersFromDir(address); + removeAllLocalSharersFromDir(cache_entry, address); } action(gg_clearSharerFromL1Response, "\gg", desc="Clear sharer from L1 response queue") { peek(responseNetwork_in, ResponseMsg) { - removeSharerFromDir(in_msg.Address, in_msg.Sender); + removeSharerFromDir(cache_entry, in_msg.Address, in_msg.Sender); } } action(gg_clearOwnerFromL1Response, "g\g", desc="Clear sharer from L1 response queue") { peek(responseNetwork_in, ResponseMsg) { - removeOwnerFromDir(in_msg.Address, in_msg.Sender); + removeOwnerFromDir(cache_entry, in_msg.Address, in_msg.Sender); } } action(h_countLocalSharersExceptRequestor, "h", desc="counts number of acks needed for L1 GETX") { peek(L1requestNetwork_in, RequestMsg) { - L2_TBEs[address].Local_GETX_IntAcks := countLocalSharersExceptRequestor(address, in_msg.Requestor); + assert(is_valid(tbe)); + tbe.Local_GETX_IntAcks := countLocalSharersExceptRequestor(cache_entry, address, in_msg.Requestor); } } action(h_clearIntAcks, "\h", desc="clear IntAcks") { - L2_TBEs[address].Local_GETX_IntAcks := 0; + assert(is_valid(tbe)); + tbe.Local_GETX_IntAcks := 0; } action(hh_countLocalSharersExceptL1GETXRequestorInTBE, "hh", desc="counts number of acks needed for L1 GETX") { - L2_TBEs[address].Local_GETX_IntAcks := countLocalSharersExceptRequestor(address, L2_TBEs[address].L1_GetX_ID); + assert(is_valid(tbe)); + tbe.Local_GETX_IntAcks := countLocalSharersExceptRequestor(cache_entry, address, tbe.L1_GetX_ID); } action(i_copyDataToTBE, "\i", desc="Copy data from response queue to TBE") { peek(responseNetwork_in, ResponseMsg) { - L2_TBEs[address].DataBlk := in_msg.DataBlk; - L2_TBEs[address].Dirty := in_msg.Dirty; + assert(is_valid(tbe)); + tbe.DataBlk := in_msg.DataBlk; + tbe.Dirty := in_msg.Dirty; } } action(i_allocateTBE, "i", desc="Allocate TBE for internal/external request(isPrefetch=0, number of invalidates=0)") { - check_allocate(L2_TBEs); - L2_TBEs.allocate(address); - if(isCacheTagPresent(address)) { - L2_TBEs[address].DataBlk := getL2CacheEntry(address).DataBlk; - L2_TBEs[address].Dirty := getL2CacheEntry(address).Dirty; + check_allocate(TBEs); + TBEs.allocate(address); + set_tbe(TBEs[address]); + if(is_valid(cache_entry)) { + tbe.DataBlk := cache_entry.DataBlk; + tbe.Dirty := cache_entry.Dirty; } - L2_TBEs[address].NumIntPendingAcks := 0; // default value - L2_TBEs[address].NumExtPendingAcks := 0; // default value - L2_TBEs[address].Fwd_GetS_IDs.clear(); - L2_TBEs[address].L1_GetS_IDs.clear(); + tbe.NumIntPendingAcks := 0; // default value + tbe.NumExtPendingAcks := 0; // default value + tbe.Fwd_GetS_IDs.clear(); + tbe.L1_GetS_IDs.clear(); } @@ -1141,7 +1143,7 @@ machine(L2Cache, "Token protocol") out_msg.Type := in_msg.Type; out_msg.Requestor := machineID; out_msg.RequestorMachine := MachineType:L2Cache; - out_msg.Destination.add(getLocalOwner(in_msg.Address)); + out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.Address)); out_msg.Type := in_msg.Type; out_msg.MessageSize := MessageSizeType:Forwarded_Control; out_msg.Acks := 0 - 1; @@ -1166,13 +1168,14 @@ machine(L2Cache, "Token protocol") action(k_forwardLocalGETXToLocalOwner, "\k", desc="Forward local request to local owner") { enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceRequestType:GETX; - out_msg.Requestor := L2_TBEs[address].L1_GetX_ID; + out_msg.Requestor := tbe.L1_GetX_ID; out_msg.RequestorMachine := MachineType:L1Cache; out_msg.Destination.add(localDirectory[address].Owner); out_msg.MessageSize := MessageSizeType:Forwarded_Control; - out_msg.Acks := 1 + L2_TBEs[address].Local_GETX_IntAcks; + out_msg.Acks := 1 + tbe.Local_GETX_IntAcks; } } @@ -1184,7 +1187,7 @@ machine(L2Cache, "Token protocol") out_msg.Type := CoherenceRequestType:GETX; out_msg.Requestor := in_msg.Requestor; out_msg.RequestorMachine := MachineType:L1Cache; - out_msg.Destination.add(getLocalOwner(in_msg.Address)); + out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.Address)); out_msg.MessageSize := MessageSizeType:Forwarded_Control; out_msg.Acks := 1; } @@ -1198,7 +1201,7 @@ machine(L2Cache, "Token protocol") out_msg.Type := CoherenceRequestType:GETS; out_msg.Requestor := in_msg.Requestor; out_msg.RequestorMachine := MachineType:L1Cache; - out_msg.Destination.add(getLocalOwner(in_msg.Address)); + out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.Address)); out_msg.MessageSize := MessageSizeType:Forwarded_Control; } } @@ -1252,19 +1255,22 @@ machine(L2Cache, "Token protocol") action(m_decrementNumberOfMessagesInt, "\m", desc="Decrement the number of messages for which we're waiting") { peek(responseNetwork_in, ResponseMsg) { - L2_TBEs[address].NumIntPendingAcks := L2_TBEs[address].NumIntPendingAcks + in_msg.Acks; + assert(is_valid(tbe)); + tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + in_msg.Acks; } } action(m_decrementNumberOfMessagesExt, "\mmm", desc="Decrement the number of messages for which we're waiting") { peek(responseNetwork_in, ResponseMsg) { - L2_TBEs[address].NumExtPendingAcks := L2_TBEs[address].NumExtPendingAcks - in_msg.Acks; + assert(is_valid(tbe)); + tbe.NumExtPendingAcks := tbe.NumExtPendingAcks - in_msg.Acks; } } action(mm_decrementNumberOfMessagesExt, "\mm", desc="Decrement the number of messages for which we're waiting") { peek(requestNetwork_in, RequestMsg) { - L2_TBEs[address].NumExtPendingAcks := L2_TBEs[address].NumExtPendingAcks - in_msg.Acks; + assert(is_valid(tbe)); + tbe.NumExtPendingAcks := tbe.NumExtPendingAcks - in_msg.Acks; } } @@ -1282,7 +1288,8 @@ machine(L2Cache, "Token protocol") action(o_checkForIntCompletion, "\o", desc="Check if we have received all the messages required for completion") { - if (L2_TBEs[address].NumIntPendingAcks == 0) { + assert(is_valid(tbe)); + if (tbe.NumIntPendingAcks == 0) { enqueue(triggerQueue_out, TriggerMsg) { out_msg.Address := address; out_msg.Type := TriggerType:ALL_ACKS; @@ -1291,7 +1298,8 @@ machine(L2Cache, "Token protocol") } action(o_checkForExtCompletion, "\oo", desc="Check if we have received all the messages required for completion") { - if (L2_TBEs[address].NumExtPendingAcks == 0) { + assert(is_valid(tbe)); + if (tbe.NumExtPendingAcks == 0) { enqueue(triggerQueue_out, TriggerMsg) { out_msg.Address := address; out_msg.Type := TriggerType:ALL_ACKS; @@ -1302,83 +1310,92 @@ machine(L2Cache, "Token protocol") action( qq_sendDataFromTBEToMemory, "qq", desc="Send data from TBE to directory") { enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; out_msg.Destination.add(map_Address_to_Directory(address)); - out_msg.Dirty := L2_TBEs[address].Dirty; - if (L2_TBEs[address].Dirty) { + out_msg.Dirty := tbe.Dirty; + if (tbe.Dirty) { out_msg.Type := CoherenceResponseType:WRITEBACK_DIRTY_DATA; - out_msg.DataBlk := L2_TBEs[address].DataBlk; + out_msg.DataBlk := tbe.DataBlk; out_msg.MessageSize := MessageSizeType:Writeback_Data; } else { out_msg.Type := CoherenceResponseType:WRITEBACK_CLEAN_ACK; // 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 := L2_TBEs[address].DataBlk; + out_msg.DataBlk := tbe.DataBlk; out_msg.MessageSize := MessageSizeType:Writeback_Control; } } } action( r_setMRU, "\rrr", desc="manually set the MRU bit for cache line" ) { - if(isCacheTagPresent(address)) { + if(is_valid(cache_entry)) { L2cacheMemory.setMRU(address); } } action( s_recordGetXL1ID, "ss", desc="record local GETX requestor") { peek(L1requestNetwork_in, RequestMsg) { - L2_TBEs[address].L1_GetX_ID := in_msg.Requestor; + assert(is_valid(tbe)); + tbe.L1_GetX_ID := in_msg.Requestor; } } action(s_deallocateTBE, "s", desc="Deallocate external TBE") { - L2_TBEs.deallocate(address); + TBEs.deallocate(address); + unset_tbe(); } action( s_recordGetSL1ID, "\ss", desc="record local GETS requestor") { peek(L1requestNetwork_in, RequestMsg) { - L2_TBEs[address].L1_GetS_IDs.add(in_msg.Requestor); + assert(is_valid(tbe)); + tbe.L1_GetS_IDs.add(in_msg.Requestor); } } action(t_recordFwdXID, "t", desc="record global GETX requestor") { peek(requestNetwork_in, RequestMsg) { - L2_TBEs[address].Fwd_GetX_ID := in_msg.Requestor; - L2_TBEs[address].Fwd_GETX_ExtAcks := in_msg.Acks; + assert(is_valid(tbe)); + tbe.Fwd_GetX_ID := in_msg.Requestor; + tbe.Fwd_GETX_ExtAcks := in_msg.Acks; } } action(t_recordFwdSID, "\t", desc="record global GETS requestor") { peek(requestNetwork_in, RequestMsg) { - L2_TBEs[address].Fwd_GetS_IDs.clear(); - L2_TBEs[address].Fwd_GetS_IDs.add(in_msg.Requestor); + assert(is_valid(tbe)); + tbe.Fwd_GetS_IDs.clear(); + tbe.Fwd_GetS_IDs.add(in_msg.Requestor); } } action(u_writeDataToCache, "u", desc="Write data to cache") { peek(responseNetwork_in, ResponseMsg) { - getL2CacheEntry(address).DataBlk := in_msg.DataBlk; - if ((getL2CacheEntry(address).Dirty == false) && in_msg.Dirty) { - getL2CacheEntry(address).Dirty := in_msg.Dirty; + assert(is_valid(cache_entry)); + cache_entry.DataBlk := in_msg.DataBlk; + if ((cache_entry.Dirty == false) && in_msg.Dirty) { + cache_entry.Dirty := in_msg.Dirty; } } } action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") { - L2cacheMemory.allocate(address, new Entry); + set_cache_entry(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(); } action(w_assertIncomingDataAndCacheDataMatch, "w", desc="Assert that the incoming data and the data in the cache match") { peek(responseNetwork_in, ResponseMsg) { - assert(getL2CacheEntry(address).DataBlk == in_msg.DataBlk); + assert(is_valid(cache_entry)); + assert(cache_entry.DataBlk == in_msg.DataBlk); } } @@ -1389,25 +1406,18 @@ machine(L2Cache, "Token protocol") } } - - action(y_copyCacheStateToDir, "y", desc="Copy cache state to directory state") { - - assert(isCacheTagPresent(address)); - copyCacheStateToDir(address); - + copyCacheStateToDir(cache_entry, address); } action(y_copyDirToCacheAndRemove, "/y", desc="Copy dir state to cache and remove") { - copyDirToCache(address); + copyDirToCache(cache_entry, address); localDirectory.deallocate(address); } - action(z_stall, "z", desc="Stall") { } - action(zz_recycleL1RequestQueue, "zz", desc="Send the head of the mandatory queue to the back of the queue.") { peek(L1requestNetwork_in, RequestMsg) { APPEND_TRANSITION_COMMENT(in_msg.Requestor); @@ -1422,7 +1432,6 @@ machine(L2Cache, "Token protocol") requestNetwork_in.recycle(); } - action(zz_recycleResponseQueue, "\z\z", desc="Send the head of the mandatory queue to the back of the queue.") { peek(responseNetwork_in, ResponseMsg) { APPEND_TRANSITION_COMMENT(in_msg.Sender); @@ -2603,4 +2612,3 @@ machine(L2Cache, "Token protocol") m_popRequestQueue; } } - diff --git a/src/mem/protocol/MOESI_CMP_directory-dir.sm b/src/mem/protocol/MOESI_CMP_directory-dir.sm index 36e96cf41..19b69c64c 100644 --- a/src/mem/protocol/MOESI_CMP_directory-dir.sm +++ b/src/mem/protocol/MOESI_CMP_directory-dir.sm @@ -119,15 +119,18 @@ machine(Directory, "Directory protocol") // ** OBJECTS ** TBETable TBEs, template_hack="<Directory_TBE>"; + void set_tbe(TBE b); + void unset_tbe(); + Entry getDirectoryEntry(Address addr), return_by_ref="yes" { return static_cast(Entry, directory[addr]); } - State getState(Address addr) { + State getState(TBE tbe, Address addr) { return getDirectoryEntry(addr).DirectoryState; } - void setState(Address addr, State state) { + void setState(TBE tbe, Address addr, State state) { if (directory.isPresent(addr)) { if (state == State:I) { @@ -204,18 +207,24 @@ machine(Directory, "Directory protocol") peek(unblockNetwork_in, ResponseMsg) { if (in_msg.Type == CoherenceResponseType:UNBLOCK) { if (getDirectoryEntry(in_msg.Address).WaitingUnblocks == 1) { - trigger(Event:Last_Unblock, in_msg.Address); + trigger(Event:Last_Unblock, in_msg.Address, + TBEs[in_msg.Address]); } else { - trigger(Event:Unblock, in_msg.Address); + trigger(Event:Unblock, in_msg.Address, + TBEs[in_msg.Address]); } } else if (in_msg.Type == CoherenceResponseType:UNBLOCK_EXCLUSIVE) { - trigger(Event:Exclusive_Unblock, in_msg.Address); + trigger(Event:Exclusive_Unblock, in_msg.Address, + TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:WRITEBACK_DIRTY_DATA) { - trigger(Event:Dirty_Writeback, in_msg.Address); + trigger(Event:Dirty_Writeback, in_msg.Address, + TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:WRITEBACK_CLEAN_ACK) { - trigger(Event:Clean_Writeback, in_msg.Address); + trigger(Event:Clean_Writeback, in_msg.Address, + TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) { - trigger(Event:Data, in_msg.Address); + trigger(Event:Data, in_msg.Address, + TBEs[in_msg.Address]); } else { error("Invalid message"); } @@ -227,19 +236,21 @@ machine(Directory, "Directory protocol") if (requestQueue_in.isReady()) { peek(requestQueue_in, RequestMsg) { if (in_msg.Type == CoherenceRequestType:GETS) { - trigger(Event:GETS, in_msg.Address); + trigger(Event:GETS, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:GETX) { - trigger(Event:GETX, in_msg.Address); + trigger(Event:GETX, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:PUTX) { - trigger(Event:PUTX, in_msg.Address); + trigger(Event:PUTX, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:PUTO) { - trigger(Event:PUTO, in_msg.Address); + trigger(Event:PUTO, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:PUTO_SHARERS) { - trigger(Event:PUTO_SHARERS, in_msg.Address); + trigger(Event:PUTO_SHARERS, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:DMA_READ) { - trigger(Event:DMA_READ, makeLineAddress(in_msg.Address)); + trigger(Event:DMA_READ, makeLineAddress(in_msg.Address), + TBEs[makeLineAddress(in_msg.Address)]); } else if (in_msg.Type == CoherenceRequestType:DMA_WRITE) { - trigger(Event:DMA_WRITE, makeLineAddress(in_msg.Address)); + trigger(Event:DMA_WRITE, makeLineAddress(in_msg.Address), + TBEs[makeLineAddress(in_msg.Address)]); } else { error("Invalid message"); } @@ -252,9 +263,9 @@ machine(Directory, "Directory protocol") if (memQueue_in.isReady()) { peek(memQueue_in, MemoryMsg) { if (in_msg.Type == MemoryRequestType:MEMORY_READ) { - trigger(Event:Memory_Data, in_msg.Address); + trigger(Event:Memory_Data, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { - trigger(Event:Memory_Ack, in_msg.Address); + trigger(Event:Memory_Ack, in_msg.Address, TBEs[in_msg.Address]); } else { DPRINTF(RubySlicc, "%s\n", in_msg.Type); error("Invalid message"); @@ -271,6 +282,7 @@ machine(Directory, "Directory protocol") out_msg.Address := address; out_msg.Type := CoherenceRequestType:WB_ACK; out_msg.Requestor := in_msg.Requestor; + out_msg.RequestorMachine := MachineType:Directory; out_msg.Destination.add(in_msg.Requestor); out_msg.MessageSize := MessageSizeType:Writeback_Control; } @@ -481,9 +493,9 @@ machine(Directory, "Directory protocol") out_msg.Address := address; out_msg.Type := MemoryRequestType:MEMORY_WB; out_msg.Sender := machineID; - if (TBEs.isPresent(address)) { - out_msg.OriginalRequestorMachId := TBEs[address].Requestor; - } + if (is_valid(tbe)) { + out_msg.OriginalRequestorMachId := tbe.Requestor; + } out_msg.DataBlk := in_msg.DataBlk; out_msg.MessageSize := in_msg.MessageSize; //out_msg.Prefetch := false; @@ -543,8 +555,8 @@ machine(Directory, "Directory protocol") out_msg.Address := address; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:Directory; - if (TBEs.isPresent(address)) { - out_msg.Destination.add(TBEs[address].Requestor); + if (is_valid(tbe)) { + out_msg.Destination.add(tbe.Requestor); } out_msg.DataBlk := in_msg.DataBlk; out_msg.Acks := getDirectoryEntry(address).Sharers.count(); // for dma requests @@ -561,23 +573,25 @@ machine(Directory, "Directory protocol") } action(l_writeDMADataToMemoryFromTBE, "\ll", desc="Write data from a DMA_WRITE to memory") { - getDirectoryEntry(address).DataBlk.copyPartial(TBEs[address].DataBlk, - addressOffset(TBEs[address].PhysicalAddress), - TBEs[address].Len); + assert(is_valid(tbe)); + getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, + addressOffset(tbe.PhysicalAddress), tbe.Len); } action(v_allocateTBE, "v", desc="Allocate TBE entry") { peek (requestQueue_in, RequestMsg) { TBEs.allocate(address); - TBEs[address].PhysicalAddress := in_msg.Address; - TBEs[address].Len := in_msg.Len; - TBEs[address].DataBlk := in_msg.DataBlk; - TBEs[address].Requestor := in_msg.Requestor; + set_tbe(TBEs[address]); + tbe.PhysicalAddress := in_msg.Address; + tbe.Len := in_msg.Len; + tbe.DataBlk := in_msg.DataBlk; + tbe.Requestor := in_msg.Requestor; } } action(w_deallocateTBE, "w", desc="Deallocate TBE entry") { TBEs.deallocate(address); + unset_tbe(); } diff --git a/src/mem/protocol/MOESI_CMP_directory-dma.sm b/src/mem/protocol/MOESI_CMP_directory-dma.sm index 673e0c4cb..b129757b8 100644 --- a/src/mem/protocol/MOESI_CMP_directory-dma.sm +++ b/src/mem/protocol/MOESI_CMP_directory-dma.sm @@ -51,10 +51,13 @@ machine(DMA, "DMA Controller") TBETable TBEs, template_hack="<DMA_TBE>"; State cur_state; - State getState(Address addr) { + void set_tbe(TBE b); + void unset_tbe(); + + State getState(TBE tbe, Address addr) { return cur_state; } - void setState(Address addr, State state) { + void setState(TBE tbe, Address addr, State state) { cur_state := state; } @@ -83,9 +86,11 @@ machine(DMA, "DMA Controller") if (dmaRequestQueue_in.isReady()) { peek(dmaRequestQueue_in, SequencerMsg) { if (in_msg.Type == SequencerRequestType:LD ) { - trigger(Event:ReadRequest, in_msg.LineAddress); + trigger(Event:ReadRequest, in_msg.LineAddress, + TBEs[in_msg.LineAddress]); } else if (in_msg.Type == SequencerRequestType:ST) { - trigger(Event:WriteRequest, in_msg.LineAddress); + trigger(Event:WriteRequest, in_msg.LineAddress, + TBEs[in_msg.LineAddress]); } else { error("Invalid request type"); } @@ -97,12 +102,15 @@ machine(DMA, "DMA Controller") if (dmaResponseQueue_in.isReady()) { peek( dmaResponseQueue_in, ResponseMsg) { if (in_msg.Type == CoherenceResponseType:DMA_ACK) { - trigger(Event:DMA_Ack, makeLineAddress(in_msg.Address)); + trigger(Event:DMA_Ack, makeLineAddress(in_msg.Address), + TBEs[makeLineAddress(in_msg.Address)]); } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE || - in_msg.Type == CoherenceResponseType:DATA) { - trigger(Event:Data, makeLineAddress(in_msg.Address)); + in_msg.Type == CoherenceResponseType:DATA) { + trigger(Event:Data, makeLineAddress(in_msg.Address), + TBEs[makeLineAddress(in_msg.Address)]); } else if (in_msg.Type == CoherenceResponseType:ACK) { - trigger(Event:Inv_Ack, makeLineAddress(in_msg.Address)); + trigger(Event:Inv_Ack, makeLineAddress(in_msg.Address), + TBEs[makeLineAddress(in_msg.Address)]); } else { error("Invalid response type"); } @@ -115,7 +123,7 @@ machine(DMA, "DMA Controller") if (triggerQueue_in.isReady()) { peek(triggerQueue_in, TriggerMsg) { if (in_msg.Type == TriggerType:ALL_ACKS) { - trigger(Event:All_Acks, in_msg.Address); + trigger(Event:All_Acks, in_msg.Address, TBEs[in_msg.Address]); } else { error("Unexpected message"); } @@ -156,7 +164,8 @@ machine(DMA, "DMA Controller") } action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") { - if (TBEs[address].NumAcks == 0) { + assert(is_valid(tbe)); + if (tbe.NumAcks == 0) { enqueue(triggerQueue_out, TriggerMsg) { out_msg.Address := address; out_msg.Type := TriggerType:ALL_ACKS; @@ -166,7 +175,8 @@ machine(DMA, "DMA Controller") action(u_updateAckCount, "u", desc="Update ack count") { peek(dmaResponseQueue_in, ResponseMsg) { - TBEs[address].NumAcks := TBEs[address].NumAcks - in_msg.Acks; + assert(is_valid(tbe)); + tbe.NumAcks := tbe.NumAcks - in_msg.Acks; } } @@ -193,20 +203,24 @@ machine(DMA, "DMA Controller") action(t_updateTBEData, "t", desc="Update TBE Data") { peek(dmaResponseQueue_in, ResponseMsg) { - TBEs[address].DataBlk := in_msg.DataBlk; + assert(is_valid(tbe)); + tbe.DataBlk := in_msg.DataBlk; } } action(d_dataCallbackFromTBE, "/d", desc="data callback with data from TBE") { - dma_sequencer.dataCallback(TBEs[address].DataBlk); + assert(is_valid(tbe)); + dma_sequencer.dataCallback(tbe.DataBlk); } action(v_allocateTBE, "v", desc="Allocate TBE entry") { TBEs.allocate(address); + set_tbe(TBEs[address]); } action(w_deallocateTBE, "w", desc="Deallocate TBE entry") { TBEs.deallocate(address); + unset_tbe(); } action(z_stall, "z", desc="dma is busy..stall") { diff --git a/src/mem/protocol/MOESI_CMP_token-L1cache.sm b/src/mem/protocol/MOESI_CMP_token-L1cache.sm index a810a3e02..8cb45249e 100644 --- a/src/mem/protocol/MOESI_CMP_token-L1cache.sm +++ b/src/mem/protocol/MOESI_CMP_token-L1cache.sm @@ -171,6 +171,11 @@ machine(L1Cache, "Token protocol") int countStarvingForAddress(Address); int countReadStarvingForAddress(Address); } + + void set_cache_entry(AbstractCacheEntry b); + void unset_cache_entry(); + void set_tbe(TBE b); + void unset_tbe(); TBETable L1_TBEs, template_hack="<L1Cache_TBE>"; @@ -210,46 +215,39 @@ machine(L1Cache, "Token protocol") averageLatencyCounter := averageLatencyCounter - averageLatencyEstimate() + latency; } - - Entry getCacheEntry(Address addr), return_by_ref="yes" { - if (L1DcacheMemory.isTagPresent(addr)) { - assert(L1IcacheMemory.isTagPresent(addr) == false); - return static_cast(Entry, L1DcacheMemory[addr]); - } else { - return static_cast(Entry, L1IcacheMemory[addr]); + Entry getCacheEntry(Address addr), return_by_pointer="yes" { + Entry L1Dcache_entry := static_cast(Entry, "pointer", L1DcacheMemory.lookup(addr)); + if(is_valid(L1Dcache_entry)) { + return L1Dcache_entry; } + + Entry L1Icache_entry := static_cast(Entry, "pointer", L1IcacheMemory.lookup(addr)); + return L1Icache_entry; } - int getTokens(Address addr) { - if (L1DcacheMemory.isTagPresent(addr)) { - assert(L1IcacheMemory.isTagPresent(addr) == false); - return static_cast(Entry, L1DcacheMemory[addr]).Tokens; - } else if (L1IcacheMemory.isTagPresent(addr)) { - return static_cast(Entry, L1IcacheMemory[addr]).Tokens; - } else { - return 0; - } + Entry getL1DCacheEntry(Address addr), return_by_pointer="yes" { + Entry L1Dcache_entry := static_cast(Entry, "pointer", L1DcacheMemory.lookup(addr)); + return L1Dcache_entry; } - void changePermission(Address addr, AccessPermission permission) { - if (L1DcacheMemory.isTagPresent(addr)) { - return L1DcacheMemory.changePermission(addr, permission); - } else { - return L1IcacheMemory.changePermission(addr, permission); - } + Entry getL1ICacheEntry(Address addr), return_by_pointer="yes" { + Entry L1Icache_entry := static_cast(Entry, "pointer", L1IcacheMemory.lookup(addr)); + return L1Icache_entry; } - bool isCacheTagPresent(Address addr) { - return (L1DcacheMemory.isTagPresent(addr) || L1IcacheMemory.isTagPresent(addr)); + int getTokens(Entry cache_entry) { + if (is_valid(cache_entry)) { + return cache_entry.Tokens; + } + return 0; } - State getState(Address addr) { - assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); + State getState(TBE tbe, Entry cache_entry, Address addr) { - if (L1_TBEs.isPresent(addr)) { - return L1_TBEs[addr].TBEState; - } else if (isCacheTagPresent(addr)) { - return getCacheEntry(addr).CacheState; + if (is_valid(tbe)) { + return tbe.TBEState; + } else if (is_valid(cache_entry)) { + return cache_entry.CacheState; } else { if ((persistentTable.isLocked(addr) == true) && (persistentTable.findSmallest(addr) != machineID)) { // Not in cache, in persistent table, but this processor isn't highest priority @@ -260,31 +258,29 @@ machine(L1Cache, "Token protocol") } } - void setState(Address addr, State state) { + void setState(TBE tbe, Entry cache_entry, Address addr, State state) { assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); - if (L1_TBEs.isPresent(addr)) { + if (is_valid(tbe)) { assert(state != State:I); assert(state != State:S); assert(state != State:O); assert(state != State:MM); assert(state != State:M); - L1_TBEs[addr].TBEState := state; + tbe.TBEState := state; } - if (isCacheTagPresent(addr)) { + if (is_valid(cache_entry)) { // Make sure the token count is in range - assert(getCacheEntry(addr).Tokens >= 0); - assert(getCacheEntry(addr).Tokens <= max_tokens()); - assert(getCacheEntry(addr).Tokens != (max_tokens() / 2)); + assert(cache_entry.Tokens >= 0); + assert(cache_entry.Tokens <= max_tokens()); + assert(cache_entry.Tokens != (max_tokens() / 2)); if ((state == State:I_L) || (state == State:IM_L) || (state == State:IS_L)) { // Make sure we have no tokens in the "Invalid, locked" states - if (isCacheTagPresent(addr)) { - assert(getCacheEntry(addr).Tokens == 0); - } + assert(cache_entry.Tokens == 0); // Make sure the line is locked // assert(persistentTable.isLocked(addr)); @@ -294,8 +290,8 @@ machine(L1Cache, "Token protocol") } else if ((state == State:S_L) || (state == State:SM_L)) { - assert(getCacheEntry(addr).Tokens >= 1); - assert(getCacheEntry(addr).Tokens < (max_tokens() / 2)); + assert(cache_entry.Tokens >= 1); + assert(cache_entry.Tokens < (max_tokens() / 2)); // Make sure the line is locked... // assert(persistentTable.isLocked(addr)); @@ -321,30 +317,30 @@ machine(L1Cache, "Token protocol") // in M and E you have all the tokens if (state == State:MM || state == State:M || state == State:MM_W || state == State:M_W) { - assert(getCacheEntry(addr).Tokens == max_tokens()); + assert(cache_entry.Tokens == max_tokens()); } // in NP you have no tokens if (state == State:NP) { - assert(getCacheEntry(addr).Tokens == 0); + assert(cache_entry.Tokens == 0); } // You have at least one token in S-like states if (state == State:S || state == State:SM) { - assert(getCacheEntry(addr).Tokens > 0); + assert(cache_entry.Tokens > 0); } // You have at least half the token in O-like states if (state == State:O && state == State:OM) { - assert(getCacheEntry(addr).Tokens > (max_tokens() / 2)); + assert(cache_entry.Tokens > (max_tokens() / 2)); } - getCacheEntry(addr).CacheState := state; + 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) || @@ -353,9 +349,9 @@ machine(L1Cache, "Token protocol") (state == State:S_L) || (state == State:SM_L) || (state == State:OM)) { - changePermission(addr, AccessPermission:Read_Only); + cache_entry.changePermission(AccessPermission:Read_Only); } else { - changePermission(addr, AccessPermission:Invalid); + cache_entry.changePermission(AccessPermission:Invalid); } } } @@ -418,6 +414,16 @@ machine(L1Cache, "Token protocol") persistentTable.markEntries(addr); } + void setExternalResponse(TBE tbe) { + assert(is_valid(tbe)); + tbe.ExternalResponse := true; + } + + bool IsAtomic(TBE tbe) { + assert(is_valid(tbe)); + return tbe.IsAtomic; + } + // ** OUT_PORTS ** out_port(persistentNetwork_out, PersistentMsg, persistentFromL1Cache); out_port(requestNetwork_out, RequestMsg, requestFromL1Cache); @@ -429,18 +435,24 @@ machine(L1Cache, "Token protocol") // Use Timer in_port(useTimerTable_in, Address, useTimerTable) { if (useTimerTable_in.isReady()) { - if (persistentTable.isLocked(useTimerTable.readyAddress()) && (persistentTable.findSmallest(useTimerTable.readyAddress()) != machineID)) { + TBE tbe := L1_TBEs[useTimerTable.readyAddress()]; + + if (persistentTable.isLocked(useTimerTable.readyAddress()) && + (persistentTable.findSmallest(useTimerTable.readyAddress()) != machineID)) { if (persistentTable.typeOfSmallest(useTimerTable.readyAddress()) == AccessType:Write) { - trigger(Event:Use_TimeoutStarverX, useTimerTable.readyAddress()); + trigger(Event:Use_TimeoutStarverX, useTimerTable.readyAddress(), + getCacheEntry(useTimerTable.readyAddress()), tbe); } else { - trigger(Event:Use_TimeoutStarverS, useTimerTable.readyAddress()); + trigger(Event:Use_TimeoutStarverS, useTimerTable.readyAddress(), + getCacheEntry(useTimerTable.readyAddress()), tbe); } } else { - assert(L1_TBEs.isPresent(useTimerTable.readyAddress())); - if (no_mig_atomic && L1_TBEs[useTimerTable.readyAddress()].IsAtomic) { - trigger(Event:Use_TimeoutNoStarvers_NoMig, useTimerTable.readyAddress()); + if (no_mig_atomic && IsAtomic(tbe)) { + trigger(Event:Use_TimeoutNoStarvers_NoMig, useTimerTable.readyAddress(), + getCacheEntry(useTimerTable.readyAddress()), tbe); } else { - trigger(Event:Use_TimeoutNoStarvers, useTimerTable.readyAddress()); + trigger(Event:Use_TimeoutNoStarvers, useTimerTable.readyAddress(), + getCacheEntry(useTimerTable.readyAddress()), tbe); } } } @@ -449,7 +461,9 @@ machine(L1Cache, "Token protocol") // Reissue Timer in_port(reissueTimerTable_in, Address, reissueTimerTable) { if (reissueTimerTable_in.isReady()) { - trigger(Event:Request_Timeout, reissueTimerTable.readyAddress()); + trigger(Event:Request_Timeout, reissueTimerTable.readyAddress(), + getCacheEntry(reissueTimerTable.readyAddress()), + L1_TBEs[reissueTimerTable.readyAddress()]); } } @@ -473,25 +487,33 @@ machine(L1Cache, "Token protocol") } // React to the message based on the current state of the table + Entry cache_entry := getCacheEntry(in_msg.Address); + TBE tbe := L1_TBEs[in_msg.Address]; + if (persistentTable.isLocked(in_msg.Address)) { if (persistentTable.findSmallest(in_msg.Address) == machineID) { // Our Own Lock - this processor is highest priority - trigger(Event:Own_Lock_or_Unlock, in_msg.Address); + trigger(Event:Own_Lock_or_Unlock, in_msg.Address, + cache_entry, tbe); } else { if (persistentTable.typeOfSmallest(in_msg.Address) == AccessType:Read) { - if (getTokens(in_msg.Address) == 1 || - getTokens(in_msg.Address) == (max_tokens() / 2) + 1) { - trigger(Event:Persistent_GETS_Last_Token, in_msg.Address); + if (getTokens(cache_entry) == 1 || + getTokens(cache_entry) == (max_tokens() / 2) + 1) { + trigger(Event:Persistent_GETS_Last_Token, in_msg.Address, + cache_entry, tbe); } else { - trigger(Event:Persistent_GETS, in_msg.Address); + trigger(Event:Persistent_GETS, in_msg.Address, + cache_entry, tbe); } } else { - trigger(Event:Persistent_GETX, in_msg.Address); + trigger(Event:Persistent_GETX, in_msg.Address, + cache_entry, tbe); } } } else { // Unlock case - no entries in the table - trigger(Event:Own_Lock_or_Unlock, in_msg.Address); + trigger(Event:Own_Lock_or_Unlock, in_msg.Address, + cache_entry, tbe); } } } @@ -503,29 +525,39 @@ machine(L1Cache, "Token protocol") if (requestNetwork_in.isReady()) { peek(requestNetwork_in, RequestMsg, block_on="Address") { assert(in_msg.Destination.isElement(machineID)); + + Entry cache_entry := getCacheEntry(in_msg.Address); + TBE tbe := L1_TBEs[in_msg.Address]; + if (in_msg.Type == CoherenceRequestType:GETX) { if (in_msg.isLocal) { - trigger(Event:Transient_Local_GETX, in_msg.Address); + trigger(Event:Transient_Local_GETX, in_msg.Address, + cache_entry, tbe); } else { - trigger(Event:Transient_GETX, in_msg.Address); + trigger(Event:Transient_GETX, in_msg.Address, + cache_entry, tbe); } } else if (in_msg.Type == CoherenceRequestType:GETS) { - if (getTokens(in_msg.Address) == 1 || - getTokens(in_msg.Address) == (max_tokens() / 2) + 1) { + if (getTokens(cache_entry) == 1 || + getTokens(cache_entry) == (max_tokens() / 2) + 1) { if (in_msg.isLocal) { - trigger(Event:Transient_Local_GETS_Last_Token, in_msg.Address); + trigger(Event:Transient_Local_GETS_Last_Token, in_msg.Address, + cache_entry, tbe); } else { - trigger(Event:Transient_GETS_Last_Token, in_msg.Address); + trigger(Event:Transient_GETS_Last_Token, in_msg.Address, + cache_entry, tbe); } } else { if (in_msg.isLocal) { - trigger(Event:Transient_Local_GETS, in_msg.Address); + trigger(Event:Transient_Local_GETS, in_msg.Address, + cache_entry, tbe); } else { - trigger(Event:Transient_GETS, in_msg.Address); + trigger(Event:Transient_GETS, in_msg.Address, + cache_entry, tbe); } } } else { @@ -541,6 +573,9 @@ machine(L1Cache, "Token protocol") 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 ) { @@ -550,7 +585,7 @@ machine(L1Cache, "Token protocol") l2_select_num_bits)) { // came from an off-chip L2 cache - if (L1_TBEs.isPresent(in_msg.Address)) { + if (is_valid(tbe)) { // L1_TBEs[in_msg.Address].ExternalResponse := true; // profile_offchipL2_response(in_msg.Address); } @@ -559,14 +594,14 @@ machine(L1Cache, "Token protocol") // profile_onchipL2_response(in_msg.Address ); } } else if ( machineIDToMachineType(in_msg.Sender) == MachineType:Directory ) { - if (L1_TBEs.isPresent(in_msg.Address)) { - L1_TBEs[in_msg.Address].ExternalResponse := true; + 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 (L1_TBEs.isPresent(in_msg.Address)) { - // L1_TBEs[in_msg.Address].ExternalResponse := true; + //if (is_valid(tbe)) { + // tbe.ExternalResponse := true; // profile_offchipL1_response(in_msg.Address ); //} //} @@ -578,24 +613,24 @@ machine(L1Cache, "Token protocol") } - if (getTokens(in_msg.Address) + in_msg.Tokens != max_tokens()) { + 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); + trigger(Event:Ack, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER) { - trigger(Event:Data_Owner, in_msg.Address); + 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); + 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); + 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); + trigger(Event:Data_All_Tokens, in_msg.Address, cache_entry, tbe); } else { error("Unexpected message"); } @@ -610,46 +645,65 @@ machine(L1Cache, "Token protocol") peek(mandatoryQueue_in, CacheMsg, block_on="LineAddress") { // Check for data access to blocks in I-cache and ifetchs to blocks in D-cache + TBE tbe := L1_TBEs[in_msg.LineAddress]; + if (in_msg.Type == CacheRequestType:IFETCH) { // ** INSTRUCTION ACCESS *** // Check to see if it is in the OTHER L1 - if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); + if (is_valid(L1Dcache_entry)) { // The block is in the wrong L1, try to write it to the L2 - trigger(Event:L1_Replacement, in_msg.LineAddress); + trigger(Event:L1_Replacement, in_msg.LineAddress, + L1Dcache_entry, tbe); } - if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); + if (is_valid(L1Icache_entry)) { // The tag matches for the L1, so the L1 fetches the line. We know it can't be in the L2 due to exclusion - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Icache_entry, tbe); } else { if (L1IcacheMemory.cacheAvail(in_msg.LineAddress)) { // L1 does't have the line, but we have space for it in the L1 - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Icache_entry, tbe); } else { // No room in the L1, so we need to make room - trigger(Event:L1_Replacement, L1IcacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:L1_Replacement, + L1IcacheMemory.cacheProbe(in_msg.LineAddress), + getL1ICacheEntry(L1IcacheMemory.cacheProbe(in_msg.LineAddress)), + L1_TBEs[L1IcacheMemory.cacheProbe(in_msg.LineAddress)]); } } } else { // *** DATA ACCESS *** // Check to see if it is in the OTHER L1 - if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); + + if (is_valid(L1Icache_entry)) { // The block is in the wrong L1, try to write it to the L2 - trigger(Event:L1_Replacement, in_msg.LineAddress); + trigger(Event:L1_Replacement, in_msg.LineAddress, + L1Icache_entry, tbe); } - if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); + if (is_valid(L1Dcache_entry)) { // The tag matches for the L1, so the L1 fetches the line. We know it can't be in the L2 due to exclusion - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Dcache_entry, tbe); } else { if (L1DcacheMemory.cacheAvail(in_msg.LineAddress)) { // L1 does't have the line, but we have space for it in the L1 - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Dcache_entry, tbe); } else { // No room in the L1, so we need to make room - trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:L1_Replacement, + L1DcacheMemory.cacheProbe(in_msg.LineAddress), + getL1DCacheEntry(L1DcacheMemory.cacheProbe(in_msg.LineAddress)), + L1_TBEs[L1DcacheMemory.cacheProbe(in_msg.LineAddress)]); } } } @@ -660,13 +714,14 @@ machine(L1Cache, "Token protocol") // ACTIONS action(a_issueReadRequest, "a", desc="Issue GETS") { - if (L1_TBEs[address].IssueCount == 0) { + assert(is_valid(tbe)); + if (tbe.IssueCount == 0) { // Update outstanding requests //profile_outstanding_request(outstandingRequests); outstandingRequests := outstandingRequests + 1; } - if (L1_TBEs[address].IssueCount >= retry_threshold) { + if (tbe.IssueCount >= retry_threshold) { // Issue a persistent request if possible if (okToIssueStarving(address, machineID) && (starving == false)) { enqueue(persistentNetwork_out, PersistentMsg, latency = l1_request_latency) { @@ -689,14 +744,14 @@ machine(L1Cache, "Token protocol") out_msg.Destination.add(map_Address_to_Directory(address)); out_msg.MessageSize := MessageSizeType:Persistent_Control; - out_msg.Prefetch := L1_TBEs[address].Prefetch; - out_msg.AccessMode := L1_TBEs[address].AccessMode; + out_msg.Prefetch := tbe.Prefetch; + out_msg.AccessMode := tbe.AccessMode; } markPersistentEntries(address); starving := true; - if (L1_TBEs[address].IssueCount == 0) { - //profile_persistent_prediction(address, L1_TBEs[address].AccessType); + if (tbe.IssueCount == 0) { + //profile_persistent_prediction(address, tbe.AccessType); } // Update outstanding requests @@ -704,9 +759,9 @@ machine(L1Cache, "Token protocol") outstandingPersistentRequests := outstandingPersistentRequests + 1; // Increment IssueCount - L1_TBEs[address].IssueCount := L1_TBEs[address].IssueCount + 1; + tbe.IssueCount := tbe.IssueCount + 1; - L1_TBEs[address].WentPersistent := true; + tbe.WentPersistent := true; // Do not schedule a wakeup, a persistent requests will always complete } @@ -731,14 +786,14 @@ machine(L1Cache, "Token protocol") l2_select_low_bit, l2_select_num_bits)); - out_msg.RetryNum := L1_TBEs[address].IssueCount; - if (L1_TBEs[address].IssueCount == 0) { + out_msg.RetryNum := tbe.IssueCount; + if (tbe.IssueCount == 0) { out_msg.MessageSize := MessageSizeType:Request_Control; } else { out_msg.MessageSize := MessageSizeType:Reissue_Control; } - out_msg.Prefetch := L1_TBEs[address].Prefetch; - out_msg.AccessMode := L1_TBEs[address].AccessMode; + out_msg.Prefetch := tbe.Prefetch; + out_msg.AccessMode := tbe.AccessMode; } // send to other local L1s, with local bit set @@ -753,19 +808,19 @@ machine(L1Cache, "Token protocol") out_msg.Destination.broadcast(MachineType:L1Cache); out_msg.Destination.remove(machineID); - out_msg.RetryNum := L1_TBEs[address].IssueCount; + out_msg.RetryNum := tbe.IssueCount; out_msg.isLocal := true; - if (L1_TBEs[address].IssueCount == 0) { + if (tbe.IssueCount == 0) { out_msg.MessageSize := MessageSizeType:Broadcast_Control; } else { out_msg.MessageSize := MessageSizeType:Broadcast_Control; } - out_msg.Prefetch := L1_TBEs[address].Prefetch; - out_msg.AccessMode := L1_TBEs[address].AccessMode; + out_msg.Prefetch := tbe.Prefetch; + out_msg.AccessMode := tbe.AccessMode; } // Increment IssueCount - L1_TBEs[address].IssueCount := L1_TBEs[address].IssueCount + 1; + tbe.IssueCount := tbe.IssueCount + 1; // Set a wakeup timer @@ -780,13 +835,14 @@ machine(L1Cache, "Token protocol") action(b_issueWriteRequest, "b", desc="Issue GETX") { - if (L1_TBEs[address].IssueCount == 0) { + assert(is_valid(tbe)); + if (tbe.IssueCount == 0) { // Update outstanding requests //profile_outstanding_request(outstandingRequests); outstandingRequests := outstandingRequests + 1; } - if (L1_TBEs[address].IssueCount >= retry_threshold) { + if (tbe.IssueCount >= retry_threshold) { // Issue a persistent request if possible if ( okToIssueStarving(address, machineID) && (starving == false)) { enqueue(persistentNetwork_out, PersistentMsg, latency = l1_request_latency) { @@ -809,8 +865,8 @@ machine(L1Cache, "Token protocol") out_msg.Destination.add(map_Address_to_Directory(address)); out_msg.MessageSize := MessageSizeType:Persistent_Control; - out_msg.Prefetch := L1_TBEs[address].Prefetch; - out_msg.AccessMode := L1_TBEs[address].AccessMode; + out_msg.Prefetch := tbe.Prefetch; + out_msg.AccessMode := tbe.AccessMode; } markPersistentEntries(address); starving := true; @@ -819,14 +875,14 @@ machine(L1Cache, "Token protocol") //profile_outstanding_persistent_request(outstandingPersistentRequests); outstandingPersistentRequests := outstandingPersistentRequests + 1; - if (L1_TBEs[address].IssueCount == 0) { - //profile_persistent_prediction(address, L1_TBEs[address].AccessType); + if (tbe.IssueCount == 0) { + //profile_persistent_prediction(address, tbe.AccessType); } // Increment IssueCount - L1_TBEs[address].IssueCount := L1_TBEs[address].IssueCount + 1; + tbe.IssueCount := tbe.IssueCount + 1; - L1_TBEs[address].WentPersistent := true; + tbe.WentPersistent := true; // Do not schedule a wakeup, a persistent requests will always complete } @@ -853,15 +909,15 @@ machine(L1Cache, "Token protocol") l2_select_low_bit, l2_select_num_bits)); - out_msg.RetryNum := L1_TBEs[address].IssueCount; + out_msg.RetryNum := tbe.IssueCount; - if (L1_TBEs[address].IssueCount == 0) { + if (tbe.IssueCount == 0) { out_msg.MessageSize := MessageSizeType:Request_Control; } else { out_msg.MessageSize := MessageSizeType:Reissue_Control; } - out_msg.Prefetch := L1_TBEs[address].Prefetch; - out_msg.AccessMode := L1_TBEs[address].AccessMode; + out_msg.Prefetch := tbe.Prefetch; + out_msg.AccessMode := tbe.AccessMode; } // send to other local L1s too @@ -878,21 +934,21 @@ machine(L1Cache, "Token protocol") out_msg.Destination.broadcast(MachineType:L1Cache); out_msg.Destination.remove(machineID); - out_msg.RetryNum := L1_TBEs[address].IssueCount; - if (L1_TBEs[address].IssueCount == 0) { + out_msg.RetryNum := tbe.IssueCount; + if (tbe.IssueCount == 0) { out_msg.MessageSize := MessageSizeType:Broadcast_Control; } else { out_msg.MessageSize := MessageSizeType:Broadcast_Control; } - out_msg.Prefetch := L1_TBEs[address].Prefetch; - out_msg.AccessMode := L1_TBEs[address].AccessMode; + out_msg.Prefetch := tbe.Prefetch; + out_msg.AccessMode := tbe.AccessMode; } // Increment IssueCount - L1_TBEs[address].IssueCount := L1_TBEs[address].IssueCount + 1; + tbe.IssueCount := tbe.IssueCount + 1; DPRINTF(RubySlicc, "incremented issue count to %d\n", - L1_TBEs[address].IssueCount); + tbe.IssueCount); // Set a wakeup timer if (dynamic_timeout_enabled) { @@ -920,6 +976,7 @@ machine(L1Cache, "Token protocol") } action(c_ownedReplacement, "c", desc="Issue writeback") { + assert(is_valid(cache_entry)); enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Sender := machineID; @@ -929,21 +986,22 @@ machine(L1Cache, "Token protocol") l2_select_low_bit, l2_select_num_bits)); - out_msg.Tokens := getCacheEntry(address).Tokens; - out_msg.DataBlk := getCacheEntry(address).DataBlk; - out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.Type := CoherenceResponseType:WB_OWNED; // always send the data? out_msg.MessageSize := MessageSizeType:Writeback_Data; } - getCacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(cc_sharedReplacement, "\c", desc="Issue shared writeback") { // don't send writeback if replacing block with no tokens - assert (getCacheEntry(address).Tokens > 0); + assert(is_valid(cache_entry)); + assert (cache_entry.Tokens > 0); enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Sender := machineID; @@ -953,19 +1011,20 @@ machine(L1Cache, "Token protocol") l2_select_low_bit, l2_select_num_bits)); - out_msg.Tokens := getCacheEntry(address).Tokens; - out_msg.DataBlk := getCacheEntry(address).DataBlk; - // assert(getCacheEntry(address).Dirty == false); + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; + // assert(cache_entry.Dirty == false); out_msg.Dirty := false; out_msg.MessageSize := MessageSizeType:Writeback_Data; out_msg.Type := CoherenceResponseType:WB_SHARED_DATA; } - getCacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(tr_tokenReplacement, "tr", desc="Issue token writeback") { - if (getCacheEntry(address).Tokens > 0) { + assert(is_valid(cache_entry)); + if (cache_entry.Tokens > 0) { enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Sender := machineID; @@ -975,9 +1034,9 @@ machine(L1Cache, "Token protocol") l2_select_low_bit, l2_select_num_bits)); - out_msg.Tokens := getCacheEntry(address).Tokens; - out_msg.DataBlk := getCacheEntry(address).DataBlk; - // assert(getCacheEntry(address).Dirty == false); + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; + // assert(cache_entry.Dirty == false); out_msg.Dirty := false; // always send the data? @@ -985,11 +1044,12 @@ machine(L1Cache, "Token protocol") out_msg.Type := CoherenceResponseType:WB_TOKENS; } } - getCacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(d_sendDataWithToken, "d", desc="Send data and a token from cache to requestor") { + assert(is_valid(cache_entry)); peek(requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; @@ -997,8 +1057,8 @@ machine(L1Cache, "Token protocol") out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); out_msg.Tokens := 1; - out_msg.DataBlk := getCacheEntry(address).DataBlk; - // out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + // out_msg.Dirty := cache_entry.Dirty; out_msg.Dirty := false; if (in_msg.isLocal) { out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; @@ -1007,21 +1067,22 @@ machine(L1Cache, "Token protocol") } } } - getCacheEntry(address).Tokens := getCacheEntry(address).Tokens - 1; - assert(getCacheEntry(address).Tokens >= 1); + cache_entry.Tokens := cache_entry.Tokens - 1; + assert(cache_entry.Tokens >= 1); } action(d_sendDataWithNTokenIfAvail, "\dd", desc="Send data and a token from cache to requestor") { + assert(is_valid(cache_entry)); peek(requestNetwork_in, RequestMsg) { - if (getCacheEntry(address).Tokens > (N_tokens + (max_tokens() / 2))) { + if (cache_entry.Tokens > (N_tokens + (max_tokens() / 2))) { enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); out_msg.Tokens := N_tokens; - out_msg.DataBlk := getCacheEntry(address).DataBlk; - // out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + // out_msg.Dirty := cache_entry.Dirty; out_msg.Dirty := false; if (in_msg.isLocal) { out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; @@ -1029,17 +1090,17 @@ machine(L1Cache, "Token protocol") out_msg.MessageSize := MessageSizeType:Response_Data; } } - getCacheEntry(address).Tokens := getCacheEntry(address).Tokens - N_tokens; + cache_entry.Tokens := cache_entry.Tokens - N_tokens; } - else if (getCacheEntry(address).Tokens > 1) { + else if (cache_entry.Tokens > 1) { enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); out_msg.Tokens := 1; - out_msg.DataBlk := getCacheEntry(address).DataBlk; - // out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + // out_msg.Dirty := cache_entry.Dirty; out_msg.Dirty := false; if (in_msg.isLocal) { out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; @@ -1047,23 +1108,24 @@ machine(L1Cache, "Token protocol") out_msg.MessageSize := MessageSizeType:Response_Data; } } - getCacheEntry(address).Tokens := getCacheEntry(address).Tokens - 1; + cache_entry.Tokens := cache_entry.Tokens - 1; } } -// assert(getCacheEntry(address).Tokens >= 1); +// assert(cache_entry.Tokens >= 1); } action(dd_sendDataWithAllTokens, "\d", desc="Send data and all tokens from cache to requestor") { peek(requestNetwork_in, RequestMsg) { + assert(is_valid(cache_entry)); enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - assert(getCacheEntry(address).Tokens > (max_tokens() / 2)); - out_msg.Tokens := getCacheEntry(address).Tokens; - out_msg.DataBlk := getCacheEntry(address).DataBlk; - out_msg.Dirty := getCacheEntry(address).Dirty; + assert(cache_entry.Tokens > (max_tokens() / 2)); + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; if (in_msg.isLocal) { out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; } else { @@ -1071,116 +1133,121 @@ machine(L1Cache, "Token protocol") } } } - getCacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(e_sendAckWithCollectedTokens, "e", desc="Send ack with the tokens we've collected thus far.") { // assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself - if (getCacheEntry(address).Tokens > 0) { + assert(is_valid(cache_entry)); + if (cache_entry.Tokens > 0) { enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; - if (getCacheEntry(address).Tokens > (max_tokens() / 2)) { + if (cache_entry.Tokens > (max_tokens() / 2)) { out_msg.Type := CoherenceResponseType:DATA_OWNER; } else { out_msg.Type := CoherenceResponseType:ACK; } out_msg.Sender := machineID; out_msg.Destination.add(persistentTable.findSmallest(address)); - assert(getCacheEntry(address).Tokens >= 1); - out_msg.Tokens := getCacheEntry(address).Tokens; - out_msg.DataBlk := getCacheEntry(address).DataBlk; + assert(cache_entry.Tokens >= 1); + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; out_msg.MessageSize := MessageSizeType:Response_Control; } } - getCacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(ee_sendDataWithAllTokens, "\e", desc="Send data and all tokens from cache to starver") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself - assert(getCacheEntry(address).Tokens > 0); + assert(is_valid(cache_entry)); + assert(cache_entry.Tokens > 0); enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.Destination.add(persistentTable.findSmallest(address)); - assert(getCacheEntry(address).Tokens > (max_tokens() / 2)); - out_msg.Tokens := getCacheEntry(address).Tokens; - out_msg.DataBlk := getCacheEntry(address).DataBlk; - out_msg.Dirty := getCacheEntry(address).Dirty; + assert(cache_entry.Tokens > (max_tokens() / 2)); + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } - getCacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(f_sendAckWithAllButNorOneTokens, "f", desc="Send ack with all our tokens but one to starver.") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself - assert(getCacheEntry(address).Tokens > 0); - if (getCacheEntry(address).Tokens > 1) { + assert(is_valid(cache_entry)); + assert(cache_entry.Tokens > 0); + if (cache_entry.Tokens > 1) { enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; - if (getCacheEntry(address).Tokens > (max_tokens() / 2)) { + if (cache_entry.Tokens > (max_tokens() / 2)) { out_msg.Type := CoherenceResponseType:DATA_OWNER; } else { out_msg.Type := CoherenceResponseType:ACK; } out_msg.Sender := machineID; out_msg.Destination.add(persistentTable.findSmallest(address)); - assert(getCacheEntry(address).Tokens >= 1); - if (getCacheEntry(address).Tokens > N_tokens) { - out_msg.Tokens := getCacheEntry(address).Tokens - N_tokens; + assert(cache_entry.Tokens >= 1); + if (cache_entry.Tokens > N_tokens) { + out_msg.Tokens := cache_entry.Tokens - N_tokens; } else { - out_msg.Tokens := getCacheEntry(address).Tokens - 1; + out_msg.Tokens := cache_entry.Tokens - 1; } - out_msg.DataBlk := getCacheEntry(address).DataBlk; + out_msg.DataBlk := cache_entry.DataBlk; out_msg.MessageSize := MessageSizeType:Response_Control; } } - if (getCacheEntry(address).Tokens > N_tokens) { - getCacheEntry(address).Tokens := N_tokens; + if (cache_entry.Tokens > N_tokens) { + cache_entry.Tokens := N_tokens; } else { - getCacheEntry(address).Tokens := 1; + cache_entry.Tokens := 1; } } action(ff_sendDataWithAllButNorOneTokens, "\f", desc="Send data and out tokens but one to starver") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself - assert(getCacheEntry(address).Tokens > ((max_tokens() / 2) + 1)); + assert(is_valid(cache_entry)); + assert(cache_entry.Tokens > ((max_tokens() / 2) + 1)); enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.Destination.add(persistentTable.findSmallest(address)); - if (getCacheEntry(address).Tokens > (N_tokens + (max_tokens() / 2))) { - out_msg.Tokens := getCacheEntry(address).Tokens - N_tokens; + if (cache_entry.Tokens > (N_tokens + (max_tokens() / 2))) { + out_msg.Tokens := cache_entry.Tokens - N_tokens; } else { - out_msg.Tokens := getCacheEntry(address).Tokens - 1; + out_msg.Tokens := cache_entry.Tokens - 1; } assert(out_msg.Tokens > (max_tokens() / 2)); - out_msg.DataBlk := getCacheEntry(address).DataBlk; - out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } - if (getCacheEntry(address).Tokens > (N_tokens + (max_tokens() / 2))) { - getCacheEntry(address).Tokens := N_tokens; + if (cache_entry.Tokens > (N_tokens + (max_tokens() / 2))) { + cache_entry.Tokens := N_tokens; } else { - getCacheEntry(address).Tokens := 1; + cache_entry.Tokens := 1; } } action(fo_sendDataWithOwnerToken, "fo", desc="Send data and owner tokens") { - assert(getCacheEntry(address).Tokens == ((max_tokens() / 2) + 1)); + assert(is_valid(cache_entry)); + assert(cache_entry.Tokens == ((max_tokens() / 2) + 1)); enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.Destination.add(persistentTable.findSmallest(address)); - out_msg.Tokens := getCacheEntry(address).Tokens; + out_msg.Tokens := cache_entry.Tokens; assert(out_msg.Tokens > (max_tokens() / 2)); - out_msg.DataBlk := getCacheEntry(address).DataBlk; - out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } - getCacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(g_bounceResponseToStarver, "g", desc="Redirect response to starving processor") { @@ -1204,67 +1271,72 @@ machine(L1Cache, "Token protocol") action(h_load_hit, "h", desc="Notify sequencer the load completed.") { + assert(is_valid(cache_entry)); DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, getCacheEntry(address).DataBlk); + address, cache_entry.DataBlk); sequencer.readCallback(address, GenericMachineType:L1Cache, - getCacheEntry(address).DataBlk); + cache_entry.DataBlk); } action(x_external_load_hit, "x", desc="Notify sequencer the load completed.") { + assert(is_valid(cache_entry)); DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, getCacheEntry(address).DataBlk); + address, cache_entry.DataBlk); peek(responseNetwork_in, ResponseMsg) { sequencer.readCallback(address, getNondirectHitMachType(address, in_msg.Sender), - getCacheEntry(address).DataBlk); + cache_entry.DataBlk); } } action(hh_store_hit, "\h", desc="Notify sequencer that store completed.") { + assert(is_valid(cache_entry)); DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, getCacheEntry(address).DataBlk); + address, cache_entry.DataBlk); sequencer.writeCallback(address, GenericMachineType:L1Cache, - getCacheEntry(address).DataBlk); + cache_entry.DataBlk); - getCacheEntry(address).Dirty := true; - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); + cache_entry.Dirty := true; + DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); } action(xx_external_store_hit, "\x", desc="Notify sequencer that store completed.") { + assert(is_valid(cache_entry)); DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", - address, getCacheEntry(address).DataBlk); + address, cache_entry.DataBlk); peek(responseNetwork_in, ResponseMsg) { sequencer.writeCallback(address, getNondirectHitMachType(address, in_msg.Sender), - getCacheEntry(address).DataBlk); + cache_entry.DataBlk); } - getCacheEntry(address).Dirty := true; - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); + cache_entry.Dirty := true; + DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); } action(i_allocateTBE, "i", desc="Allocate TBE") { check_allocate(L1_TBEs); L1_TBEs.allocate(address); - L1_TBEs[address].IssueCount := 0; + set_tbe(L1_TBEs[address]); + tbe.IssueCount := 0; peek(mandatoryQueue_in, CacheMsg) { - L1_TBEs[address].PC := in_msg.ProgramCounter; - L1_TBEs[address].AccessType := cache_request_type_to_access_type(in_msg.Type); + tbe.PC := in_msg.ProgramCounter; + tbe.AccessType := cache_request_type_to_access_type(in_msg.Type); if (in_msg.Type == CacheRequestType:ATOMIC) { - L1_TBEs[address].IsAtomic := true; + tbe.IsAtomic := true; } - L1_TBEs[address].Prefetch := in_msg.Prefetch; - L1_TBEs[address].AccessMode := in_msg.AccessMode; + tbe.Prefetch := in_msg.Prefetch; + tbe.AccessMode := in_msg.AccessMode; } - L1_TBEs[address].IssueTime := get_time(); + tbe.IssueTime := get_time(); } @@ -1317,21 +1389,23 @@ machine(L1Cache, "Token protocol") action(q_updateTokensFromResponse, "q", desc="Update the token count based on the incoming response message") { peek(responseNetwork_in, ResponseMsg) { + assert(is_valid(cache_entry)); assert(in_msg.Tokens != 0); DPRINTF(RubySlicc, "L1 received tokens for address: %s, tokens: %d\n", in_msg.Address, in_msg.Tokens); - getCacheEntry(address).Tokens := getCacheEntry(address).Tokens + in_msg.Tokens; - DPRINTF(RubySlicc, "%d\n", getCacheEntry(address).Tokens); + cache_entry.Tokens := cache_entry.Tokens + in_msg.Tokens; + DPRINTF(RubySlicc, "%d\n", cache_entry.Tokens); - if (getCacheEntry(address).Dirty == false && in_msg.Dirty) { - getCacheEntry(address).Dirty := true; + if (cache_entry.Dirty == false && in_msg.Dirty) { + cache_entry.Dirty := true; } } } action(s_deallocateTBE, "s", desc="Deallocate TBE") { - if (L1_TBEs[address].WentPersistent) { + assert(is_valid(tbe)); + if (tbe.WentPersistent) { // assert(starving == true); outstandingRequests := outstandingRequests - 1; enqueue(persistentNetwork_out, PersistentMsg, latency = l1_request_latency) { @@ -1359,74 +1433,80 @@ machine(L1Cache, "Token protocol") } // Update average latency - if (L1_TBEs[address].IssueCount <= 1) { - if (L1_TBEs[address].ExternalResponse == true) { - updateAverageLatencyEstimate(time_to_int(get_time()) - time_to_int(L1_TBEs[address].IssueTime)); + if (tbe.IssueCount <= 1) { + if (tbe.ExternalResponse == true) { + updateAverageLatencyEstimate(time_to_int(get_time()) - time_to_int(tbe.IssueTime)); } } // Profile - //if (L1_TBEs[address].WentPersistent) { - // profile_token_retry(address, L1_TBEs[address].AccessType, 2); + //if (tbe.WentPersistent) { + // profile_token_retry(address, tbe.AccessType, 2); //} //else { - // profile_token_retry(address, L1_TBEs[address].AccessType, 1); + // profile_token_retry(address, tbe.AccessType, 1); //} - //profile_token_retry(address, L1_TBEs[address].AccessType, L1_TBEs[address].IssueCount); + //profile_token_retry(address, tbe.AccessType, tbe.IssueCount); L1_TBEs.deallocate(address); + unset_tbe(); } action(t_sendAckWithCollectedTokens, "t", desc="Send ack with the tokens we've collected thus far.") { - if (getCacheEntry(address).Tokens > 0) { + assert(is_valid(cache_entry)); + if (cache_entry.Tokens > 0) { peek(requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; - if (getCacheEntry(address).Tokens > (max_tokens() / 2)) { + if (cache_entry.Tokens > (max_tokens() / 2)) { out_msg.Type := CoherenceResponseType:DATA_OWNER; } else { out_msg.Type := CoherenceResponseType:ACK; } out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - assert(getCacheEntry(address).Tokens >= 1); - out_msg.Tokens := getCacheEntry(address).Tokens; - out_msg.DataBlk := getCacheEntry(address).DataBlk; + assert(cache_entry.Tokens >= 1); + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; out_msg.MessageSize := MessageSizeType:Response_Control; } } } - getCacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(u_writeDataToCache, "u", desc="Write data to cache") { peek(responseNetwork_in, ResponseMsg) { - getCacheEntry(address).DataBlk := in_msg.DataBlk; - if (getCacheEntry(address).Dirty == false && in_msg.Dirty) { - getCacheEntry(address).Dirty := in_msg.Dirty; + assert(is_valid(cache_entry)); + cache_entry.DataBlk := in_msg.DataBlk; + if (cache_entry.Dirty == false && in_msg.Dirty) { + cache_entry.Dirty := in_msg.Dirty; } } } action(gg_deallocateL1CacheBlock, "\g", desc="Deallocate cache block. Sets the cache to invalid, allowing a replacement in parallel with a fetch.") { - assert(getTokens(address) == 0); + assert(getTokens(cache_entry) == 0); if (L1DcacheMemory.isTagPresent(address)) { L1DcacheMemory.deallocate(address); } else { L1IcacheMemory.deallocate(address); } + unset_cache_entry(); } 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(cache_entry)) { + } else { + set_cache_entry(L1DcacheMemory.allocate(address, new Entry)); } } action(pp_allocateL1ICacheBlock, "\p", 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(cache_entry)) { + } else { + set_cache_entry(L1IcacheMemory.allocate(address, new Entry)); } } @@ -1442,7 +1522,8 @@ machine(L1Cache, "Token protocol") action(w_assertIncomingDataAndCacheDataMatch, "w", desc="Assert that the incoming data and the data in the cache match") { peek(responseNetwork_in, ResponseMsg) { - assert(getCacheEntry(address).DataBlk == in_msg.DataBlk); + assert(is_valid(cache_entry)); + assert(cache_entry.DataBlk == in_msg.DataBlk); } } diff --git a/src/mem/protocol/MOESI_CMP_token-L2cache.sm b/src/mem/protocol/MOESI_CMP_token-L2cache.sm index 3541da41b..c23f98f9a 100644 --- a/src/mem/protocol/MOESI_CMP_token-L2cache.sm +++ b/src/mem/protocol/MOESI_CMP_token-L2cache.sm @@ -148,35 +148,25 @@ machine(L2Cache, "Token protocol") PersistentTable persistentTable; PerfectCacheMemory localDirectory, template_hack="<L2Cache_DirEntry>"; - Entry getL2CacheEntry(Address addr), return_by_ref="yes" { - if (L2cacheMemory.isTagPresent(addr)) { - return static_cast(Entry, L2cacheMemory[addr]); - } - assert(false); - return static_cast(Entry, L2cacheMemory[addr]); - } + void set_cache_entry(AbstractCacheEntry b); + void unset_cache_entry(); - int getTokens(Address addr) { - if (L2cacheMemory.isTagPresent(addr)) { - return getL2CacheEntry(addr).Tokens; + Entry getCacheEntry(Address address), return_by_pointer="yes" { + Entry cache_entry := static_cast(Entry, "pointer", L2cacheMemory.lookup(address)); + return cache_entry; + } + + int getTokens(Entry cache_entry) { + if (is_valid(cache_entry)) { + return cache_entry.Tokens; } else { return 0; } } - void changePermission(Address addr, AccessPermission permission) { - if (L2cacheMemory.isTagPresent(addr)) { - return L2cacheMemory.changePermission(addr, permission); - } - } - - bool isCacheTagPresent(Address addr) { - return (L2cacheMemory.isTagPresent(addr) ); - } - - State getState(Address addr) { - if (isCacheTagPresent(addr)) { - return getL2CacheEntry(addr).CacheState; + State getState(Entry cache_entry, Address addr) { + if (is_valid(cache_entry)) { + return cache_entry.CacheState; } else if (persistentTable.isLocked(addr) == true) { return State:I_L; } else { @@ -184,57 +174,50 @@ machine(L2Cache, "Token protocol") } } - std::string getStateStr(Address addr) { - return L2Cache_State_to_string(getState(addr)); - } - - void setState(Address addr, State state) { - + void setState(Entry cache_entry, Address addr, State state) { - if (isCacheTagPresent(addr)) { + if (is_valid(cache_entry)) { // Make sure the token count is in range - assert(getL2CacheEntry(addr).Tokens >= 0); - assert(getL2CacheEntry(addr).Tokens <= max_tokens()); - assert(getL2CacheEntry(addr).Tokens != (max_tokens() / 2)); + assert(cache_entry.Tokens >= 0); + assert(cache_entry.Tokens <= max_tokens()); + assert(cache_entry.Tokens != (max_tokens() / 2)); // Make sure we have no tokens in L if ((state == State:I_L) ) { - if (isCacheTagPresent(addr)) { - assert(getL2CacheEntry(addr).Tokens == 0); - } + assert(cache_entry.Tokens == 0); } // in M and E you have all the tokens if (state == State:M ) { - assert(getL2CacheEntry(addr).Tokens == max_tokens()); + assert(cache_entry.Tokens == max_tokens()); } // in NP you have no tokens if (state == State:NP) { - assert(getL2CacheEntry(addr).Tokens == 0); + assert(cache_entry.Tokens == 0); } // You have at least one token in S-like states if (state == State:S ) { - assert(getL2CacheEntry(addr).Tokens > 0); + assert(cache_entry.Tokens > 0); } // You have at least half the token in O-like states if (state == State:O ) { - assert(getL2CacheEntry(addr).Tokens > (max_tokens() / 2)); + assert(cache_entry.Tokens > (max_tokens() / 2)); } - getL2CacheEntry(addr).CacheState := state; + cache_entry.CacheState := state; // Set permission if (state == State:I) { - changePermission(addr, AccessPermission:Invalid); + cache_entry.changePermission(AccessPermission:Invalid); } else if (state == State:S || state == State:O ) { - changePermission(addr, AccessPermission:Read_Only); + cache_entry.changePermission(AccessPermission:Read_Only); } else if (state == State:M ) { - changePermission(addr, AccessPermission:Read_Write); + cache_entry.changePermission(AccessPermission:Read_Write); } else { - changePermission(addr, AccessPermission:Invalid); + cache_entry.changePermission(AccessPermission:Invalid); } } } @@ -341,22 +324,24 @@ machine(L2Cache, "Token protocol") error("Unexpected message"); } + Entry cache_entry := getCacheEntry(in_msg.Address); // React to the message based on the current state of the table if (persistentTable.isLocked(in_msg.Address)) { if (persistentTable.typeOfSmallest(in_msg.Address) == AccessType:Read) { - if (getTokens(in_msg.Address) == 1 || - getTokens(in_msg.Address) == (max_tokens() / 2) + 1) { - trigger(Event:Persistent_GETS_Last_Token, in_msg.Address); + if (getTokens(cache_entry) == 1 || + getTokens(cache_entry) == (max_tokens() / 2) + 1) { + trigger(Event:Persistent_GETS_Last_Token, in_msg.Address, + cache_entry); } else { - trigger(Event:Persistent_GETS, in_msg.Address); + trigger(Event:Persistent_GETS, in_msg.Address, cache_entry); } } else { - trigger(Event:Persistent_GETX, in_msg.Address); + trigger(Event:Persistent_GETX, in_msg.Address, cache_entry); } } else { - trigger(Event:Own_Lock_or_Unlock, in_msg.Address); + trigger(Event:Own_Lock_or_Unlock, in_msg.Address, cache_entry); } } } @@ -369,14 +354,16 @@ machine(L2Cache, "Token protocol") peek(requestNetwork_in, RequestMsg) { assert(in_msg.Destination.isElement(machineID)); + Entry cache_entry := getCacheEntry(in_msg.Address); if (in_msg.Type == CoherenceRequestType:GETX) { - trigger(Event:Transient_GETX, in_msg.Address); + trigger(Event:Transient_GETX, in_msg.Address, cache_entry); } else if (in_msg.Type == CoherenceRequestType:GETS) { - if (L2cacheMemory.isTagPresent(in_msg.Address) && getL2CacheEntry(in_msg.Address).Tokens == 1) { - trigger(Event:Transient_GETS_Last_Token, in_msg.Address); + if (getTokens(cache_entry) == 1) { + trigger(Event:Transient_GETS_Last_Token, in_msg.Address, + cache_entry); } else { - trigger(Event:Transient_GETS, in_msg.Address); + trigger(Event:Transient_GETS, in_msg.Address, cache_entry); } } else { error("Unexpected message"); @@ -389,15 +376,16 @@ machine(L2Cache, "Token protocol") if (L1requestNetwork_in.isReady()) { peek(L1requestNetwork_in, RequestMsg) { assert(in_msg.Destination.isElement(machineID)); + Entry cache_entry := getCacheEntry(in_msg.Address); if (in_msg.Type == CoherenceRequestType:GETX) { - trigger(Event:L1_GETX, in_msg.Address); + trigger(Event:L1_GETX, in_msg.Address, cache_entry); } else if (in_msg.Type == CoherenceRequestType:GETS) { - if (getTokens(in_msg.Address) == 1 || - getTokens(in_msg.Address) == (max_tokens() / 2) + 1) { - trigger(Event:L1_GETS_Last_Token, in_msg.Address); + if (getTokens(cache_entry) == 1 || + getTokens(cache_entry) == (max_tokens() / 2) + 1) { + trigger(Event:L1_GETS_Last_Token, in_msg.Address, cache_entry); } else { - trigger(Event:L1_GETS, in_msg.Address); + trigger(Event:L1_GETS, in_msg.Address, cache_entry); } } else { error("Unexpected message"); @@ -412,68 +400,80 @@ machine(L2Cache, "Token protocol") if (responseNetwork_in.isReady()) { peek(responseNetwork_in, ResponseMsg) { assert(in_msg.Destination.isElement(machineID)); - if (getTokens(in_msg.Address) + in_msg.Tokens != max_tokens()) { + Entry cache_entry := getCacheEntry(in_msg.Address); + + 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); + trigger(Event:Ack, in_msg.Address, cache_entry); } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER) { - trigger(Event:Data_Owner, in_msg.Address); + trigger(Event:Data_Owner, in_msg.Address, cache_entry); } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) { - trigger(Event:Data_Shared, in_msg.Address); - } else if (in_msg.Type == CoherenceResponseType:WB_TOKENS || in_msg.Type == CoherenceResponseType:WB_OWNED || in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { + trigger(Event:Data_Shared, in_msg.Address, cache_entry); + } else if (in_msg.Type == CoherenceResponseType:WB_TOKENS || + in_msg.Type == CoherenceResponseType:WB_OWNED || + in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { - if (L2cacheMemory.cacheAvail(in_msg.Address) || L2cacheMemory.isTagPresent(in_msg.Address)) { + if (L2cacheMemory.cacheAvail(in_msg.Address) || is_valid(cache_entry)) { // either room is available or the block is already present if (in_msg.Type == CoherenceResponseType:WB_TOKENS) { assert(in_msg.Dirty == false); - trigger(Event:Writeback_Tokens, in_msg.Address); + trigger(Event:Writeback_Tokens, in_msg.Address, cache_entry); } else if (in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { assert(in_msg.Dirty == false); - trigger(Event:Writeback_Shared_Data, in_msg.Address); + trigger(Event:Writeback_Shared_Data, in_msg.Address, cache_entry); } else if (in_msg.Type == CoherenceResponseType:WB_OWNED) { //assert(in_msg.Dirty == false); - trigger(Event:Writeback_Owned, in_msg.Address); + trigger(Event:Writeback_Owned, in_msg.Address, cache_entry); } } else { - trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address)); + trigger(Event:L2_Replacement, + L2cacheMemory.cacheProbe(in_msg.Address), + getCacheEntry(L2cacheMemory.cacheProbe(in_msg.Address))); } } else if (in_msg.Type == CoherenceResponseType:INV) { - trigger(Event:L1_INV, in_msg.Address); + trigger(Event:L1_INV, in_msg.Address, cache_entry); } 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); - } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER || in_msg.Type == CoherenceResponseType:DATA_SHARED) { - trigger(Event:Data_All_Tokens, in_msg.Address); - } else if (in_msg.Type == CoherenceResponseType:WB_TOKENS || in_msg.Type == CoherenceResponseType:WB_OWNED || in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { - if (L2cacheMemory.cacheAvail(in_msg.Address) || L2cacheMemory.isTagPresent(in_msg.Address)) { + trigger(Event:Ack_All_Tokens, in_msg.Address, cache_entry); + } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER || + in_msg.Type == CoherenceResponseType:DATA_SHARED) { + trigger(Event:Data_All_Tokens, in_msg.Address, cache_entry); + } else if (in_msg.Type == CoherenceResponseType:WB_TOKENS || + in_msg.Type == CoherenceResponseType:WB_OWNED || + in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { + if (L2cacheMemory.cacheAvail(in_msg.Address) || is_valid(cache_entry)) { // either room is available or the block is already present if (in_msg.Type == CoherenceResponseType:WB_TOKENS) { assert(in_msg.Dirty == false); - assert( (getState(in_msg.Address) != State:NP) && (getState(in_msg.Address) != State:I) ); - trigger(Event:Writeback_All_Tokens, in_msg.Address); + assert( (getState(cache_entry, in_msg.Address) != State:NP) + && (getState(cache_entry, in_msg.Address) != State:I) ); + trigger(Event:Writeback_All_Tokens, in_msg.Address, cache_entry); } else if (in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { assert(in_msg.Dirty == false); - trigger(Event:Writeback_All_Tokens, in_msg.Address); + trigger(Event:Writeback_All_Tokens, in_msg.Address, cache_entry); } else if (in_msg.Type == CoherenceResponseType:WB_OWNED) { - trigger(Event:Writeback_All_Tokens, in_msg.Address); + trigger(Event:Writeback_All_Tokens, in_msg.Address, cache_entry); } } else { - trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address)); + trigger(Event:L2_Replacement, + L2cacheMemory.cacheProbe(in_msg.Address), + getCacheEntry(L2cacheMemory.cacheProbe(in_msg.Address))); } } else if (in_msg.Type == CoherenceResponseType:INV) { - trigger(Event:L1_INV, in_msg.Address); + trigger(Event:L1_INV, in_msg.Address, cache_entry); } else { DPRINTF(RubySlicc, "%s\n", in_msg.Type); error("Unexpected message"); @@ -536,29 +536,31 @@ machine(L2Cache, "Token protocol") } action(c_cleanReplacement, "c", desc="Issue clean writeback") { - if (getL2CacheEntry(address).Tokens > 0) { + assert(is_valid(cache_entry)); + if (cache_entry.Tokens > 0) { enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; out_msg.Destination.add(map_Address_to_Directory(address)); - out_msg.Tokens := getL2CacheEntry(address).Tokens; + out_msg.Tokens := cache_entry.Tokens; out_msg.MessageSize := MessageSizeType:Writeback_Control; } - getL2CacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } } action(cc_dirtyReplacement, "\c", desc="Issue dirty writeback") { + assert(is_valid(cache_entry)); enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Sender := machineID; out_msg.Destination.add(map_Address_to_Directory(address)); - out_msg.Tokens := getL2CacheEntry(address).Tokens; - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; - if (getL2CacheEntry(address).Dirty) { + if (cache_entry.Dirty) { out_msg.MessageSize := MessageSizeType:Writeback_Data; out_msg.Type := CoherenceResponseType:DATA_OWNER; } else { @@ -566,23 +568,24 @@ machine(L2Cache, "Token protocol") out_msg.Type := CoherenceResponseType:ACK_OWNER; } } - getL2CacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(d_sendDataWithTokens, "d", desc="Send data and a token from cache to requestor") { peek(requestNetwork_in, RequestMsg) { - if (getL2CacheEntry(address).Tokens > (N_tokens + (max_tokens() / 2))) { + assert(is_valid(cache_entry)); + if (cache_entry.Tokens > (N_tokens + (max_tokens() / 2))) { enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); out_msg.Tokens := N_tokens; - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; + out_msg.DataBlk := cache_entry.DataBlk; out_msg.Dirty := false; out_msg.MessageSize := MessageSizeType:Response_Data; } - getL2CacheEntry(address).Tokens := getL2CacheEntry(address).Tokens - N_tokens; + cache_entry.Tokens := cache_entry.Tokens - N_tokens; } else { enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { @@ -591,109 +594,115 @@ machine(L2Cache, "Token protocol") out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); out_msg.Tokens := 1; - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; + out_msg.DataBlk := cache_entry.DataBlk; out_msg.Dirty := false; out_msg.MessageSize := MessageSizeType:Response_Data; } - getL2CacheEntry(address).Tokens := getL2CacheEntry(address).Tokens - 1; + cache_entry.Tokens := cache_entry.Tokens - 1; } } } action(dd_sendDataWithAllTokens, "\d", desc="Send data and all tokens from cache to requestor") { + assert(is_valid(cache_entry)); peek(requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - assert(getL2CacheEntry(address).Tokens >= 1); - out_msg.Tokens := getL2CacheEntry(address).Tokens; - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + assert(cache_entry.Tokens >= 1); + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } } - getL2CacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(e_sendAckWithCollectedTokens, "e", desc="Send ack with the tokens we've collected thus far.") { - if (getL2CacheEntry(address).Tokens > 0) { + assert(is_valid(cache_entry)); + if (cache_entry.Tokens > 0) { enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; out_msg.Destination.add(persistentTable.findSmallest(address)); - assert(getL2CacheEntry(address).Tokens >= 1); - out_msg.Tokens := getL2CacheEntry(address).Tokens; + assert(cache_entry.Tokens >= 1); + out_msg.Tokens := cache_entry.Tokens; out_msg.MessageSize := MessageSizeType:Response_Control; } } - getL2CacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(ee_sendDataWithAllTokens, "\e", desc="Send data and all tokens from cache to starver") { + assert(is_valid(cache_entry)); enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.Destination.add(persistentTable.findSmallest(address)); - assert(getL2CacheEntry(address).Tokens >= 1); - out_msg.Tokens := getL2CacheEntry(address).Tokens; - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + assert(cache_entry.Tokens >= 1); + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } - getL2CacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(f_sendAckWithAllButOneTokens, "f", desc="Send ack with all our tokens but one to starver.") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself - assert(getL2CacheEntry(address).Tokens > 0); - if (getL2CacheEntry(address).Tokens > 1) { + assert(is_valid(cache_entry)); + assert(cache_entry.Tokens > 0); + if (cache_entry.Tokens > 1) { enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; out_msg.Destination.add(persistentTable.findSmallest(address)); - assert(getL2CacheEntry(address).Tokens >= 1); - out_msg.Tokens := getL2CacheEntry(address).Tokens - 1; + assert(cache_entry.Tokens >= 1); + out_msg.Tokens := cache_entry.Tokens - 1; out_msg.MessageSize := MessageSizeType:Response_Control; } } - getL2CacheEntry(address).Tokens := 1; + cache_entry.Tokens := 1; } action(ff_sendDataWithAllButOneTokens, "\f", desc="Send data and out tokens but one to starver") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself - assert(getL2CacheEntry(address).Tokens > (max_tokens() / 2) + 1); + assert(is_valid(cache_entry)); + assert(cache_entry.Tokens > (max_tokens() / 2) + 1); enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.Destination.add(persistentTable.findSmallest(address)); - out_msg.Tokens := getL2CacheEntry(address).Tokens - 1; - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.Tokens := cache_entry.Tokens - 1; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } - getL2CacheEntry(address).Tokens := 1; + cache_entry.Tokens := 1; } action(fa_sendDataWithAllTokens, "fa", desc="Send data and out tokens but one to starver") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself - assert(getL2CacheEntry(address).Tokens == (max_tokens() / 2) + 1); + assert(is_valid(cache_entry)); + assert(cache_entry.Tokens == (max_tokens() / 2) + 1); enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.Destination.add(persistentTable.findSmallest(address)); - out_msg.Tokens := getL2CacheEntry(address).Tokens; - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.Tokens := cache_entry.Tokens; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } - getL2CacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } @@ -791,58 +800,60 @@ machine(L2Cache, "Token protocol") } } - action(k_dataFromL2CacheToL1Requestor, "k", desc="Send data and a token from cache to L1 requestor") { peek(L1requestNetwork_in, RequestMsg) { - assert(getL2CacheEntry(address).Tokens > 0); + assert(is_valid(cache_entry)); + assert(cache_entry.Tokens > 0); //enqueue(responseIntraChipL2Network_out, ResponseMsg, latency="L2_to_L1_RESPONSE_LATENCY") { enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; + out_msg.DataBlk := cache_entry.DataBlk; out_msg.Dirty := false; out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data; out_msg.Tokens := 1; } - getL2CacheEntry(address).Tokens := getL2CacheEntry(address).Tokens - 1; + cache_entry.Tokens := cache_entry.Tokens - 1; } } action(k_dataOwnerFromL2CacheToL1Requestor, "\k", desc="Send data and a token from cache to L1 requestor") { peek(L1requestNetwork_in, RequestMsg) { - assert(getL2CacheEntry(address).Tokens == (max_tokens() / 2) + 1); + assert(is_valid(cache_entry)); + assert(cache_entry.Tokens == (max_tokens() / 2) + 1); enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data; - out_msg.Tokens := getL2CacheEntry(address).Tokens; + out_msg.Tokens := cache_entry.Tokens; } - getL2CacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } } action(k_dataAndAllTokensFromL2CacheToL1Requestor, "\kk", desc="Send data and a token from cache to L1 requestor") { peek(L1requestNetwork_in, RequestMsg) { -// assert(getL2CacheEntry(address).Tokens == max_tokens()); + assert(is_valid(cache_entry)); +// assert(cache_entry.Tokens == max_tokens()); //enqueue(responseIntraChipL2Network_out, ResponseMsg, latency="L2_to_L1_RESPONSE_LATENCY") { enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := getL2CacheEntry(address).DataBlk; - out_msg.Dirty := getL2CacheEntry(address).Dirty; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data; //out_msg.Tokens := max_tokens(); - out_msg.Tokens := getL2CacheEntry(address).Tokens; + out_msg.Tokens := cache_entry.Tokens; } - getL2CacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } } @@ -865,13 +876,14 @@ machine(L2Cache, "Token protocol") action(q_updateTokensFromResponse, "q", desc="Update the token count based on the incoming response message") { peek(responseNetwork_in, ResponseMsg) { + assert(is_valid(cache_entry)); assert(in_msg.Tokens != 0); - getL2CacheEntry(address).Tokens := getL2CacheEntry(address).Tokens + in_msg.Tokens; + cache_entry.Tokens := cache_entry.Tokens + in_msg.Tokens; // this should ideally be in u_writeDataToCache, but Writeback_All_Tokens // may not trigger this action. if ( (in_msg.Type == CoherenceResponseType:DATA_OWNER || in_msg.Type == CoherenceResponseType:WB_OWNED) && in_msg.Dirty) { - getL2CacheEntry(address).Dirty := true; + cache_entry.Dirty := true; } } } @@ -895,61 +907,65 @@ machine(L2Cache, "Token protocol") action(r_setMRU, "\rr", desc="manually set the MRU bit for cache line" ) { peek(L1requestNetwork_in, RequestMsg) { if ((machineIDToMachineType(in_msg.Requestor) == MachineType:L1Cache) && - (isCacheTagPresent(address))) { + (is_valid(cache_entry))) { L2cacheMemory.setMRU(address); } } } action(t_sendAckWithCollectedTokens, "t", desc="Send ack with the tokens we've collected thus far.") { - if (getL2CacheEntry(address).Tokens > 0) { + assert(is_valid(cache_entry)); + if (cache_entry.Tokens > 0) { peek(requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - assert(getL2CacheEntry(address).Tokens >= 1); - out_msg.Tokens := getL2CacheEntry(address).Tokens; + assert(cache_entry.Tokens >= 1); + out_msg.Tokens := cache_entry.Tokens; out_msg.MessageSize := MessageSizeType:Response_Control; } } } - getL2CacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(tt_sendLocalAckWithCollectedTokens, "tt", desc="Send ack with the tokens we've collected thus far.") { - if (getL2CacheEntry(address).Tokens > 0) { + assert(is_valid(cache_entry)); + if (cache_entry.Tokens > 0) { peek(L1requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; out_msg.Destination.add(in_msg.Requestor); - assert(getL2CacheEntry(address).Tokens >= 1); - out_msg.Tokens := getL2CacheEntry(address).Tokens; + assert(cache_entry.Tokens >= 1); + out_msg.Tokens := cache_entry.Tokens; out_msg.MessageSize := MessageSizeType:Response_Control; } } } - getL2CacheEntry(address).Tokens := 0; + cache_entry.Tokens := 0; } action(u_writeDataToCache, "u", desc="Write data to cache") { peek(responseNetwork_in, ResponseMsg) { - getL2CacheEntry(address).DataBlk := in_msg.DataBlk; - if ((getL2CacheEntry(address).Dirty == false) && in_msg.Dirty) { - getL2CacheEntry(address).Dirty := in_msg.Dirty; + assert(is_valid(cache_entry)); + cache_entry.DataBlk := in_msg.DataBlk; + if ((cache_entry.Dirty == false) && in_msg.Dirty) { + cache_entry.Dirty := in_msg.Dirty; } } } action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") { - L2cacheMemory.allocate(address, new Entry); + set_cache_entry(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(); } action(uu_profileMiss, "\u", desc="Profile the demand miss") { @@ -965,7 +981,8 @@ machine(L2Cache, "Token protocol") peek(responseNetwork_in, ResponseMsg) { if (in_msg.Type != CoherenceResponseType:ACK && in_msg.Type != CoherenceResponseType:WB_TOKENS) { - assert(getL2CacheEntry(address).DataBlk == in_msg.DataBlk); + assert(is_valid(cache_entry)); + assert(cache_entry.DataBlk == in_msg.DataBlk); } } } diff --git a/src/mem/protocol/MOESI_CMP_token-dir.sm b/src/mem/protocol/MOESI_CMP_token-dir.sm index 041d9b743..c77d46bbe 100644 --- a/src/mem/protocol/MOESI_CMP_token-dir.sm +++ b/src/mem/protocol/MOESI_CMP_token-dir.sm @@ -162,21 +162,24 @@ machine(Directory, "Token protocol") bool starving, default="false"; int l2_select_low_bit, default="RubySystem::getBlockSizeBits()"; + void set_tbe(TBE b); + void unset_tbe(); + Entry getDirectoryEntry(Address addr), return_by_ref="yes" { return static_cast(Entry, directory[addr]); } - State getState(Address addr) { - if (TBEs.isPresent(addr)) { - return TBEs[addr].TBEState; + State getState(TBE tbe, Address addr) { + if (is_valid(tbe)) { + return tbe.TBEState; } else { return getDirectoryEntry(addr).DirectoryState; } } - void setState(Address addr, State state) { - if (TBEs.isPresent(addr)) { - TBEs[addr].TBEState := state; + void setState(TBE tbe, Address addr, State state) { + if (is_valid(tbe)) { + tbe.TBEState := state; } getDirectoryEntry(addr).DirectoryState := state; @@ -223,9 +226,9 @@ machine(Directory, "Token protocol") if (memQueue_in.isReady()) { peek(memQueue_in, MemoryMsg) { if (in_msg.Type == MemoryRequestType:MEMORY_READ) { - trigger(Event:Memory_Data, in_msg.Address); + trigger(Event:Memory_Data, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { - trigger(Event:Memory_Ack, in_msg.Address); + trigger(Event:Memory_Ack, in_msg.Address, TBEs[in_msg.Address]); } else { DPRINTF(RubySlicc, "%s\n", in_msg.Type); error("Invalid message"); @@ -237,7 +240,8 @@ machine(Directory, "Token protocol") // Reissue Timer in_port(reissueTimerTable_in, Address, reissueTimerTable) { if (reissueTimerTable_in.isReady()) { - trigger(Event:Request_Timeout, reissueTimerTable.readyAddress()); + trigger(Event:Request_Timeout, reissueTimerTable.readyAddress(), + TBEs[reissueTimerTable.readyAddress()]); } } @@ -248,23 +252,29 @@ machine(Directory, "Token protocol") if (getDirectoryEntry(in_msg.Address).Tokens + in_msg.Tokens == max_tokens()) { if ((in_msg.Type == CoherenceResponseType:DATA_OWNER) || (in_msg.Type == CoherenceResponseType:DATA_SHARED)) { - trigger(Event:Data_All_Tokens, in_msg.Address); + trigger(Event:Data_All_Tokens, in_msg.Address, + TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:ACK_OWNER) { - trigger(Event:Ack_Owner_All_Tokens, in_msg.Address); + trigger(Event:Ack_Owner_All_Tokens, in_msg.Address, + TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:ACK) { - trigger(Event:Ack_All_Tokens, in_msg.Address); + trigger(Event:Ack_All_Tokens, in_msg.Address, + TBEs[in_msg.Address]); } else { DPRINTF(RubySlicc, "%s\n", in_msg.Type); error("Invalid message"); } } else { if (in_msg.Type == CoherenceResponseType:DATA_OWNER) { - trigger(Event:Data_Owner, in_msg.Address); + trigger(Event:Data_Owner, in_msg.Address, + TBEs[in_msg.Address]); } else if ((in_msg.Type == CoherenceResponseType:ACK) || (in_msg.Type == CoherenceResponseType:DATA_SHARED)) { - trigger(Event:Tokens, in_msg.Address); + trigger(Event:Tokens, in_msg.Address, + TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceResponseType:ACK_OWNER) { - trigger(Event:Ack_Owner, in_msg.Address); + trigger(Event:Ack_Owner, in_msg.Address, + TBEs[in_msg.Address]); } else { DPRINTF(RubySlicc, "%s\n", in_msg.Type); error("Invalid message"); @@ -295,30 +305,39 @@ machine(Directory, "Token protocol") if (persistentTable.isLocked(in_msg.Address)) { if (persistentTable.findSmallest(in_msg.Address) == machineID) { if (getDirectoryEntry(in_msg.Address).Tokens > 0) { - trigger(Event:Own_Lock_or_Unlock_Tokens, in_msg.Address); + trigger(Event:Own_Lock_or_Unlock_Tokens, in_msg.Address, + TBEs[in_msg.Address]); } else { - trigger(Event:Own_Lock_or_Unlock, in_msg.Address); + trigger(Event:Own_Lock_or_Unlock, in_msg.Address, + TBEs[in_msg.Address]); } } else { - trigger(Event:Lockdown, in_msg.Address); // locked + // locked + trigger(Event:Lockdown, in_msg.Address, TBEs[in_msg.Address]); } } else { - trigger(Event:Unlockdown, in_msg.Address); // unlocked + // unlocked + trigger(Event:Unlockdown, in_msg.Address, TBEs[in_msg.Address]); } } else { if (persistentTable.findSmallest(in_msg.Address) == machineID) { if (getDirectoryEntry(in_msg.Address).Tokens > 0) { - trigger(Event:Own_Lock_or_Unlock_Tokens, in_msg.Address); + trigger(Event:Own_Lock_or_Unlock_Tokens, in_msg.Address, + TBEs[in_msg.Address]); } else { - trigger(Event:Own_Lock_or_Unlock, in_msg.Address); + trigger(Event:Own_Lock_or_Unlock, in_msg.Address, + TBEs[in_msg.Address]); } } else if (in_msg.Type == PersistentRequestType:GETX_PERSISTENT) { - trigger(Event:Lockdown, in_msg.Address); // locked + // locked + trigger(Event:Lockdown, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == PersistentRequestType:GETS_PERSISTENT) { - trigger(Event:Lockdown, in_msg.Address); // locked + // locked + trigger(Event:Lockdown, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == PersistentRequestType:DEACTIVATE_PERSISTENT) { - trigger(Event:Unlockdown, in_msg.Address); // unlocked + // unlocked + trigger(Event:Unlockdown, in_msg.Address, TBEs[in_msg.Address]); } else { error("Invalid message"); } @@ -332,9 +351,9 @@ machine(Directory, "Token protocol") peek(requestNetwork_in, RequestMsg) { assert(in_msg.Destination.isElement(machineID)); if (in_msg.Type == CoherenceRequestType:GETS) { - trigger(Event:GETS, in_msg.Address); + trigger(Event:GETS, in_msg.Address, TBEs[in_msg.Address]); } else if (in_msg.Type == CoherenceRequestType:GETX) { - trigger(Event:GETX, in_msg.Address); + trigger(Event:GETX, in_msg.Address, TBEs[in_msg.Address]); } else { error("Invalid message"); } @@ -346,12 +365,14 @@ machine(Directory, "Token protocol") if (dmaRequestQueue_in.isReady()) { peek(dmaRequestQueue_in, DMARequestMsg) { if (in_msg.Type == DMARequestType:READ) { - trigger(Event:DMA_READ, in_msg.LineAddress); + trigger(Event:DMA_READ, in_msg.LineAddress, TBEs[in_msg.LineAddress]); } else if (in_msg.Type == DMARequestType:WRITE) { if (getDirectoryEntry(in_msg.LineAddress).Tokens == max_tokens()) { - trigger(Event:DMA_WRITE_All_Tokens, in_msg.LineAddress); + trigger(Event:DMA_WRITE_All_Tokens, in_msg.LineAddress, + TBEs[in_msg.LineAddress]); } else { - trigger(Event:DMA_WRITE, in_msg.LineAddress); + trigger(Event:DMA_WRITE, in_msg.LineAddress, + TBEs[in_msg.LineAddress]); } } else { error("Invalid message"); @@ -408,7 +429,7 @@ machine(Directory, "Token protocol") markPersistentEntries(address); starving := true; - TBEs[address].WentPersistent := true; + tbe.WentPersistent := true; // Do not schedule a wakeup, a persistent requests will always complete } else { @@ -478,7 +499,7 @@ machine(Directory, "Token protocol") markPersistentEntries(address); starving := true; - TBEs[address].WentPersistent := true; + tbe.WentPersistent := true; // Do not schedule a wakeup, a persistent requests will always complete } else { @@ -574,7 +595,7 @@ machine(Directory, "Token protocol") out_msg.Destination.add(persistentTable.findSmallest(address)); assert(getDirectoryEntry(address).Tokens > 0); out_msg.Tokens := getDirectoryEntry(address).Tokens; - out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.DataBlk := tbe.DataBlk; out_msg.Dirty := false; out_msg.MessageSize := MessageSizeType:Response_Data; } @@ -634,9 +655,9 @@ machine(Directory, "Token protocol") 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); } } @@ -646,7 +667,7 @@ machine(Directory, "Token protocol") 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; DPRINTF(RubySlicc, "%s\n", out_msg); } } @@ -654,17 +675,18 @@ machine(Directory, "Token protocol") 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].WentPersistent := false; + 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.WentPersistent := false; } } action(s_deallocateTBE, "s", desc="Deallocate TBE") { - if (TBEs[address].WentPersistent) { + if (tbe.WentPersistent) { assert(starving == true); enqueue(persistentNetwork_out, PersistentMsg, latency = "1") { @@ -692,21 +714,22 @@ machine(Directory, "Token protocol") } TBEs.deallocate(address); + unset_tbe(); } action(rd_recordDataInTbe, "rd", desc="Record data in TBE") { peek(responseNetwork_in, ResponseMsg) { - TBEs[address].DataBlk := in_msg.DataBlk; + tbe.DataBlk := in_msg.DataBlk; } } action(cd_writeCleanDataToTbe, "cd", desc="Write clean memory data to TBE") { - TBEs[address].DataBlk := getDirectoryEntry(address).DataBlk; + tbe.DataBlk := getDirectoryEntry(address).DataBlk; } action(dwt_writeDmaDataFromTBE, "dwt", desc="DMA Write data to memory from TBE") { - getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk; - getDirectoryEntry(address).DataBlk.copyPartial(TBEs[address].DmaDataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + getDirectoryEntry(address).DataBlk := tbe.DataBlk; + getDirectoryEntry(address).DataBlk.copyPartial(tbe.DmaDataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len); } action(f_incrementTokens, "f", desc="Increment the number of tokens we're tracking") { @@ -837,7 +860,7 @@ machine(Directory, "Token protocol") 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; } } @@ -853,7 +876,7 @@ machine(Directory, "Token protocol") // 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; } } @@ -870,7 +893,7 @@ machine(Directory, "Token protocol") // 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; } } diff --git a/src/mem/protocol/MOESI_hammer-cache.sm b/src/mem/protocol/MOESI_hammer-cache.sm index 6e62c7472..659979ddf 100644 --- a/src/mem/protocol/MOESI_hammer-cache.sm +++ b/src/mem/protocol/MOESI_hammer-cache.sm @@ -153,59 +153,66 @@ machine(L1Cache, "AMD Hammer-like protocol") TBETable TBEs, template_hack="<L1Cache_TBE>"; - 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(AbstractCacheEntry b); + void unset_cache_entry(); + void set_tbe(TBE b); + void unset_tbe(); + + Entry getCacheEntry(Address address), return_by_pointer="yes" { + Entry L2cache_entry := static_cast(Entry, "pointer", L2cacheMemory.lookup(address)); + if(is_valid(L2cache_entry)) { + return L2cache_entry; } - } - 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); + Entry L1Dcache_entry := static_cast(Entry, "pointer", L1DcacheMemory.lookup(address)); + if(is_valid(L1Dcache_entry)) { + return L1Dcache_entry; } + + Entry L1Icache_entry := static_cast(Entry, "pointer", L1IcacheMemory.lookup(address)); + return L1Icache_entry; } - bool isCacheTagPresent(Address addr) { - return (L2cacheMemory.isTagPresent(addr) || L1DcacheMemory.isTagPresent(addr) || L1IcacheMemory.isTagPresent(addr)); + Entry getL2CacheEntry(Address address), return_by_pointer="yes" { + Entry L2cache_entry := static_cast(Entry, "pointer", L2cacheMemory.lookup(address)); + return L2cache_entry; } - 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); + Entry getL1DCacheEntry(Address address), return_by_pointer="yes" { + Entry L1Dcache_entry := static_cast(Entry, "pointer", L1DcacheMemory.lookup(address)); + return L1Dcache_entry; + } + + Entry getL1ICacheEntry(Address address), return_by_pointer="yes" { + Entry L1Icache_entry := static_cast(Entry, "pointer", L1IcacheMemory.lookup(address)); + return L1Icache_entry; + } - if(TBEs.isPresent(addr)) { - return TBEs[addr].TBEState; - } else if (isCacheTagPresent(addr)) { - return getCacheEntry(addr).CacheState; + State getState(TBE tbe, Entry cache_entry, Address addr) { + if(is_valid(tbe)) { + return tbe.TBEState; + } else if (is_valid(cache_entry)) { + return cache_entry.CacheState; } return State:I; } - void setState(Address addr, State state) { + 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(tbe)) { + tbe.TBEState := state; } - if (isCacheTagPresent(addr)) { - getCacheEntry(addr).CacheState := state; + if (is_valid(cache_entry)) { + 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 +221,9 @@ machine(L1Cache, "AMD Hammer-like protocol") 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,15 +251,20 @@ machine(L1Cache, "AMD Hammer-like protocol") } } - GenericMachineType testAndClearLocalHit(Address addr) { - if (getCacheEntry(addr).FromL2) { - getCacheEntry(addr).FromL2 := false; + GenericMachineType testAndClearLocalHit(Entry cache_entry) { + if (is_valid(cache_entry) && cache_entry.FromL2) { + cache_entry.FromL2 := false; return GenericMachineType:L2Cache; } else { return GenericMachineType:L1Cache; } } + bool IsAtomicAccessed(Entry cache_entry) { + assert(is_valid(cache_entry)); + return cache_entry.AtomicAccessed; + } + MessageBuffer triggerQueue, ordered="true"; // ** OUT_PORTS ** @@ -268,12 +280,16 @@ machine(L1Cache, "AMD Hammer-like protocol") in_port(triggerQueue_in, TriggerMsg, triggerQueue) { if (triggerQueue_in.isReady()) { peek(triggerQueue_in, TriggerMsg) { + + Entry cache_entry := getCacheEntry(in_msg.Address); + TBE tbe := TBEs[in_msg.Address]; + if (in_msg.Type == TriggerType:L2_to_L1) { - trigger(Event:Complete_L2_to_L1, in_msg.Address); + trigger(Event:Complete_L2_to_L1, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == TriggerType:ALL_ACKS) { - trigger(Event:All_acks, in_msg.Address); + trigger(Event:All_acks, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == TriggerType:ALL_ACKS_NO_SHARERS) { - trigger(Event:All_acks_no_sharers, in_msg.Address); + trigger(Event:All_acks_no_sharers, in_msg.Address, cache_entry, tbe); } else { error("Unexpected message"); } @@ -287,30 +303,34 @@ machine(L1Cache, "AMD Hammer-like protocol") in_port(forwardToCache_in, RequestMsg, forwardToCache) { if (forwardToCache_in.isReady()) { peek(forwardToCache_in, RequestMsg, block_on="Address") { + + Entry cache_entry := getCacheEntry(in_msg.Address); + TBE tbe := TBEs[in_msg.Address]; + if (in_msg.Type == CoherenceRequestType:GETX) { - trigger(Event:Other_GETX, in_msg.Address); + trigger(Event:Other_GETX, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceRequestType:MERGED_GETS) { - trigger(Event:Merged_GETS, in_msg.Address); + trigger(Event:Merged_GETS, in_msg.Address, cache_entry, tbe); } 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) { - trigger(Event:Other_GETS_No_Mig, in_msg.Address); + if (is_valid(cache_entry)) { + if (IsAtomicAccessed(cache_entry) && no_mig_atomic) { + trigger(Event:Other_GETS_No_Mig, in_msg.Address, cache_entry, tbe); } else { - trigger(Event:Other_GETS, in_msg.Address); + trigger(Event:Other_GETS, in_msg.Address, cache_entry, tbe); } } else { - trigger(Event:Other_GETS, in_msg.Address); + trigger(Event:Other_GETS, in_msg.Address, cache_entry, tbe); } } else { - trigger(Event:NC_DMA_GETS, in_msg.Address); + trigger(Event:NC_DMA_GETS, in_msg.Address, cache_entry, tbe); } } else if (in_msg.Type == CoherenceRequestType:INV) { - trigger(Event:Invalidate, in_msg.Address); + trigger(Event:Invalidate, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceRequestType:WB_ACK) { - trigger(Event:Writeback_Ack, in_msg.Address); + trigger(Event:Writeback_Ack, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceRequestType:WB_NACK) { - trigger(Event:Writeback_Nack, in_msg.Address); + trigger(Event:Writeback_Nack, in_msg.Address, cache_entry, tbe); } else { error("Unexpected message"); } @@ -322,16 +342,20 @@ machine(L1Cache, "AMD Hammer-like protocol") 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); + trigger(Event:Ack, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) { - trigger(Event:Shared_Ack, in_msg.Address); + trigger(Event:Shared_Ack, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:DATA) { - trigger(Event:Data, in_msg.Address); + trigger(Event:Data, in_msg.Address, cache_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) { - trigger(Event:Shared_Data, in_msg.Address); + 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); + trigger(Event:Exclusive_Data, in_msg.Address, cache_entry, tbe); } else { error("Unexpected message"); } @@ -347,41 +371,58 @@ machine(L1Cache, "AMD Hammer-like protocol") peek(mandatoryQueue_in, CacheMsg, block_on="LineAddress") { // Check for data access to blocks in I-cache and ifetchs to blocks in D-cache + TBE tbe := TBEs[in_msg.LineAddress]; if (in_msg.Type == CacheRequestType:IFETCH) { // ** INSTRUCTION ACCESS *** // Check to see if it is in the OTHER L1 - if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); + if (is_valid(L1Dcache_entry)) { // The block is in the wrong L1, try to write it to the L2 if (L2cacheMemory.cacheAvail(in_msg.LineAddress)) { - trigger(Event:L1_to_L2, in_msg.LineAddress); + trigger(Event:L1_to_L2, in_msg.LineAddress, L1Dcache_entry, tbe); } else { - trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:L2_Replacement, + L2cacheMemory.cacheProbe(in_msg.LineAddress), + getL2CacheEntry(L2cacheMemory.cacheProbe(in_msg.LineAddress)), + TBEs[L2cacheMemory.cacheProbe(in_msg.LineAddress)]); } } - if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); + if (is_valid(L1Icache_entry)) { // The tag matches for the L1, so the L1 fetches the line. We know it can't be in the L2 due to exclusion - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Icache_entry, tbe); } 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)) { + + Entry L2cache_entry := getL2CacheEntry(in_msg.LineAddress); + if (is_valid(L2cache_entry)) { // L2 has it (maybe not with the right permissions) - trigger(Event:Trigger_L2_to_L1I, in_msg.LineAddress); + trigger(Event:Trigger_L2_to_L1I, in_msg.LineAddress, + L2cache_entry, tbe); } else { // We have room, the L2 doesn't have it, so the L1 fetches the line - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Icache_entry, tbe); } } 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 - trigger(Event:L1_to_L2, L1IcacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:L1_to_L2, + L1IcacheMemory.cacheProbe(in_msg.LineAddress), + getL1ICacheEntry(L1IcacheMemory.cacheProbe(in_msg.LineAddress)), + TBEs[L1IcacheMemory.cacheProbe(in_msg.LineAddress)]); } else { // The L2 does not have room, so we replace a line from the L2 - trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(L1IcacheMemory.cacheProbe(in_msg.LineAddress))); + trigger(Event:L2_Replacement, + L2cacheMemory.cacheProbe(L1IcacheMemory.cacheProbe(in_msg.LineAddress)), + getL2CacheEntry(L2cacheMemory.cacheProbe(L1IcacheMemory.cacheProbe(in_msg.LineAddress))), + TBEs[L2cacheMemory.cacheProbe(L1IcacheMemory.cacheProbe(in_msg.LineAddress))]); } } } @@ -389,36 +430,51 @@ machine(L1Cache, "AMD Hammer-like protocol") // *** DATA ACCESS *** // Check to see if it is in the OTHER L1 - if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); + if (is_valid(L1Icache_entry)) { // The block is in the wrong L1, try to write it to the L2 if (L2cacheMemory.cacheAvail(in_msg.LineAddress)) { - trigger(Event:L1_to_L2, in_msg.LineAddress); + trigger(Event:L1_to_L2, in_msg.LineAddress, L1Icache_entry, tbe); } else { - trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:L2_Replacement, + L2cacheMemory.cacheProbe(in_msg.LineAddress), + getL2CacheEntry(L2cacheMemory.cacheProbe(in_msg.LineAddress)), + TBEs[L2cacheMemory.cacheProbe(in_msg.LineAddress)]); } } - if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); + if (is_valid(L1Dcache_entry)) { // The tag matches for the L1, so the L1 fetches the line. We know it can't be in the L2 due to exclusion - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Dcache_entry, tbe); } 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)) { + Entry L2cache_entry := getL2CacheEntry(in_msg.LineAddress); + if (is_valid(L2cache_entry)) { // L2 has it (maybe not with the right permissions) - trigger(Event:Trigger_L2_to_L1D, in_msg.LineAddress); + trigger(Event:Trigger_L2_to_L1D, in_msg.LineAddress, + L2cache_entry, tbe); } else { // We have room, the L2 doesn't have it, so the L1 fetches the line - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + trigger(mandatory_request_type_to_event(in_msg.Type), + in_msg.LineAddress, L1Dcache_entry, tbe); } } 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 - trigger(Event:L1_to_L2, L1DcacheMemory.cacheProbe(in_msg.LineAddress)); + trigger(Event:L1_to_L2, + L1DcacheMemory.cacheProbe(in_msg.LineAddress), + getL1DCacheEntry(L1DcacheMemory.cacheProbe(in_msg.LineAddress)), + TBEs[L1DcacheMemory.cacheProbe(in_msg.LineAddress)]); } else { // The L2 does not have room, so we replace a line from the L2 - trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(L1DcacheMemory.cacheProbe(in_msg.LineAddress))); + trigger(Event:L2_Replacement, + L2cacheMemory.cacheProbe(L1DcacheMemory.cacheProbe(in_msg.LineAddress)), + getL2CacheEntry(L2cacheMemory.cacheProbe(L1DcacheMemory.cacheProbe(in_msg.LineAddress))), + TBEs[L2cacheMemory.cacheProbe(L1DcacheMemory.cacheProbe(in_msg.LineAddress))]); } } } @@ -431,37 +487,40 @@ machine(L1Cache, "AMD Hammer-like protocol") action(a_issueGETS, "a", desc="Issue GETS") { enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceRequestType:GETS; out_msg.Requestor := machineID; 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) } } action(b_issueGETX, "b", desc="Issue GETX") { enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceRequestType:GETX; out_msg.Requestor := machineID; 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) } } action(c_sendExclusiveData, "c", desc="Send exclusive data from cache to requestor") { peek(forwardToCache_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; 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 := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; if (in_msg.DirectedProbe) { out_msg.Acks := machineCount(MachineType:L1Cache); } else { @@ -487,12 +546,13 @@ machine(L1Cache, "AMD Hammer-like protocol") action(e_sendData, "e", desc="Send data from cache to requestor") { peek(forwardToCache_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; 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 := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.Dirty; if (in_msg.DirectedProbe) { out_msg.Acks := machineCount(MachineType:L1Cache); } else { @@ -508,13 +568,14 @@ machine(L1Cache, "AMD Hammer-like protocol") action(ee_sendDataShared, "\e", desc="Send data from cache to requestor, keep a shared copy") { peek(forwardToCache_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; 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 := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.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 { @@ -530,13 +591,14 @@ machine(L1Cache, "AMD Hammer-like protocol") action(em_sendDataSharedMultiple, "em", desc="Send data from cache to all requestors") { peek(forwardToCache_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; 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 := cache_entry.DataBlk; + out_msg.Dirty := cache_entry.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; @@ -599,87 +661,91 @@ machine(L1Cache, "AMD Hammer-like protocol") action(gs_sendUnblockS, "gs", desc="Send unblock to memory and indicate S state") { enqueue(unblockNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(tbe)); 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); - - sequencer.readCallback(address, - testAndClearLocalHit(address), - getCacheEntry(address).DataBlk); - + assert(is_valid(cache_entry)); + DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); + sequencer.readCallback(address, testAndClearLocalHit(cache_entry), + cache_entry.DataBlk); } action(hx_external_load_hit, "hx", desc="load required external msgs") { - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); + assert(is_valid(cache_entry)); + assert(is_valid(tbe)); + DPRINTF(RubySlicc, "%s\n", cache_entry.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); - + cache_entry.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); + assert(is_valid(cache_entry)); + DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); peek(mandatoryQueue_in, CacheMsg) { - sequencer.writeCallback(address, - testAndClearLocalHit(address), - getCacheEntry(address).DataBlk); + sequencer.writeCallback(address, testAndClearLocalHit(cache_entry), + cache_entry.DataBlk); - getCacheEntry(address).Dirty := true; + cache_entry.Dirty := true; if (in_msg.Type == CacheRequestType:ATOMIC) { - getCacheEntry(address).AtomicAccessed := true; + cache_entry.AtomicAccessed := true; } } } action(sx_external_store_hit, "sx", desc="store required external msgs.") { - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); + assert(is_valid(cache_entry)); + assert(is_valid(tbe)); + DPRINTF(RubySlicc, "%s\n", cache_entry.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); - + cache_entry.DataBlk, + tbe.InitialRequestTime, + tbe.ForwardRequestTime, + tbe.FirstResponseTime); } - getCacheEntry(address).Dirty := true; + cache_entry.Dirty := true; } action(sxt_trig_ext_store_hit, "sxt", desc="store required external msgs.") { - DPRINTF(RubySlicc, "%s\n", getCacheEntry(address).DataBlk); + assert(is_valid(cache_entry)); + assert(is_valid(tbe)); + DPRINTF(RubySlicc, "%s\n", cache_entry.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), + cache_entry.DataBlk, + tbe.InitialRequestTime, + tbe.ForwardRequestTime, + tbe.FirstResponseTime); - getCacheEntry(address).Dirty := true; + cache_entry.Dirty := true; } action(i_allocateTBE, "i", desc="Allocate TBE") { check_allocate(TBEs); + assert(is_valid(cache_entry)); 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 := cache_entry.DataBlk; // Data only used for writebacks + tbe.Dirty := cache_entry.Dirty; + tbe.Sharers := false; } action(j_popTriggerQueue, "j", desc="Pop trigger queue.") { @@ -695,43 +761,49 @@ machine(L1Cache, "AMD Hammer-like protocol") } action(hp_copyFromTBEToL2, "li", desc="Copy data from TBE to L2 cache entry.") { - getCacheEntry(address).Dirty := TBEs[address].Dirty; - getCacheEntry(address).DataBlk := TBEs[address].DataBlk; + assert(is_valid(cache_entry)); + assert(is_valid(tbe)); + cache_entry.Dirty := tbe.Dirty; + cache_entry.DataBlk := tbe.DataBlk; } action(nb_copyFromTBEToL1, "fu", desc="Copy data from TBE to L1 cache entry.") { - getCacheEntry(address).Dirty := TBEs[address].Dirty; - getCacheEntry(address).DataBlk := TBEs[address].DataBlk; - getCacheEntry(address).FromL2 := true; + assert(is_valid(cache_entry)); + assert(is_valid(tbe)); + cache_entry.Dirty := tbe.Dirty; + cache_entry.DataBlk := tbe.DataBlk; + cache_entry.FromL2 := true; } 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); + assert(is_valid(tbe)); + 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; + assert(is_valid(tbe)); + tbe.CurOwner := in_msg.Sender; } } @@ -747,10 +819,11 @@ machine(L1Cache, "AMD Hammer-like protocol") } action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") { - if (TBEs[address].NumPendingMsgs == 0) { + assert(is_valid(tbe)); + 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; @@ -760,23 +833,26 @@ machine(L1Cache, "AMD Hammer-like protocol") } action(p_decrementNumberOfMessagesByOne, "p", desc="Decrement the number of messages for which we're waiting by one") { - TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - 1; + assert(is_valid(tbe)); + 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; + assert(is_valid(tbe)); + tbe.NumPendingMsgs := tbe.NumPendingMsgs + 1; } action(q_sendDataFromTBEToCache, "q", desc="Send data from TBE to cache") { peek(forwardToCache_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; 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 { @@ -792,13 +868,14 @@ machine(L1Cache, "AMD Hammer-like protocol") action(qm_sendDataFromTBEToCache, "qm", desc="Send data from TBE to cache, multiple sharers") { peek(forwardToCache_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(tbe)); out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA; 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; @@ -809,48 +886,52 @@ machine(L1Cache, "AMD Hammer-like protocol") action(qq_sendDataFromTBEToMemory, "\q", desc="Send data from TBE to memory") { enqueue(unblockNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(tbe)); 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; + assert(is_valid(tbe)); + 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") { enqueue(unblockNetwork_out, ResponseMsg, latency=cache_response_latency) { + assert(is_valid(tbe)); 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; } } @@ -858,18 +939,20 @@ machine(L1Cache, "AMD Hammer-like protocol") 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; + assert(is_valid(cache_entry)); + cache_entry.DataBlk := in_msg.DataBlk; + cache_entry.Dirty := in_msg.Dirty; } } action(v_writeDataToCacheVerify, "v", desc="Write data to cache, assert it was same as before") { peek(responseToCache_in, ResponseMsg) { + assert(is_valid(cache_entry)); 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; + cache_entry.DataBlk, in_msg.DataBlk); + assert(cache_entry.DataBlk == in_msg.DataBlk); + cache_entry.DataBlk := in_msg.DataBlk; + cache_entry.Dirty := in_msg.Dirty || cache_entry.Dirty; } } @@ -879,26 +962,28 @@ machine(L1Cache, "AMD Hammer-like protocol") } else { L1IcacheMemory.deallocate(address); } + unset_cache_entry(); } 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_invalid(cache_entry)) { + set_cache_entry(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_invalid(cache_entry)) { + set_cache_entry(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.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(); } action(uu_profileMiss, "\u", desc="Profile the demand miss") { @@ -1513,4 +1598,3 @@ machine(L1Cache, "AMD Hammer-like protocol") l_popForwardQueue; } } - diff --git a/src/mem/protocol/MOESI_hammer-dir.sm b/src/mem/protocol/MOESI_hammer-dir.sm index e6e474e95..8f9ce2360 100644 --- a/src/mem/protocol/MOESI_hammer-dir.sm +++ b/src/mem/protocol/MOESI_hammer-dir.sm @@ -166,6 +166,11 @@ machine(Directory, "AMD Hammer-like protocol") bool isPresent(Address); } + void set_cache_entry(AbstractCacheEntry b); + void unset_cache_entry(); + void set_tbe(TBE a); + void unset_tbe(); + // ** OBJECTS ** TBETable TBEs, template_hack="<Directory_TBE>"; @@ -174,17 +179,21 @@ machine(Directory, "AMD Hammer-like protocol") return static_cast(Entry, directory[addr]); } - PfEntry getPfEntry(Address addr), return_by_ref="yes" { - return static_cast(PfEntry, probeFilter[addr]); + PfEntry getProbeFilterEntry(Address addr), return_by_pointer="yes" { + if(probe_filter_enabled) { + PfEntry pfEntry := static_cast(PfEntry, "pointer", probeFilter.lookup(addr)); + return pfEntry; + } + return OOD; } - State getState(Address addr) { - if (TBEs.isPresent(addr)) { - return TBEs[addr].TBEState; + State getState(TBE tbe, PfEntry pf_entry, Address addr) { + if (is_valid(tbe)) { + return tbe.TBEState; } else { if (probe_filter_enabled) { - if (probeFilter.isTagPresent(addr)) { - assert(getPfEntry(addr).PfState == getDirectoryEntry(addr).DirectoryState); + if (is_valid(pf_entry)) { + assert(pf_entry.PfState == getDirectoryEntry(addr).DirectoryState); } else { assert(getDirectoryEntry(addr).DirectoryState == State:E); } @@ -193,21 +202,21 @@ machine(Directory, "AMD Hammer-like protocol") } } - 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(tbe)) { + tbe.TBEState := state; } if (probe_filter_enabled) { - if (probeFilter.isTagPresent(addr)) { - getPfEntry(addr).PfState := state; + if (is_valid(pf_entry)) { + pf_entry.PfState := state; } if (state == State:NX || state == State:NO || state == State:S || state == State:O) { - assert(probeFilter.isTagPresent(addr)); + assert(is_valid(pf_entry)); } } if (state == State:E || state == State:NX || state == State:NO || state == State:S || state == State:O) { - assert(TBEs.isPresent(addr) == false); + assert(is_valid(tbe) == false); } getDirectoryEntry(addr).DirectoryState := state; } @@ -242,14 +251,20 @@ machine(Directory, "AMD Hammer-like protocol") in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=5) { if (triggerQueue_in.isReady()) { peek(triggerQueue_in, TriggerMsg) { + PfEntry pf_entry := getProbeFilterEntry(in_msg.Address); + TBE tbe := TBEs[in_msg.Address]; if (in_msg.Type == TriggerType:ALL_ACKS) { - trigger(Event:All_acks_and_owner_data, in_msg.Address); + trigger(Event:All_acks_and_owner_data, in_msg.Address, + pf_entry, tbe); } else if (in_msg.Type == TriggerType:ALL_ACKS_OWNER_EXISTS) { - trigger(Event:All_acks_and_shared_data, in_msg.Address); + trigger(Event:All_acks_and_shared_data, in_msg.Address, + pf_entry, tbe); } else if (in_msg.Type == TriggerType:ALL_ACKS_NO_SHARERS) { - trigger(Event:All_acks_and_data_no_sharers, in_msg.Address); + trigger(Event:All_acks_and_data_no_sharers, in_msg.Address, + pf_entry, tbe); } else if (in_msg.Type == TriggerType:ALL_UNBLOCKS) { - trigger(Event:All_Unblocks, in_msg.Address); + trigger(Event:All_Unblocks, in_msg.Address, + pf_entry, tbe); } else { error("Unexpected message"); } @@ -260,20 +275,24 @@ machine(Directory, "AMD Hammer-like protocol") in_port(unblockNetwork_in, ResponseMsg, unblockToDir, rank=4) { if (unblockNetwork_in.isReady()) { peek(unblockNetwork_in, ResponseMsg) { + PfEntry pf_entry := getProbeFilterEntry(in_msg.Address); + TBE tbe := TBEs[in_msg.Address]; if (in_msg.Type == CoherenceResponseType:UNBLOCK) { - trigger(Event:Unblock, in_msg.Address); + trigger(Event:Unblock, in_msg.Address, pf_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:UNBLOCKS) { - trigger(Event:UnblockS, in_msg.Address); + trigger(Event:UnblockS, in_msg.Address, pf_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:UNBLOCKM) { - trigger(Event:UnblockM, in_msg.Address); + trigger(Event:UnblockM, in_msg.Address, pf_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:WB_CLEAN) { - trigger(Event:Writeback_Clean, in_msg.Address); + trigger(Event:Writeback_Clean, in_msg.Address, pf_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:WB_DIRTY) { - trigger(Event:Writeback_Dirty, in_msg.Address); + trigger(Event:Writeback_Dirty, in_msg.Address, pf_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_CLEAN) { - trigger(Event:Writeback_Exclusive_Clean, in_msg.Address); + trigger(Event:Writeback_Exclusive_Clean, in_msg.Address, + pf_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_DIRTY) { - trigger(Event:Writeback_Exclusive_Dirty, in_msg.Address); + trigger(Event:Writeback_Exclusive_Dirty, in_msg.Address, + pf_entry, tbe); } else { error("Invalid message"); } @@ -285,16 +304,18 @@ machine(Directory, "AMD Hammer-like protocol") in_port(responseToDir_in, ResponseMsg, responseToDir, rank=3) { if (responseToDir_in.isReady()) { peek(responseToDir_in, ResponseMsg) { + PfEntry pf_entry := getProbeFilterEntry(in_msg.Address); + TBE tbe := TBEs[in_msg.Address]; if (in_msg.Type == CoherenceResponseType:ACK) { - trigger(Event:Ack, in_msg.Address); + trigger(Event:Ack, in_msg.Address, pf_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) { - trigger(Event:Shared_Ack, in_msg.Address); + trigger(Event:Shared_Ack, in_msg.Address, pf_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) { - trigger(Event:Shared_Data, in_msg.Address); + trigger(Event:Shared_Data, in_msg.Address, pf_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:DATA) { - trigger(Event:Data, in_msg.Address); + trigger(Event:Data, in_msg.Address, pf_entry, tbe); } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) { - trigger(Event:Exclusive_Data, in_msg.Address); + trigger(Event:Exclusive_Data, in_msg.Address, pf_entry, tbe); } else { error("Unexpected message"); } @@ -306,10 +327,12 @@ machine(Directory, "AMD Hammer-like protocol") in_port(memQueue_in, MemoryMsg, memBuffer, rank=2) { if (memQueue_in.isReady()) { peek(memQueue_in, MemoryMsg) { + PfEntry pf_entry := getProbeFilterEntry(in_msg.Address); + TBE tbe := TBEs[in_msg.Address]; if (in_msg.Type == MemoryRequestType:MEMORY_READ) { - trigger(Event:Memory_Data, in_msg.Address); + trigger(Event:Memory_Data, in_msg.Address, pf_entry, tbe); } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { - trigger(Event:Memory_Ack, in_msg.Address); + trigger(Event:Memory_Ack, in_msg.Address, pf_entry, tbe); } else { DPRINTF(RubySlicc, "%d\n", in_msg.Type); error("Invalid message"); @@ -321,21 +344,29 @@ machine(Directory, "AMD Hammer-like protocol") in_port(requestQueue_in, RequestMsg, requestToDir, rank=1) { if (requestQueue_in.isReady()) { peek(requestQueue_in, RequestMsg) { + PfEntry pf_entry := getProbeFilterEntry(in_msg.Address); + TBE tbe := TBEs[in_msg.Address]; if (in_msg.Type == CoherenceRequestType:PUT) { - trigger(Event:PUT, in_msg.Address); + trigger(Event:PUT, in_msg.Address, pf_entry, tbe); } else { if (probe_filter_enabled) { - if (probeFilter.isTagPresent(in_msg.Address)) { - trigger(cache_request_to_event(in_msg.Type), in_msg.Address); + if (is_valid(pf_entry)) { + trigger(cache_request_to_event(in_msg.Type), in_msg.Address, + pf_entry, tbe); } else { if (probeFilter.cacheAvail(in_msg.Address)) { - trigger(cache_request_to_event(in_msg.Type), in_msg.Address); + trigger(cache_request_to_event(in_msg.Type), in_msg.Address, + pf_entry, tbe); } else { - trigger(Event:Pf_Replacement, probeFilter.cacheProbe(in_msg.Address)); + trigger(Event:Pf_Replacement, + probeFilter.cacheProbe(in_msg.Address), + getProbeFilterEntry(probeFilter.cacheProbe(in_msg.Address)), + TBEs[probeFilter.cacheProbe(in_msg.Address)]); } } } else { - trigger(cache_request_to_event(in_msg.Type), in_msg.Address); + trigger(cache_request_to_event(in_msg.Type), in_msg.Address, + pf_entry, tbe); } } } @@ -345,10 +376,12 @@ machine(Directory, "AMD Hammer-like protocol") in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir, rank=0) { if (dmaRequestQueue_in.isReady()) { peek(dmaRequestQueue_in, DMARequestMsg) { + PfEntry pf_entry := getProbeFilterEntry(in_msg.LineAddress); + TBE tbe := TBEs[in_msg.LineAddress]; if (in_msg.Type == DMARequestType:READ) { - trigger(Event:DMA_READ, in_msg.LineAddress); + trigger(Event:DMA_READ, in_msg.LineAddress, pf_entry, tbe); } else if (in_msg.Type == DMARequestType:WRITE) { - trigger(Event:DMA_WRITE, in_msg.LineAddress); + trigger(Event:DMA_WRITE, in_msg.LineAddress, pf_entry, tbe); } else { error("Invalid message"); } @@ -360,25 +393,25 @@ machine(Directory, "AMD Hammer-like protocol") action(r_setMRU, "\rr", desc="manually set the MRU bit for pf entry" ) { if (probe_filter_enabled) { - assert(probeFilter.isTagPresent(address)); + assert(is_valid(cache_entry)); probeFilter.setMRU(address); } } action(auno_assertUnblockerNotOwner, "auno", desc="assert unblocker not owner") { if (probe_filter_enabled) { - assert(probeFilter.isTagPresent(address)); + assert(is_valid(cache_entry)); peek(unblockNetwork_in, ResponseMsg) { - assert(getPfEntry(address).Owner != in_msg.Sender); + assert(cache_entry.Owner != in_msg.Sender); } } } action(uo_updateOwnerIfPf, "uo", desc="update owner") { if (probe_filter_enabled) { - assert(probeFilter.isTagPresent(address)); + assert(is_valid(cache_entry)); peek(unblockNetwork_in, ResponseMsg) { - getPfEntry(address).Owner := in_msg.Sender; + cache_entry.Owner := in_msg.Sender; } } } @@ -410,8 +443,8 @@ machine(Directory, "AMD Hammer-like protocol") 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.allocate(address, new PfEntry)); + cache_entry.Owner := in_msg.Requestor; } } } @@ -419,92 +452,103 @@ machine(Directory, "AMD Hammer-like protocol") action(pfd_probeFilterDeallocate, "pfd", desc="Deallocate ProbeFilterEntry") { if (probe_filter_enabled) { probeFilter.deallocate(address); + unset_cache_entry(); } } action(ppfd_possibleProbeFilterDeallocate, "ppfd", desc="Deallocate ProbeFilterEntry") { - if (probe_filter_enabled && probeFilter.isTagPresent(address)) { + if (probe_filter_enabled && is_valid(cache_entry)) { probeFilter.deallocate(address); + unset_cache_entry(); } } 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); + assert(is_valid(tbe)); + tbe.NumPendingMsgs := machineCount(MachineType:L1Cache); } action(po_setPendingMsgsToOne, "po", desc="set pending msgs to one") { - TBEs[address].NumPendingMsgs := 1; + assert(is_valid(tbe)); + 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; + assert(is_valid(tbe)); + tbe.Acks := 1; } action(saa_setAcksToAllIfPF, "saa", desc="Non-forwarded request, set the ack amount to all") { + assert(is_valid(tbe)); 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(is_valid(tbe)); 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(is_valid(tbe)); 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 +557,12 @@ machine(Directory, "AMD Hammer-like protocol") } action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") { - if (TBEs[address].NumPendingMsgs == 0) { + assert(is_valid(tbe)); + 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 +575,8 @@ machine(Directory, "AMD Hammer-like protocol") } action(os_checkForMergedGetSCompletion, "os", desc="Check for merged GETS completion") { - if (TBEs[address].NumPendingMsgs == 0) { + assert(is_valid(tbe)); + if (tbe.NumPendingMsgs == 0) { enqueue(triggerQueue_out, TriggerMsg) { out_msg.Address := address; out_msg.Type := TriggerType:ALL_UNBLOCKS; @@ -539,17 +585,20 @@ machine(Directory, "AMD Hammer-like protocol") } action(sp_setPendingMsgsToMergedSharers, "sp", desc="Set pending messages to waiting sharers") { - TBEs[address].NumPendingMsgs := TBEs[address].GetSRequestors.count(); + assert(is_valid(tbe)); + 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; + assert(is_valid(tbe)); + tbe.NumPendingMsgs := 0; } } action(sc_signalCompletionIfPF, "sc", desc="indicate that we should skip waiting for cpu acks") { - if (TBEs[address].NumPendingMsgs == 0) { + assert(is_valid(tbe)); + if (tbe.NumPendingMsgs == 0) { assert(probe_filter_enabled); enqueue(triggerQueue_out, TriggerMsg) { out_msg.Address := address; @@ -561,14 +610,15 @@ machine(Directory, "AMD Hammer-like protocol") action(d_sendData, "d", desc="Send data to requestor") { peek(memQueue_in, MemoryMsg) { enqueue(responseNetwork_out, ResponseMsg, latency="1") { + assert(is_valid(tbe)); 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; @@ -579,6 +629,7 @@ machine(Directory, "AMD Hammer-like protocol") action(dr_sendDmaData, "dr", desc="Send Data to DMA controller from memory") { peek(memQueue_in, MemoryMsg) { enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + assert(is_valid(tbe)); out_msg.PhysicalAddress := address; out_msg.LineAddress := address; out_msg.Type := DMAResponseType:DATA; @@ -587,7 +638,7 @@ machine(Directory, "AMD Hammer-like protocol") // 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; } } @@ -596,6 +647,7 @@ machine(Directory, "AMD Hammer-like protocol") action(dt_sendDmaDataFromTbe, "dt", desc="Send Data to DMA controller from tbe") { peek(triggerQueue_in, TriggerMsg) { enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + assert(is_valid(tbe)); out_msg.PhysicalAddress := address; out_msg.LineAddress := address; out_msg.Type := DMAResponseType:DATA; @@ -603,8 +655,8 @@ machine(Directory, "AMD Hammer-like protocol") // 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; } } @@ -612,39 +664,45 @@ machine(Directory, "AMD Hammer-like protocol") action(da_sendDmaAck, "da", desc="Send Ack to DMA controller") { enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + assert(is_valid(tbe)); 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; + assert(is_valid(tbe)); + tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE; } } action(r_recordDataInTBE, "rt", desc="Record Data in TBE") { peek(requestQueue_in, RequestMsg) { - TBEs[address].ResponseType := CoherenceResponseType:DATA; + assert(is_valid(tbe)); + 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); + assert(is_valid(tbe)); + tbe.GetSRequestors.add(in_msg.Requestor); } } action(r_setSharerBit, "r", desc="We saw other sharers") { - TBEs[address].Sharers := true; + assert(is_valid(tbe)); + tbe.Sharers := true; } action(so_setOwnerBit, "so", desc="We saw other sharers") { - TBEs[address].Sharers := true; - TBEs[address].Owned := true; + assert(is_valid(tbe)); + tbe.Sharers := true; + tbe.Owned := true; } action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") { @@ -676,7 +734,8 @@ machine(Directory, "AMD Hammer-like protocol") } action(fn_forwardRequestIfNecessary, "fn", desc="Forward requests if necessary") { - if ((machineCount(MachineType:L1Cache) > 1) && (TBEs[address].Acks <= 1)) { + assert(is_valid(tbe)); + if ((machineCount(MachineType:L1Cache) > 1) && (tbe.Acks <= 1)) { peek(requestQueue_in, RequestMsg) { enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { out_msg.Address := address; @@ -707,10 +766,11 @@ machine(Directory, "AMD Hammer-like protocol") action(io_invalidateOwnerRequest, "io", desc="invalidate all copies") { if (machineCount(MachineType:L1Cache) > 1) { enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { + assert(is_valid(cache_entry)); out_msg.Address := address; out_msg.Type := CoherenceRequestType:INV; out_msg.Requestor := machineID; - out_msg.Destination.add(getPfEntry(address).Owner); + out_msg.Destination.add(cache_entry.Owner); out_msg.MessageSize := MessageSizeType:Request_Control; out_msg.DirectedProbe := true; } @@ -742,9 +802,10 @@ machine(Directory, "AMD Hammer-like protocol") // peek(unblockNetwork_in, ResponseMsg) { enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { + assert(is_valid(tbe)); 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 { @@ -762,10 +823,11 @@ machine(Directory, "AMD Hammer-like protocol") if (probe_filter_enabled) { peek(requestQueue_in, RequestMsg) { enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { + assert(is_valid(cache_entry)); 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(cache_entry.Owner); out_msg.MessageSize := MessageSizeType:Request_Control; out_msg.DirectedProbe := true; out_msg.InitialRequestTime := in_msg.InitialRequestTime; @@ -789,7 +851,8 @@ machine(Directory, "AMD Hammer-like protocol") } action(f_forwardWriteFromDma, "fw", desc="Forward requests") { - if (TBEs[address].NumPendingMsgs > 0) { + assert(is_valid(tbe)); + if (tbe.NumPendingMsgs > 0) { peek(dmaRequestQueue_in, DMARequestMsg) { enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { out_msg.Address := address; @@ -807,7 +870,8 @@ machine(Directory, "AMD Hammer-like protocol") } action(f_forwardReadFromDma, "fr", desc="Forward requests") { - if (TBEs[address].NumPendingMsgs > 0) { + assert(is_valid(tbe)); + if (tbe.NumPendingMsgs > 0) { peek(dmaRequestQueue_in, DMARequestMsg) { enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { out_msg.Address := address; @@ -860,16 +924,18 @@ machine(Directory, "AMD Hammer-like protocol") 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; + assert(is_valid(tbe)); + 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; + assert(is_valid(tbe)); + tbe.CacheDirty := true; + tbe.DataBlk := in_msg.DataBlk; } } @@ -893,26 +959,30 @@ machine(Directory, "AMD Hammer-like protocol") 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; + assert(is_valid(tbe)); + 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") { + assert(is_valid(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(is_valid(tbe)); + 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(is_valid(cache_entry)); + assert(cache_entry.Owner != in_msg.Requestor); } } } @@ -929,12 +999,13 @@ machine(Directory, "AMD Hammer-like protocol") action(ld_queueMemoryDmaWrite, "ld", desc="Write DMA data to memory") { enqueue(memQueue_out, MemoryMsg, latency="1") { + assert(is_valid(tbe)); 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); } } diff --git a/src/mem/protocol/RubySlicc_Types.sm b/src/mem/protocol/RubySlicc_Types.sm index 9d3cd6634..1d68768e4 100644 --- a/src/mem/protocol/RubySlicc_Types.sm +++ b/src/mem/protocol/RubySlicc_Types.sm @@ -117,15 +117,16 @@ external_type(DirectoryMemory) { void invalidateBlock(Address); } -external_type(AbstractCacheEntry, primitive="yes"); +external_type(AbstractCacheEntry, primitive="yes") { + void changePermission(AccessPermission); +} external_type(CacheMemory) { bool cacheAvail(Address); Address cacheProbe(Address); - void allocate(Address, AbstractCacheEntry); + AbstractCacheEntry allocate(Address, AbstractCacheEntry); void deallocate(Address); AbstractCacheEntry lookup(Address); - void changePermission(Address, AccessPermission); bool isTagPresent(Address); void profileMiss(CacheMsg); |