changeset b9c7716f6aa6 in /z/repo/m5
details: http://repo.m5sim.org/m5?cmd=changeset;node=b9c7716f6aa6
description:
ruby: Changes necessary to get the hammer protocol to work in GEM5
diffstat:
5 files changed, 141 insertions(+), 92 deletions(-)
src/mem/protocol/MOESI_hammer-cache.sm | 178 ++++++++++++++++++--------------
src/mem/protocol/MOESI_hammer-dir.sm | 38 +++++-
src/mem/protocol/MOESI_hammer-msg.sm | 7 -
src/mem/protocol/MOESI_hammer.slicc | 9 -
src/mem/protocol/SConsopts | 1
diffs (truncated from 558 to 300 lines):
diff -r 000fa68c57a9 -r b9c7716f6aa6 src/mem/protocol/MOESI_hammer-cache.sm
--- a/src/mem/protocol/MOESI_hammer-cache.sm Wed Nov 18 16:34:31 2009 -0800
+++ b/src/mem/protocol/MOESI_hammer-cache.sm Wed Nov 18 16:34:32 2009 -0800
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,9 +25,27 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * AMD's contributions to the MOESI hammer protocol do not constitute an
+ * endorsement of its similarity to any AMD products.
+ *
+ * Authors: Milo Martin
+ * Brad Beckmann
*/
-machine(L1Cache, "AMD Hammer-like protocol") {
+machine(L1Cache, "AMD Hammer-like protocol")
+: int cache_response_latency,
+ int issue_latency
+{
+
+ // NETWORK BUFFERS
+ MessageBuffer requestFromCache, network="To", virtual_network="3",
ordered="false";
+ MessageBuffer responseFromCache, network="To", virtual_network="1",
ordered="false";
+ MessageBuffer unblockFromCache, network="To", virtual_network="0",
ordered="false";
+
+ MessageBuffer forwardToCache, network="From", virtual_network="2",
ordered="false";
+ MessageBuffer responseToCache, network="From", virtual_network="1",
ordered="false";
+
// STATES
enumeration(State, desc="Cache states", default="L1Cache_State_I") {
@@ -82,14 +101,16 @@
// TYPES
+ // STRUCTURE DEFINITIONS
+
+ MessageBuffer mandatoryQueue, ordered="false";
+ Sequencer sequencer, factory='RubySystem::getSequencer(m_cfg["sequencer"])';
+
// CacheEntry
- structure(Entry, desc="...") {
- Address Address, desc="Address of this block, required by
CacheMemory";
- Time LastRef, desc="Last time this block was referenced,
required by CacheMemory";
- AccessPermission Permission, desc="Access permission for this block,
required by CacheMemory";
- DataBlock DataBlk, desc="data for the block, required by
CacheMemory";
+ structure(Entry, desc="...", interface="AbstractCacheEntry") {
State CacheState, desc="cache state";
bool Dirty, desc="Is the data dirty (different than memory)?";
+ DataBlock DataBlk, desc="data for the block";
}
// TBE fields
@@ -101,27 +122,28 @@
bool Sharers, desc="On a GetS, did we find any other sharers in
the system";
}
- external_type(NewCacheMemory) {
+ external_type(CacheMemory) {
bool cacheAvail(Address);
Address cacheProbe(Address);
- void allocate(Address);
+ void allocate(Address, Entry);
void deallocate(Address);
Entry lookup(Address);
void changePermission(Address, AccessPermission);
bool isTagPresent(Address);
+ void profileMiss(CacheMsg);
}
- external_type(NewTBETable) {
+ external_type(TBETable) {
TBE lookup(Address);
void allocate(Address);
void deallocate(Address);
bool isPresent(Address);
}
- NewTBETable TBEs, template_hack="<L1Cache_TBE>";
- NewCacheMemory L1IcacheMemory, template_hack="<L1Cache_Entry>",
constructor_hack='L1_CACHE_NUM_SETS_BITS,L1_CACHE_ASSOC,"L1I"';
- NewCacheMemory L1DcacheMemory, template_hack="<L1Cache_Entry>",
constructor_hack='L1_CACHE_NUM_SETS_BITS,L1_CACHE_ASSOC,"L1D"';
- NewCacheMemory L2cacheMemory, template_hack="<L1Cache_Entry>",
constructor_hack='L2_CACHE_NUM_SETS_BITS,L2_CACHE_ASSOC,"L2"';
+ TBETable TBEs, template_hack="<L1Cache_TBE>";
+ CacheMemory L1IcacheMemory, factory='RubySystem::getCache(m_cfg["icache"])';
+ CacheMemory L1DcacheMemory, factory='RubySystem::getCache(m_cfg["dcache"])';
+ CacheMemory L2cacheMemory, factory='RubySystem::getCache(m_cfg["cache"])';
Entry getCacheEntry(Address addr), return_by_ref="yes" {
if (L2cacheMemory.isTagPresent(addr)) {
@@ -284,36 +306,36 @@
// ** INSTRUCTION ACCESS ***
// Check to see if it is in the OTHER L1
- if (L1DcacheMemory.isTagPresent(in_msg.Address)) {
+ if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) {
// The block is in the wrong L1, try to write it to the L2
- if (L2cacheMemory.cacheAvail(in_msg.Address)) {
- trigger(Event:L1_to_L2, in_msg.Address);
+ if (L2cacheMemory.cacheAvail(in_msg.LineAddress)) {
+ trigger(Event:L1_to_L2, in_msg.LineAddress);
} else {
- trigger(Event:L2_Replacement,
L2cacheMemory.cacheProbe(in_msg.Address));
+ trigger(Event:L2_Replacement,
L2cacheMemory.cacheProbe(in_msg.LineAddress));
}
}
- if (L1IcacheMemory.isTagPresent(in_msg.Address)) {
+ if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) {
// 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.Address);
+ trigger(mandatory_request_type_to_event(in_msg.Type),
in_msg.LineAddress);
} else {
- if (L1IcacheMemory.cacheAvail(in_msg.Address)) {
+ 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.Address)) {
+ if (L2cacheMemory.isTagPresent(in_msg.LineAddress)) {
// L2 has it (maybe not with the right permissions)
- trigger(Event:L2_to_L1I, in_msg.Address);
+ trigger(Event:L2_to_L1I, in_msg.LineAddress);
} 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.Address);
+ trigger(mandatory_request_type_to_event(in_msg.Type),
in_msg.LineAddress);
}
} else {
// No room in the L1, so we need to make room
- if
(L2cacheMemory.cacheAvail(L1IcacheMemory.cacheProbe(in_msg.Address))) {
+ 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.Address));
+ trigger(Event:L1_to_L2,
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.Address)));
+ trigger(Event:L2_Replacement,
L2cacheMemory.cacheProbe(L1IcacheMemory.cacheProbe(in_msg.LineAddress)));
}
}
}
@@ -321,36 +343,36 @@
// *** DATA ACCESS ***
// Check to see if it is in the OTHER L1
- if (L1IcacheMemory.isTagPresent(in_msg.Address)) {
+ if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) {
// The block is in the wrong L1, try to write it to the L2
- if (L2cacheMemory.cacheAvail(in_msg.Address)) {
- trigger(Event:L1_to_L2, in_msg.Address);
+ if (L2cacheMemory.cacheAvail(in_msg.LineAddress)) {
+ trigger(Event:L1_to_L2, in_msg.LineAddress);
} else {
- trigger(Event:L2_Replacement,
L2cacheMemory.cacheProbe(in_msg.Address));
+ trigger(Event:L2_Replacement,
L2cacheMemory.cacheProbe(in_msg.LineAddress));
}
}
- if (L1DcacheMemory.isTagPresent(in_msg.Address)) {
+ if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) {
// 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.Address);
+ trigger(mandatory_request_type_to_event(in_msg.Type),
in_msg.LineAddress);
} else {
- if (L1DcacheMemory.cacheAvail(in_msg.Address)) {
+ 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.Address)) {
+ if (L2cacheMemory.isTagPresent(in_msg.LineAddress)) {
// L2 has it (maybe not with the right permissions)
- trigger(Event:L2_to_L1D, in_msg.Address);
+ trigger(Event:L2_to_L1D, in_msg.LineAddress);
} 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.Address);
+ trigger(mandatory_request_type_to_event(in_msg.Type),
in_msg.LineAddress);
}
} else {
// No room in the L1, so we need to make room
- if
(L2cacheMemory.cacheAvail(L1DcacheMemory.cacheProbe(in_msg.Address))) {
+ 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.Address));
+ trigger(Event:L1_to_L2,
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.Address)));
+ trigger(Event:L2_Replacement,
L2cacheMemory.cacheProbe(L1DcacheMemory.cacheProbe(in_msg.LineAddress)));
}
}
}
@@ -362,33 +384,33 @@
// ACTIONS
action(a_issueGETS, "a", desc="Issue GETS") {
- enqueue(requestNetwork_out, RequestMsg, latency="ISSUE_LATENCY") {
+ enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:GETS;
- out_msg.Requestor := id;
- out_msg.Destination.add(map_address_to_node(address));
+ out_msg.Requestor := machineID;
+ out_msg.Destination.add(map_Address_to_Directory(address));
out_msg.MessageSize := MessageSizeType:Request_Control;
- TBEs[address].NumPendingMsgs := numberOfNodes(); // One from each other
processor (n-1) plus the memory (+1)
+ TBEs[address].NumPendingMsgs := getNumberOfLastLevelCaches(); // 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") {
+ enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:GETX;
- out_msg.Requestor := id;
- out_msg.Destination.add(map_address_to_node(address));
+ out_msg.Requestor := machineID;
+ out_msg.Destination.add(map_Address_to_Directory(address));
out_msg.MessageSize := MessageSizeType:Request_Control;
- TBEs[address].NumPendingMsgs := numberOfNodes(); // One from each other
processor (n-1) plus the memory (+1)
+ TBEs[address].NumPendingMsgs := getNumberOfLastLevelCaches(); // 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_LATENCY") {
+ enqueue(responseNetwork_out, ResponseMsg,
latency=cache_response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
- out_msg.Sender := id;
+ out_msg.Sender := machineID;
out_msg.Destination.add(in_msg.Requestor);
out_msg.DataBlk := getCacheEntry(address).DataBlk;
out_msg.Dirty := getCacheEntry(address).Dirty;
@@ -399,21 +421,21 @@
}
action(d_issuePUT, "d", desc="Issue PUT") {
- enqueue(requestNetwork_out, RequestMsg, latency="CACHE_LATENCY") {
+ enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:PUT;
- out_msg.Requestor := id;
- out_msg.Destination.add(map_address_to_node(address));
+ out_msg.Requestor := machineID;
+ out_msg.Destination.add(map_Address_to_Directory(address));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
action(e_sendData, "e", desc="Send data from cache to requestor") {
peek(forwardToCache_in, RequestMsg) {
- enqueue(responseNetwork_out, ResponseMsg, latency="CACHE_LATENCY") {
+ enqueue(responseNetwork_out, ResponseMsg,
latency=cache_response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
- out_msg.Sender := id;
+ out_msg.Sender := machineID;
out_msg.Destination.add(in_msg.Requestor);
out_msg.DataBlk := getCacheEntry(address).DataBlk;
out_msg.Dirty := getCacheEntry(address).Dirty;
@@ -425,10 +447,10 @@
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_LATENCY") {
+ enqueue(responseNetwork_out, ResponseMsg,
latency=cache_response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_SHARED;
- out_msg.Sender := id;
+ out_msg.Sender := machineID;
out_msg.Destination.add(in_msg.Requestor);
out_msg.DataBlk := getCacheEntry(address).DataBlk;
out_msg.Dirty := getCacheEntry(address).Dirty;
@@ -440,10 +462,10 @@
action(f_sendAck, "f", desc="Send ack from cache to requestor") {
peek(forwardToCache_in, RequestMsg) {
- enqueue(responseNetwork_out, ResponseMsg, latency="CACHE_LATENCY") {
+ enqueue(responseNetwork_out, ResponseMsg,
latency=cache_response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:ACK;
- out_msg.Sender := id;
+ out_msg.Sender := machineID;
out_msg.Destination.add(in_msg.Requestor);
out_msg.Acks := 1;
out_msg.MessageSize := MessageSizeType:Response_Control;
@@ -453,10 +475,10 @@
action(ff_sendAckShared, "\f", desc="Send shared ack from cache to
requestor") {
peek(forwardToCache_in, RequestMsg) {
- enqueue(responseNetwork_out, ResponseMsg, latency="CACHE_LATENCY") {
+ enqueue(responseNetwork_out, ResponseMsg,
latency=cache_response_latency) {
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev