mem-ruby: MESI_Three_Level LL/SC improvements
This patch fixes the MESI_Three_Level protocols so that it correctly informers the Ruby sequencer when a line eviction occurs. Furthermore, the patch allows the protocol to recognize the 'Store_Conditional' RubyRequestType and shortcuts this operation if the monitored line has been cleared from the address monitor. This prevents certain livelock behaviour in which a line could ping-pong between competing cores. The patch establishes a new C/C++ preprocessor definition which allows the Sequencer to send the 'Store_Conditional' RubyRequestType to MESI_Three_Level instead of 'ST'. This is a temporary measure until the other protocols explicitely recognize 'Store_Conditional'. Change-Id: I27ae041ab0e015a4f54f20df666f9c4873c7583d Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/28328 Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br> Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Pouya Fotouhi
parent
dd6cd33344
commit
e61f10740b
@@ -121,6 +121,8 @@ machine(MachineType:L0Cache, "MESI Directory L0 Cache")
|
||||
Ack, desc="Ack for processor";
|
||||
|
||||
WB_Ack, desc="Ack for replacement";
|
||||
|
||||
Failed_SC, desc="Store conditional request that will fail";
|
||||
}
|
||||
|
||||
// TYPES
|
||||
@@ -257,7 +259,8 @@ machine(MachineType:L0Cache, "MESI Directory L0 Cache")
|
||||
return Event:Load;
|
||||
} else if (type == RubyRequestType:IFETCH) {
|
||||
return Event:Ifetch;
|
||||
} else if ((type == RubyRequestType:ST) || (type == RubyRequestType:ATOMIC)) {
|
||||
} else if ((type == RubyRequestType:ST) || (type == RubyRequestType:ATOMIC)
|
||||
|| (type == RubyRequestType:Store_Conditional)) {
|
||||
return Event:Store;
|
||||
} else {
|
||||
error("Invalid RubyRequestType");
|
||||
@@ -349,36 +352,51 @@ machine(MachineType:L0Cache, "MESI Directory L0 Cache")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// *** DATA ACCESS ***
|
||||
Entry Dcache_entry := getDCacheEntry(in_msg.LineAddress);
|
||||
|
||||
// early out for failed store conditionals
|
||||
|
||||
if (in_msg.Type == RubyRequestType:Store_Conditional) {
|
||||
if (!sequencer.llscCheckMonitor(in_msg.LineAddress)) {
|
||||
trigger(Event:Failed_SC, in_msg.LineAddress,
|
||||
Dcache_entry, TBEs[in_msg.LineAddress]);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_valid(Dcache_entry)) {
|
||||
// The tag matches for the L0, so the L0 ask the L1 for it
|
||||
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress,
|
||||
Dcache_entry, TBEs[in_msg.LineAddress]);
|
||||
} else {
|
||||
|
||||
// Check to see if it is in the OTHER L0
|
||||
Entry Icache_entry := getICacheEntry(in_msg.LineAddress);
|
||||
if (is_valid(Icache_entry)) {
|
||||
// The block is in the wrong L0, put the request on the queue to the private L1
|
||||
trigger(Event:L0_Replacement, in_msg.LineAddress,
|
||||
Icache_entry, TBEs[in_msg.LineAddress]);
|
||||
}
|
||||
|
||||
if (Dcache.cacheAvail(in_msg.LineAddress)) {
|
||||
// L1 does't have the line, but we have space for it
|
||||
// in the L0 let's see if the L1 has it
|
||||
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress,
|
||||
Dcache_entry, TBEs[in_msg.LineAddress]);
|
||||
// if the request is not valid, the store conditional will fail
|
||||
if (in_msg.Type == RubyRequestType:Store_Conditional) {
|
||||
// if the line is not valid, it can't be locked
|
||||
trigger(Event:Failed_SC, in_msg.LineAddress,
|
||||
Dcache_entry, TBEs[in_msg.LineAddress]);
|
||||
} else {
|
||||
// No room in the L1, so we need to make room in the L0
|
||||
// Check if the line we want to evict is not locked
|
||||
Addr addr := Dcache.cacheProbe(in_msg.LineAddress);
|
||||
check_on_cache_probe(mandatoryQueue_in, addr);
|
||||
trigger(Event:L0_Replacement, addr,
|
||||
getDCacheEntry(addr),
|
||||
TBEs[addr]);
|
||||
// Check to see if it is in the OTHER L0
|
||||
Entry Icache_entry := getICacheEntry(in_msg.LineAddress);
|
||||
if (is_valid(Icache_entry)) {
|
||||
// The block is in the wrong L0, put the request on the queue to the private L1
|
||||
trigger(Event:L0_Replacement, in_msg.LineAddress,
|
||||
Icache_entry, TBEs[in_msg.LineAddress]);
|
||||
}
|
||||
|
||||
if (Dcache.cacheAvail(in_msg.LineAddress)) {
|
||||
// L1 does't have the line, but we have space for it
|
||||
// in the L0 let's see if the L1 has it
|
||||
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress,
|
||||
Dcache_entry, TBEs[in_msg.LineAddress]);
|
||||
} else {
|
||||
// No room in the L1, so we need to make room in the L0
|
||||
// Check if the line we want to evict is not locked
|
||||
Addr addr := Dcache.cacheProbe(in_msg.LineAddress);
|
||||
check_on_cache_probe(mandatoryQueue_in, addr);
|
||||
trigger(Event:L0_Replacement, addr,
|
||||
getDCacheEntry(addr),
|
||||
TBEs[addr]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -629,6 +647,13 @@ machine(MachineType:L0Cache, "MESI Directory L0 Cache")
|
||||
++Dcache.demand_hits;
|
||||
}
|
||||
|
||||
// store conditionals
|
||||
|
||||
action(hhc_storec_fail, "\hc",
|
||||
desc="Notify sequencer that store conditional failed") {
|
||||
sequencer.writeCallbackScFail(address, cache_entry.DataBlk);
|
||||
}
|
||||
|
||||
//*****************************************************
|
||||
// TRANSITIONS
|
||||
//*****************************************************
|
||||
@@ -664,11 +689,13 @@ machine(MachineType:L0Cache, "MESI Directory L0 Cache")
|
||||
}
|
||||
|
||||
transition({I, IS, IM, Inst_IS}, {InvOwn, InvElse}) {
|
||||
forward_eviction_to_cpu;
|
||||
fi_sendInvAck;
|
||||
l_popRequestQueue;
|
||||
}
|
||||
|
||||
transition(SM, {InvOwn, InvElse}, IM) {
|
||||
forward_eviction_to_cpu;
|
||||
fi_sendInvAck;
|
||||
l_popRequestQueue;
|
||||
}
|
||||
@@ -768,6 +795,7 @@ machine(MachineType:L0Cache, "MESI Directory L0 Cache")
|
||||
|
||||
transition(IS, Data_Stale, I) {
|
||||
u_writeDataToCache;
|
||||
forward_eviction_to_cpu;
|
||||
hx_load_hit;
|
||||
s_deallocateTBE;
|
||||
ff_deallocateCacheBlock;
|
||||
@@ -807,4 +835,12 @@ machine(MachineType:L0Cache, "MESI Directory L0 Cache")
|
||||
o_popIncomingResponseQueue;
|
||||
kd_wakeUpDependents;
|
||||
}
|
||||
|
||||
// store conditionals
|
||||
|
||||
transition({I,S,E,M}, Failed_SC) {
|
||||
// IS,IM,SM don't handle store conditionals
|
||||
hhc_storec_fail;
|
||||
k_popMandatoryQueue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# -*- mode:python -*-
|
||||
|
||||
# Copyright (c) 2020 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
# not be construed as granting a license to any other intellectual
|
||||
# property including but not limited to intellectual property relating
|
||||
# to a hardware implementation of the functionality of the software
|
||||
# licensed hereunder. You may use the software subject to the license
|
||||
# terms below provided that you ensure that this notice is replicated
|
||||
# unmodified and in its entirety in all distributions of the software,
|
||||
# modified or unmodified, in source code or in binary form.
|
||||
#
|
||||
# Copyright (c) 2009 The Hewlett-Packard Development Company
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -31,6 +43,8 @@ Import('*')
|
||||
if env['PROTOCOL'] == 'None':
|
||||
Return()
|
||||
|
||||
env.Append(CPPDEFINES=['PROTOCOL_' + env['PROTOCOL']])
|
||||
|
||||
if env['BUILD_GPU']:
|
||||
SimObject('GPUCoalescer.py')
|
||||
SimObject('RubySystem.py')
|
||||
|
||||
@@ -590,7 +590,11 @@ Sequencer::makeRequest(PacketPtr pkt)
|
||||
if (pkt->isWrite()) {
|
||||
DPRINTF(RubySequencer, "Issuing SC\n");
|
||||
primary_type = RubyRequestType_Store_Conditional;
|
||||
#ifdef PROTOCOL_MESI_Three_Level
|
||||
secondary_type = RubyRequestType_Store_Conditional;
|
||||
#else
|
||||
secondary_type = RubyRequestType_ST;
|
||||
#endif
|
||||
} else {
|
||||
DPRINTF(RubySequencer, "Issuing LL\n");
|
||||
assert(pkt->isRead());
|
||||
|
||||
Reference in New Issue
Block a user