Ruby: Reorder Cache Lookup in Protocol Files
The patch changes the order in which L1 dcache and icache are looked up when a request comes in. Earlier, if a request came in for instruction fetch, the dcache was looked up before the icache, to correctly handle self-modifying code. But, in the common case, dcache is going to report a miss and the subsequent icache lookup is going to report a hit. Given the invariant - caches under the same controller keep track of disjoint sets of cache blocks, we can move the icache lookup before the dcache lookup. In case of a hit in the icache, using our invariant, we know that the dcache would have reported a miss. In case of a miss in the icache, we know that icache would have missed even if the dcache was looked up before looking up the icache. Effectively, we are doing the same thing as before, though in the common case, we expect reduction in the number of lookups. This was empirically confirmed for MOESI hammer. The ratio lookups to access requests is now about 1.1 to 1.
This commit is contained in:
parent
2971b8401a
commit
0cede15d6c
4 changed files with 82 additions and 77 deletions
|
@ -287,6 +287,13 @@ machine(L1Cache, "MSI Directory L1 Cache CMP")
|
|||
if (in_msg.Type == CacheRequestType:IFETCH) {
|
||||
// ** INSTRUCTION ACCESS ***
|
||||
|
||||
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,
|
||||
L1Icache_entry, L1_TBEs[in_msg.LineAddress]);
|
||||
} else {
|
||||
|
||||
// Check to see if it is in the OTHER L1
|
||||
Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress);
|
||||
if (is_valid(L1Dcache_entry)) {
|
||||
|
@ -295,12 +302,6 @@ machine(L1Cache, "MSI Directory L1 Cache CMP")
|
|||
L1Dcache_entry, L1_TBEs[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,
|
||||
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,
|
||||
|
@ -313,7 +314,15 @@ machine(L1Cache, "MSI Directory L1 Cache CMP")
|
|||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// *** DATA ACCESS ***
|
||||
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,
|
||||
L1Dcache_entry, L1_TBEs[in_msg.LineAddress]);
|
||||
} else {
|
||||
|
||||
// Check to see if it is in the OTHER L1
|
||||
Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress);
|
||||
if (is_valid(L1Icache_entry)) {
|
||||
|
@ -322,12 +331,6 @@ machine(L1Cache, "MSI Directory L1 Cache CMP")
|
|||
L1Icache_entry, L1_TBEs[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,
|
||||
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,
|
||||
|
|
|
@ -338,14 +338,6 @@ machine(L1Cache, "Directory protocol")
|
|||
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 (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, L1Dcache_entry,
|
||||
TBEs[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.
|
||||
|
@ -353,6 +345,14 @@ machine(L1Cache, "Directory protocol")
|
|||
in_msg.LineAddress, L1Icache_entry,
|
||||
TBEs[in_msg.LineAddress]);
|
||||
} else {
|
||||
|
||||
Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress);
|
||||
// Check to see if it is in the OTHER L1
|
||||
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, L1Dcache_entry,
|
||||
TBEs[in_msg.LineAddress]);
|
||||
}
|
||||
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),
|
||||
|
@ -369,14 +369,6 @@ machine(L1Cache, "Directory protocol")
|
|||
} else {
|
||||
// *** DATA ACCESS ***
|
||||
|
||||
Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress);
|
||||
// Check to see if it is in the OTHER L1
|
||||
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,
|
||||
L1Icache_entry, TBEs[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
|
||||
|
@ -384,6 +376,14 @@ machine(L1Cache, "Directory protocol")
|
|||
in_msg.LineAddress, L1Dcache_entry,
|
||||
TBEs[in_msg.LineAddress]);
|
||||
} else {
|
||||
|
||||
Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress);
|
||||
// Check to see if it is in the OTHER L1
|
||||
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,
|
||||
L1Icache_entry, TBEs[in_msg.LineAddress]);
|
||||
}
|
||||
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),
|
||||
|
|
|
@ -647,6 +647,13 @@ machine(L1Cache, "Token protocol")
|
|||
if (in_msg.Type == CacheRequestType:IFETCH) {
|
||||
// ** INSTRUCTION ACCESS ***
|
||||
|
||||
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, L1Icache_entry, tbe);
|
||||
} else {
|
||||
|
||||
// Check to see if it is in the OTHER L1
|
||||
Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress);
|
||||
if (is_valid(L1Dcache_entry)) {
|
||||
|
@ -655,12 +662,6 @@ machine(L1Cache, "Token protocol")
|
|||
L1Dcache_entry, tbe);
|
||||
}
|
||||
|
||||
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, 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),
|
||||
|
@ -676,21 +677,21 @@ machine(L1Cache, "Token protocol")
|
|||
} else {
|
||||
// *** DATA ACCESS ***
|
||||
|
||||
// Check to see if it is in the OTHER L1
|
||||
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,
|
||||
L1Icache_entry, tbe);
|
||||
}
|
||||
|
||||
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, L1Dcache_entry, tbe);
|
||||
} else {
|
||||
|
||||
// Check to see if it is in the OTHER L1
|
||||
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,
|
||||
L1Icache_entry, tbe);
|
||||
}
|
||||
|
||||
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),
|
||||
|
|
|
@ -377,6 +377,12 @@ machine(L1Cache, "AMD Hammer-like protocol")
|
|||
if (in_msg.Type == CacheRequestType:IFETCH) {
|
||||
// ** INSTRUCTION ACCESS ***
|
||||
|
||||
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, L1Icache_entry, tbe);
|
||||
} else {
|
||||
// Check to see if it is in the OTHER L1
|
||||
Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress);
|
||||
if (is_valid(L1Dcache_entry)) {
|
||||
|
@ -391,12 +397,6 @@ machine(L1Cache, "AMD Hammer-like protocol")
|
|||
}
|
||||
}
|
||||
|
||||
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, 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
|
||||
|
||||
|
@ -430,6 +430,13 @@ machine(L1Cache, "AMD Hammer-like protocol")
|
|||
} else {
|
||||
// *** DATA ACCESS ***
|
||||
|
||||
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, L1Dcache_entry, tbe);
|
||||
} else {
|
||||
|
||||
// Check to see if it is in the OTHER L1
|
||||
Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress);
|
||||
if (is_valid(L1Icache_entry)) {
|
||||
|
@ -444,12 +451,6 @@ machine(L1Cache, "AMD Hammer-like protocol")
|
|||
}
|
||||
}
|
||||
|
||||
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, 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
|
||||
Entry L2cache_entry := getL2CacheEntry(in_msg.LineAddress);
|
||||
|
|
Loading…
Reference in a new issue