summaryrefslogtreecommitdiff
path: root/src/mem/protocol/MESI_Three_Level-L0cache.sm
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2015-08-03 22:44:29 -0500
committerNilay Vaish <nilay@cs.wisc.edu>2015-08-03 22:44:29 -0500
commit676ae5782796bd6b4f202e138b72c1048efceabd (patch)
tree9fc422b12874e842f4ea4bb473e3c24d8275c6e6 /src/mem/protocol/MESI_Three_Level-L0cache.sm
parent9bf3b8828a19570f50914d86d76e32896ecd12bb (diff)
downloadgem5-676ae5782796bd6b4f202e138b72c1048efceabd.tar.xz
ruby: mesi three level: multiple corrections to the protocol
1. Eliminate state NP in L0 and L1 Caches: The two states 'NP' and 'I' both mean that the cache block is not present in the cache. 'I' also means that the cache entry has been allocated. This causes problems when we do not correctly initialize the cache entry when it is re-used. Hence, this patch eliminates the state NP altogether. Everytime a new block comes into the cache, a cache entry is allocated. Everytime a block leaves, the corresponding entry is deallocated. 2. Separate transient state for instruction fetches: purely for accouting purposes. 3. Drop state IS_I in L1 Cache and the message type STALE_DATA: when invalidation is received for a block in IS, the block used to be moved to IS_I. This meant that the data that would arrive in future would be used but not stored since the controller lost the permissions after gaining them. This state is being dropped and now invalidation messages would not processed till the data has arrived. This also means that STALE_DATA type is not longer required.
Diffstat (limited to 'src/mem/protocol/MESI_Three_Level-L0cache.sm')
-rw-r--r--src/mem/protocol/MESI_Three_Level-L0cache.sm70
1 files changed, 46 insertions, 24 deletions
diff --git a/src/mem/protocol/MESI_Three_Level-L0cache.sm b/src/mem/protocol/MESI_Three_Level-L0cache.sm
index 8ab0a92cb..5bbc83bd0 100644
--- a/src/mem/protocol/MESI_Three_Level-L0cache.sm
+++ b/src/mem/protocol/MESI_Three_Level-L0cache.sm
@@ -48,9 +48,6 @@ machine(L0Cache, "MESI Directory L0 Cache")
// Base states
// The cache entry has not been allocated.
- NP, AccessPermission:Invalid, desc="Not present in either cache";
-
- // The cache entry has been allocated, but is not in use.
I, AccessPermission:Invalid;
// The cache entry is in shared mode. The processor can read this entry
@@ -67,6 +64,10 @@ machine(L0Cache, "MESI Directory L0 Cache")
// Transient States
+ // The cache controller has requested an instruction. It will be stored
+ // in the shared state so that the processor can read it.
+ Inst_IS, AccessPermission:Busy;
+
// The cache controller has requested that this entry be fetched in
// shared state so that the processor can read it.
IS, AccessPermission:Busy;
@@ -100,7 +101,6 @@ machine(L0Cache, "MESI Directory L0 Cache")
Data, desc="Data for processor";
Data_Exclusive, desc="Data for processor";
- Data_Stale, desc="Data for processor, but not for storage";
Ack, desc="Ack for processor";
Ack_all, desc="Last ack for processor";
@@ -172,7 +172,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
} else if (is_valid(cache_entry)) {
return cache_entry.CacheState;
}
- return State:NP;
+ return State:I;
}
void setState(TBE tbe, Entry cache_entry, Address addr, State state) {
@@ -266,8 +266,6 @@ machine(L0Cache, "MESI Directory L0 Cache")
trigger(Event:Data_Exclusive, in_msg.Addr, cache_entry, tbe);
} else if(in_msg.Class == CoherenceClass:DATA) {
trigger(Event:Data, in_msg.Addr, cache_entry, tbe);
- } else if(in_msg.Class == CoherenceClass:STALE_DATA) {
- trigger(Event:Data_Stale, in_msg.Addr, cache_entry, tbe);
} else if (in_msg.Class == CoherenceClass:ACK) {
trigger(Event:Ack, in_msg.Addr, cache_entry, tbe);
} else if (in_msg.Class == CoherenceClass:WB_ACK) {
@@ -421,6 +419,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
out_msg.Dest := createMachineID(MachineType:L1Cache, version);
out_msg.MessageSize := MessageSizeType:Writeback_Data;
}
+ cache_entry.Dirty := false;
}
action(fi_sendInvAck, "fi", desc="send data to the L2 cache") {
@@ -447,13 +446,13 @@ machine(L0Cache, "MESI Directory L0 Cache")
assert(is_valid(cache_entry));
out_msg.Addr := address;
out_msg.Class := CoherenceClass:PUTX;
- out_msg.DataBlk := cache_entry.DataBlk;
out_msg.Dirty := cache_entry.Dirty;
out_msg.Sender:= machineID;
out_msg.Dest := createMachineID(MachineType:L1Cache, version);
if (cache_entry.Dirty) {
out_msg.MessageSize := MessageSizeType:Writeback_Data;
+ out_msg.DataBlk := cache_entry.DataBlk;
} else {
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
@@ -466,6 +465,12 @@ machine(L0Cache, "MESI Directory L0 Cache")
sequencer.readCallback(address, cache_entry.DataBlk);
}
+ action(hx_load_hit, "hx", desc="If not prefetch, notify sequencer the load completed.") {
+ assert(is_valid(cache_entry));
+ DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+ sequencer.readCallback(address, cache_entry.DataBlk, true);
+ }
+
action(hh_store_hit, "\h", desc="If not prefetch, notify sequencer that store completed.") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
@@ -473,6 +478,13 @@ machine(L0Cache, "MESI Directory L0 Cache")
cache_entry.Dirty := true;
}
+ action(hhx_store_hit, "\hx", desc="If not prefetch, notify sequencer that store completed.") {
+ assert(is_valid(cache_entry));
+ DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
+ sequencer.writeCallback(address, cache_entry.DataBlk, true);
+ cache_entry.Dirty := true;
+ }
+
action(i_allocateTBE, "i", desc="Allocate TBE (number of invalidates=0)") {
check_allocate(TBEs);
assert(is_valid(cache_entry));
@@ -505,7 +517,13 @@ machine(L0Cache, "MESI Directory L0 Cache")
peek(messgeBuffer_in, CoherenceMsg) {
assert(is_valid(cache_entry));
cache_entry.DataBlk := in_msg.DataBlk;
- cache_entry.Dirty := in_msg.Dirty;
+ }
+ }
+
+ action(u_writeInstToCache, "ui", desc="Write data to cache") {
+ peek(messgeBuffer_in, CoherenceMsg) {
+ assert(is_valid(cache_entry));
+ cache_entry.DataBlk := in_msg.DataBlk;
}
}
@@ -560,16 +578,12 @@ machine(L0Cache, "MESI Directory L0 Cache")
//*****************************************************
// Transitions for Load/Store/Replacement/WriteBack from transient states
- transition({IS, IM, SM}, {Load, Ifetch, Store, L0_Replacement}) {
+ transition({Inst_IS, IS, IM, SM}, {Load, Ifetch, Store, L0_Replacement}) {
z_stallAndWaitMandatoryQueue;
}
// Transitions from Idle
- transition({NP,I}, L0_Replacement) {
- ff_deallocateCacheBlock;
- }
-
- transition({NP,I}, Load, IS) {
+ transition(I, Load, IS) {
oo_allocateDCacheBlock;
i_allocateTBE;
a_issueGETS;
@@ -577,7 +591,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
k_popMandatoryQueue;
}
- transition({NP,I}, Ifetch, IS) {
+ transition(I, Ifetch, Inst_IS) {
pp_allocateICacheBlock;
i_allocateTBE;
a_issueGETS;
@@ -585,7 +599,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
k_popMandatoryQueue;
}
- transition({NP,I}, Store, IM) {
+ transition(I, Store, IM) {
oo_allocateDCacheBlock;
i_allocateTBE;
b_issueGETX;
@@ -593,7 +607,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
k_popMandatoryQueue;
}
- transition({NP, I, IS, IM}, Inv) {
+ transition({I, IS, IM, Inst_IS}, Inv) {
fi_sendInvAck;
l_popRequestQueue;
}
@@ -682,7 +696,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
transition(IS, Data, S) {
u_writeDataToCache;
- h_load_hit;
+ hx_load_hit;
s_deallocateTBE;
o_popIncomingResponseQueue;
kd_wakeUpDependents;
@@ -690,15 +704,23 @@ machine(L0Cache, "MESI Directory L0 Cache")
transition(IS, Data_Exclusive, E) {
u_writeDataToCache;
- h_load_hit;
+ hx_load_hit;
s_deallocateTBE;
o_popIncomingResponseQueue;
kd_wakeUpDependents;
}
- transition(IS, Data_Stale, I) {
- u_writeDataToCache;
- h_load_hit;
+ transition(Inst_IS, Data, S) {
+ u_writeInstToCache;
+ hx_load_hit;
+ s_deallocateTBE;
+ o_popIncomingResponseQueue;
+ kd_wakeUpDependents;
+ }
+
+ transition(Inst_IS, Data_Exclusive, E) {
+ u_writeInstToCache;
+ hx_load_hit;
s_deallocateTBE;
o_popIncomingResponseQueue;
kd_wakeUpDependents;
@@ -706,7 +728,7 @@ machine(L0Cache, "MESI Directory L0 Cache")
transition({IM,SM}, Data_Exclusive, M) {
u_writeDataToCache;
- hh_store_hit;
+ hhx_store_hit;
s_deallocateTBE;
o_popIncomingResponseQueue;
kd_wakeUpDependents;