summaryrefslogtreecommitdiff
path: root/src/mem/protocol/MESI_CMP_directory-L2cache.sm
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2011-01-17 18:46:16 -0600
committerNilay Vaish <nilay@cs.wisc.edu>2011-01-17 18:46:16 -0600
commitc82a8979a3909037a1654fc66cb215b5bacadb08 (patch)
treeb0b51c589c665812df1ec8eb1c40adfc98877f08 /src/mem/protocol/MESI_CMP_directory-L2cache.sm
parent6fb521faba37a47ebce2aebb08ac34bd69d29f13 (diff)
downloadgem5-c82a8979a3909037a1654fc66cb215b5bacadb08.tar.xz
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with coherence protocols. Currently, whenever a cache controller (defined in the protocol under consideration) needs to carry out any operation on a cache block, it looks up the tag hash map and figures out whether or not the block exists in the cache. In case it does exist, the operation is carried out (which requires another lookup). As observed through profiling of different protocols, multiple such lookups take place for a given cache block. It was noted that the tag lookup takes anything from 10% to 20% of the simulation time. In order to reduce this time, this patch is being posted. I have to acknowledge that the many of the thoughts that went in to this patch belong to Brad. Changes to CacheMemory, TBETable and AbstractCacheEntry classes: 1. The lookup function belonging to CacheMemory class now returns a pointer to a cache block entry, instead of a reference. The pointer is NULL in case the block being looked up is not present in the cache. Similar change has been carried out in the lookup function of the TBETable class. 2. Function for setting and getting access permission of a cache block have been moved from CacheMemory class to AbstractCacheEntry class. 3. The allocate function in CacheMemory class now returns pointer to the allocated cache entry. Changes to SLICC: 1. Each action now has implicit variables - cache_entry and tbe. cache_entry, if != NULL, must point to the cache entry for the address on which the action is being carried out. Similarly, tbe should also point to the transaction buffer entry of the address on which the action is being carried out. 2. If a cache entry or a transaction buffer entry is passed on as an argument to a function, it is presumed that a pointer is being passed on. 3. The cache entry and the tbe pointers received __implicitly__ by the actions, are passed __explicitly__ to the trigger function. 4. While performing an action, set/unset_cache_entry, set/unset_tbe are to be used for setting / unsetting cache entry and tbe pointers respectively. 5. is_valid() and is_invalid() has been made available for testing whether a given pointer 'is not NULL' and 'is NULL' respectively. 6. Local variables are now available, but they are assumed to be pointers always. 7. It is now possible for an object of the derieved class to make calls to a function defined in the interface. 8. An OOD token has been introduced in SLICC. It is same as the NULL token used in C/C++. If you are wondering, OOD stands for Out Of Domain. 9. static_cast can now taken an optional parameter that asks for casting the given variable to a pointer of the given type. 10. Functions can be annotated with 'return_by_pointer=yes' to return a pointer. 11. StateMachine has two new variables, EntryType and TBEType. EntryType is set to the type which inherits from 'AbstractCacheEntry'. There can only be one such type in the machine. TBEType is set to the type for which 'TBE' is used as the name. All the protocols have been modified to conform with the new interface.
Diffstat (limited to 'src/mem/protocol/MESI_CMP_directory-L2cache.sm')
-rw-r--r--src/mem/protocol/MESI_CMP_directory-L2cache.sm308
1 files changed, 174 insertions, 134 deletions
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;
}
}
-
-
-