diff options
author | Nilay Vaish <nilay@cs.wisc.edu> | 2012-10-15 17:51:57 -0500 |
---|---|---|
committer | Nilay Vaish <nilay@cs.wisc.edu> | 2012-10-15 17:51:57 -0500 |
commit | 5ffc16593997b35f4f1abbd149e01169e6bbcff5 (patch) | |
tree | 647411a3d027f2bdfaf750f65107affb6d9c002d /src/mem/protocol | |
parent | 07ce90f7aa28a507493da905ba1881972250bb3a (diff) | |
download | gem5-5ffc16593997b35f4f1abbd149e01169e6bbcff5.tar.xz |
ruby: improved support for functional accesses
This patch adds support to different entities in the ruby memory system
for more reliable functional read/write accesses. Only the simple network
has been augmented as of now. Later on Garnet will also support functional
accesses.
The patch adds functional access code to all the different types of messages
that protocols can send around. These messages are functionally accessed
by going through the buffers maintained by the network entities.
The patch also rectifies some of the bugs found in coherence protocols while
testing the patch.
With this patch applied, functional writes always succeed. But functional
reads can still fail.
Diffstat (limited to 'src/mem/protocol')
20 files changed, 335 insertions, 46 deletions
diff --git a/src/mem/protocol/MESI_CMP_directory-L1cache.sm b/src/mem/protocol/MESI_CMP_directory-L1cache.sm index d54f7e71c..eb8e62d30 100644 --- a/src/mem/protocol/MESI_CMP_directory-L1cache.sm +++ b/src/mem/protocol/MESI_CMP_directory-L1cache.sm @@ -201,6 +201,11 @@ machine(L1Cache, "MESI Directory L1 Cache CMP") } DataBlock getDataBlock(Address addr), return_by_ref="yes" { + TBE tbe := L1_TBEs[addr]; + if(is_valid(tbe)) { + return tbe.DataBlk; + } + return getCacheEntry(addr).DataBlk; } diff --git a/src/mem/protocol/MESI_CMP_directory-L2cache.sm b/src/mem/protocol/MESI_CMP_directory-L2cache.sm index 88053aeb8..fbdc10ac2 100644 --- a/src/mem/protocol/MESI_CMP_directory-L2cache.sm +++ b/src/mem/protocol/MESI_CMP_directory-L2cache.sm @@ -232,6 +232,11 @@ machine(L2Cache, "MESI Directory L2 Cache CMP") } DataBlock getDataBlock(Address addr), return_by_ref="yes" { + TBE tbe := L2_TBEs[addr]; + if(is_valid(tbe)) { + return tbe.DataBlk; + } + return getCacheEntry(addr).DataBlk; } diff --git a/src/mem/protocol/MESI_CMP_directory-dir.sm b/src/mem/protocol/MESI_CMP_directory-dir.sm index 7e1280337..d98326b34 100644 --- a/src/mem/protocol/MESI_CMP_directory-dir.sm +++ b/src/mem/protocol/MESI_CMP_directory-dir.sm @@ -110,7 +110,7 @@ machine(Directory, "MESI_CMP_filter_directory protocol") void set_tbe(TBE tbe); void unset_tbe(); void wakeUpBuffers(Address a); - + Entry getDirectoryEntry(Address addr), return_by_pointer="yes" { Entry dir_entry := static_cast(Entry, "pointer", directory[addr]); @@ -170,6 +170,11 @@ machine(Directory, "MESI_CMP_filter_directory protocol") } DataBlock getDataBlock(Address addr), return_by_ref="yes" { + TBE tbe := TBEs[addr]; + if(is_valid(tbe)) { + return tbe.DataBlk; + } + return getDirectoryEntry(addr).DataBlk; } diff --git a/src/mem/protocol/MESI_CMP_directory-msg.sm b/src/mem/protocol/MESI_CMP_directory-msg.sm index 67619f075..473012c61 100644 --- a/src/mem/protocol/MESI_CMP_directory-msg.sm +++ b/src/mem/protocol/MESI_CMP_directory-msg.sm @@ -35,11 +35,9 @@ enumeration(CoherenceRequestType, desc="...") { GETS, desc="Get Shared"; GET_INSTR, desc="Get Instruction"; INV, desc="INValidate"; - PUTX, desc="replacement message"; + PUTX, desc="Replacement message"; WB_ACK, desc="Writeback ack"; - WB_NACK, desc="Writeback neg. ack"; - FWD, desc="Generic FWD"; DMA_READ, desc="DMA Read"; DMA_WRITE, desc="DMA Write"; @@ -47,14 +45,14 @@ enumeration(CoherenceRequestType, desc="...") { // CoherenceResponseType enumeration(CoherenceResponseType, desc="...") { - MEMORY_ACK, desc="Ack from memory controller"; - DATA, desc="Data"; - DATA_EXCLUSIVE, desc="Data"; - MEMORY_DATA, desc="Data"; - ACK, desc="Generic invalidate ack"; - WB_ACK, desc="writeback ack"; - UNBLOCK, desc="unblock"; - EXCLUSIVE_UNBLOCK, desc="exclusive unblock"; + MEMORY_ACK, desc="Ack from memory controller"; + DATA, desc="Data block for L1 cache in S state"; + DATA_EXCLUSIVE, desc="Data block for L1 cache in M/E state"; + MEMORY_DATA, desc="Data block from / to main memory"; + ACK, desc="Generic invalidate ack"; + WB_ACK, desc="writeback ack"; + UNBLOCK, desc="unblock"; + EXCLUSIVE_UNBLOCK, desc="exclusive unblock"; INV, desc="Invalidate from directory"; } @@ -70,6 +68,21 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") { int Len; bool Dirty, default="false", desc="Dirty bit"; PrefetchBit Prefetch, desc="Is this a prefetch request"; + + bool functionalRead(Packet *pkt) { + // Only PUTX messages contains the data block + if (Type == CoherenceRequestType:PUTX) { + return testAndRead(Address, DataBlk, pkt); + } + + return false; + } + + bool functionalWrite(Packet *pkt) { + // No check on message type required since the protocol should + // read data from those messages that contain the block + return testAndWrite(Address, DataBlk, pkt); + } } // ResponseMsg @@ -82,4 +95,22 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") { bool Dirty, default="false", desc="Dirty bit"; int AckCount, default="0", desc="number of acks in this message"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + // Valid data block is only present in message with following types + if (Type == CoherenceResponseType:DATA || + Type == CoherenceResponseType:DATA_EXCLUSIVE || + Type == CoherenceResponseType:MEMORY_DATA) { + + return testAndRead(Address, DataBlk, pkt); + } + + return false; + } + + bool functionalWrite(Packet *pkt) { + // No check on message type required since the protocol should + // read data from those messages that contain the block + return testAndWrite(Address, DataBlk, pkt); + } } diff --git a/src/mem/protocol/MI_example-cache.sm b/src/mem/protocol/MI_example-cache.sm index cf5cf9505..5040eb85d 100644 --- a/src/mem/protocol/MI_example-cache.sm +++ b/src/mem/protocol/MI_example-cache.sm @@ -168,6 +168,11 @@ machine(L1Cache, "MI Example L1 Cache") } DataBlock getDataBlock(Address addr), return_by_ref="yes" { + TBE tbe := TBEs[addr]; + if(is_valid(tbe)) { + return tbe.DataBlk; + } + return getCacheEntry(addr).DataBlk; } diff --git a/src/mem/protocol/MI_example-dir.sm b/src/mem/protocol/MI_example-dir.sm index 241ad3b30..f15ccb14e 100644 --- a/src/mem/protocol/MI_example-dir.sm +++ b/src/mem/protocol/MI_example-dir.sm @@ -172,6 +172,11 @@ machine(Directory, "Directory protocol") } DataBlock getDataBlock(Address addr), return_by_ref="yes" { + TBE tbe := TBEs[addr]; + if(is_valid(tbe)) { + return tbe.DataBlk; + } + return getDirectoryEntry(addr).DataBlk; } @@ -506,7 +511,6 @@ machine(Directory, "Directory protocol") out_msg.OriginalRequestorMachId := in_msg.Requestor; out_msg.DataBlk := in_msg.DataBlk; out_msg.MessageSize := in_msg.MessageSize; - //out_msg.Prefetch := in_msg.Prefetch; DPRINTF(RubySlicc,"%s\n", out_msg); } @@ -518,12 +522,8 @@ machine(Directory, "Directory protocol") } action(w_writeDataToMemoryFromTBE, "\w", desc="Write date to directory memory from TBE") { - //getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk; assert(is_valid(tbe)); - getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, - addressOffset(tbe.PhysicalAddress), - tbe.Len); - + getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk; } // TRANSITIONS @@ -633,7 +633,6 @@ machine(Directory, "Directory protocol") } transition(M, PUTX, MI) { - l_writeDataToMemory; c_clearOwner; v_allocateTBEFromRequestNet; l_queueMemoryWBRequest; diff --git a/src/mem/protocol/MI_example-msg.sm b/src/mem/protocol/MI_example-msg.sm index 2fb1c48ba..0645371f6 100644 --- a/src/mem/protocol/MI_example-msg.sm +++ b/src/mem/protocol/MI_example-msg.sm @@ -31,11 +31,9 @@ enumeration(CoherenceRequestType, desc="...") { GETX, desc="Get eXclusive"; GETS, desc="Get Shared"; PUTX, desc="Put eXclusive"; - PUTO, desc="Put Owned"; WB_ACK, desc="Writeback ack"; WB_NACK, desc="Writeback neg. ack"; INV, desc="Invalidation"; - FWD, desc="Generic FWD"; } // CoherenceResponseType @@ -59,6 +57,20 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") { NetDest Destination, desc="Multicast destination mask"; DataBlock DataBlk, desc="data for the cache line"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + // Valid data block is only present in PUTX messages + if (Type == CoherenceRequestType:PUTX) { + return testAndRead(Address, DataBlk, pkt); + } + return false; + } + + bool functionalWrite(Packet *pkt) { + // No check on message type required since the protocol should read + // data block from only those messages that contain valid data + return testAndWrite(Address, DataBlk, pkt); + } } // ResponseMsg (and also unblock requests) @@ -70,6 +82,18 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") { DataBlock DataBlk, desc="data for the cache line"; bool Dirty, desc="Is the data dirty (different than memory)?"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + // A check on message type should appear here so that only those + // messages that contain data + return testAndRead(Address, DataBlk, pkt); + } + + bool functionalWrite(Packet *pkt) { + // No check on message type required since the protocol should read + // data block from only those messages that contain valid data + return testAndWrite(Address, DataBlk, pkt); + } } enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") { @@ -93,6 +117,14 @@ structure(DMARequestMsg, desc="...", interface="NetworkMessage") { DataBlock DataBlk, desc="DataBlk attached to this request"; int Len, desc="The length of the request"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + return testAndRead(LineAddress, DataBlk, pkt); + } + + bool functionalWrite(Packet *pkt) { + return testAndWrite(LineAddress, DataBlk, pkt); + } } structure(DMAResponseMsg, desc="...", interface="NetworkMessage") { @@ -102,4 +134,12 @@ structure(DMAResponseMsg, desc="...", interface="NetworkMessage") { NetDest Destination, desc="Destination"; DataBlock DataBlk, desc="DataBlk attached to this request"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + return testAndRead(LineAddress, DataBlk, pkt); + } + + bool functionalWrite(Packet *pkt) { + return testAndWrite(LineAddress, DataBlk, pkt); + } } diff --git a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm index 43c2def2e..6295f90fd 100644 --- a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm +++ b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm @@ -219,7 +219,17 @@ machine(L1Cache, "Directory protocol") } DataBlock getDataBlock(Address addr), return_by_ref="yes" { - return getCacheEntry(addr).DataBlk; + Entry cache_entry := getCacheEntry(addr); + if(is_valid(cache_entry)) { + return cache_entry.DataBlk; + } + + TBE tbe := TBEs[addr]; + if(is_valid(tbe)) { + return tbe.DataBlk; + } + + error("Data block missing!"); } Event mandatory_request_type_to_event(RubyRequestType type) { diff --git a/src/mem/protocol/MOESI_CMP_directory-L2cache.sm b/src/mem/protocol/MOESI_CMP_directory-L2cache.sm index 6238953ad..2e4e66a7b 100644 --- a/src/mem/protocol/MOESI_CMP_directory-L2cache.sm +++ b/src/mem/protocol/MOESI_CMP_directory-L2cache.sm @@ -193,7 +193,7 @@ machine(L2Cache, "Token protocol") // TBE fields structure(TBE, desc="...") { - Address Address, desc="Physical address for this TBE"; + Address address, desc="Physical address for this TBE"; State TBEState, desc="Transient state"; Address PC, desc="Program counter of request"; DataBlock DataBlk, desc="Buffer for the data block"; @@ -512,11 +512,6 @@ machine(L2Cache, "Token protocol") return L2Cache_State_to_permission(cache_entry.CacheState); } - else if (localDirectory.isTagPresent(addr)) { - DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(localDirectory[addr].DirState)); - return L2Cache_State_to_permission(localDirectory[addr].DirState); - } - DPRINTF(RubySlicc, "AccessPermission_NotPresent\n"); return AccessPermission:NotPresent; } @@ -528,6 +523,11 @@ machine(L2Cache, "Token protocol") } DataBlock getDataBlock(Address addr), return_by_ref="yes" { + TBE tbe := TBEs[addr]; + if(is_valid(tbe)) { + return tbe.DataBlk; + } + return getCacheEntry(addr).DataBlk; } @@ -1451,6 +1451,8 @@ machine(L2Cache, "Token protocol") peek(responseNetwork_in, ResponseMsg) { assert(is_valid(cache_entry)); cache_entry.DataBlk := in_msg.DataBlk; + DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", + address, cache_entry.DataBlk); if ((cache_entry.Dirty == false) && in_msg.Dirty) { cache_entry.Dirty := in_msg.Dirty; } diff --git a/src/mem/protocol/MOESI_CMP_directory-dir.sm b/src/mem/protocol/MOESI_CMP_directory-dir.sm index 1635267f6..0dd4239a9 100644 --- a/src/mem/protocol/MOESI_CMP_directory-dir.sm +++ b/src/mem/protocol/MOESI_CMP_directory-dir.sm @@ -473,6 +473,9 @@ machine(Directory, "Directory protocol") // implementation. We include the data in the "dataless" // message so we can assert the clean data matches the datablock // in memory + DPRINTF(RubySlicc, "Address: %s, MsgDataBlock: %s MemoryDataBlock: %s\n", + in_msg.Address, in_msg.DataBlk, + getDirectoryEntry(in_msg.Address).DataBlk); assert(getDirectoryEntry(in_msg.Address).DataBlk == in_msg.DataBlk); } } diff --git a/src/mem/protocol/MOESI_CMP_directory-msg.sm b/src/mem/protocol/MOESI_CMP_directory-msg.sm index 7b203537f..e428be7f7 100644 --- a/src/mem/protocol/MOESI_CMP_directory-msg.sm +++ b/src/mem/protocol/MOESI_CMP_directory-msg.sm @@ -71,6 +71,16 @@ enumeration(TriggerType, desc="...") { structure(TriggerMsg, desc="...", interface="Message") { Address Address, desc="Physical address for this request"; TriggerType Type, desc="Type of trigger"; + + bool functionalRead(Packet *pkt) { + // Trigger message does not hold data + return false; + } + + bool functionalWrite(Packet *pkt) { + // Trigger message does not hold data + return false; + } } // RequestMsg (and also forwarded requests) @@ -86,6 +96,20 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") { MessageSizeType MessageSize, desc="size category of the message"; RubyAccessMode AccessMode, desc="user/supervisor access type"; PrefetchBit Prefetch, desc="Is this a prefetch request"; + + bool functionalRead(Packet *pkt) { + // Read only those messages that contain the data + if (Type == CoherenceRequestType:DMA_READ || + Type == CoherenceRequestType:DMA_WRITE) { + return testAndRead(Address, DataBlk, pkt); + } + return false; + } + + bool functionalWrite(Packet *pkt) { + // No check required since all messages are written + return testAndWrite(Address, DataBlk, pkt); + } } // ResponseMsg (and also unblock requests) @@ -99,4 +123,20 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") { bool Dirty, desc="Is the data dirty (different than memory)?"; int Acks, desc="How many acks to expect"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + // Read only those messages that contain the data + if (Type == CoherenceResponseType:DATA || + Type == CoherenceResponseType:DATA_EXCLUSIVE || + Type == CoherenceResponseType:WRITEBACK_CLEAN_DATA || + Type == CoherenceResponseType:WRITEBACK_DIRTY_DATA) { + return testAndRead(Address, DataBlk, pkt); + } + return false; + } + + bool functionalWrite(Packet *pkt) { + // No check required since all messages are written + return testAndWrite(Address, DataBlk, pkt); + } } diff --git a/src/mem/protocol/MOESI_CMP_token-L1cache.sm b/src/mem/protocol/MOESI_CMP_token-L1cache.sm index b6de5a714..8cf40974e 100644 --- a/src/mem/protocol/MOESI_CMP_token-L1cache.sm +++ b/src/mem/protocol/MOESI_CMP_token-L1cache.sm @@ -139,7 +139,7 @@ machine(L1Cache, "Token protocol") // TBE fields structure(TBE, desc="...") { - Address Address, desc="Physical address for this TBE"; + Address address, desc="Physical address for this TBE"; State TBEState, desc="Transient state"; int IssueCount, default="0", desc="The number of times we've issued a request for this line."; Address PC, desc="Program counter of request"; diff --git a/src/mem/protocol/MOESI_CMP_token-dir.sm b/src/mem/protocol/MOESI_CMP_token-dir.sm index 8d78be40c..fd51e2924 100644 --- a/src/mem/protocol/MOESI_CMP_token-dir.sm +++ b/src/mem/protocol/MOESI_CMP_token-dir.sm @@ -677,6 +677,7 @@ machine(Directory, "Token protocol") enqueue(memQueue_out, MemoryMsg, latency="1") { out_msg.Address := address; out_msg.Type := MemoryRequestType:MEMORY_WB; + out_msg.DataBlk := getDirectoryEntry(address).DataBlk; DPRINTF(RubySlicc, "%s\n", out_msg); } } diff --git a/src/mem/protocol/MOESI_CMP_token-msg.sm b/src/mem/protocol/MOESI_CMP_token-msg.sm index b1c3f4580..6a8d6c6bc 100644 --- a/src/mem/protocol/MOESI_CMP_token-msg.sm +++ b/src/mem/protocol/MOESI_CMP_token-msg.sm @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood * All rights reserved. @@ -66,6 +65,16 @@ structure(PersistentMsg, desc="...", interface="NetworkMessage") { MessageSizeType MessageSize, desc="size category of the message"; RubyAccessMode AccessMode, desc="user/supervisor access type"; PrefetchBit Prefetch, desc="Is this a prefetch request"; + + bool functionalRead(Packet *pkt) { + // No data in persistent messages + return false; + } + + bool functionalWrite(Packet *pkt) { + // No data in persistent messages + return false; + } } // RequestMsg @@ -79,6 +88,16 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") { MessageSizeType MessageSize, desc="size category of the message"; RubyAccessMode AccessMode, desc="user/supervisor access type"; PrefetchBit Prefetch, desc="Is this a prefetch request"; + + bool functionalRead(Packet *pkt) { + // No data in request messages + return false; + } + + bool functionalWrite(Packet *pkt) { + // No data in request messages + return false; + } } // ResponseMsg @@ -91,6 +110,16 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") { DataBlock DataBlk, desc="data for the cache line"; bool Dirty, desc="Is the data dirty (different than memory)?"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + // No check being carried out on the message type. Would be added later. + return testAndRead(Address, DataBlk, pkt); + } + + bool functionalWrite(Packet *pkt) { + // No check required since all messages are written. + return testAndWrite(Address, DataBlk, pkt); + } } enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") { @@ -114,6 +143,14 @@ structure(DMARequestMsg, desc="...", interface="NetworkMessage") { DataBlock DataBlk, desc="DataBlk attached to this request"; int Len, desc="The length of the request"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + return false; + } + + bool functionalWrite(Packet *pkt) { + return testAndWrite(LineAddress, DataBlk, pkt); + } } structure(DMAResponseMsg, desc="...", interface="NetworkMessage") { @@ -123,4 +160,12 @@ structure(DMAResponseMsg, desc="...", interface="NetworkMessage") { NetDest Destination, desc="Destination"; DataBlock DataBlk, desc="DataBlk attached to this request"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + return false; + } + + bool functionalWrite(Packet *pkt) { + return testAndWrite(LineAddress, DataBlk, pkt); + } } diff --git a/src/mem/protocol/MOESI_hammer-cache.sm b/src/mem/protocol/MOESI_hammer-cache.sm index 6eb0974b0..a3fa1219f 100644 --- a/src/mem/protocol/MOESI_hammer-cache.sm +++ b/src/mem/protocol/MOESI_hammer-cache.sm @@ -198,7 +198,17 @@ machine(L1Cache, "AMD Hammer-like protocol") } DataBlock getDataBlock(Address addr), return_by_ref="yes" { - return getCacheEntry(addr).DataBlk; + Entry cache_entry := getCacheEntry(addr); + if(is_valid(cache_entry)) { + return cache_entry.DataBlk; + } + + TBE tbe := TBEs[addr]; + if(is_valid(tbe)) { + return tbe.DataBlk; + } + + error("Missing data block"); } Entry getL2CacheEntry(Address address), return_by_pointer="yes" { @@ -879,6 +889,7 @@ machine(L1Cache, "AMD Hammer-like protocol") tbe.ForwardRequestTime, tbe.FirstResponseTime); } + DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); cache_entry.Dirty := true; } diff --git a/src/mem/protocol/MOESI_hammer-dir.sm b/src/mem/protocol/MOESI_hammer-dir.sm index ed1fb7669..22ca568a8 100644 --- a/src/mem/protocol/MOESI_hammer-dir.sm +++ b/src/mem/protocol/MOESI_hammer-dir.sm @@ -87,7 +87,7 @@ machine(Directory, "AMD Hammer-like protocol") O_DR_B, AccessPermission:Busy, desc="Owner, Dma Read waiting for cache responses"; WB, AccessPermission:Busy, desc="Blocked on a writeback"; WB_O_W, AccessPermission:Busy, desc="Blocked on memory write, will go to O"; - WB_E_W, AccessPermission:Read_Write, desc="Blocked on memory write, will go to E"; + WB_E_W, AccessPermission:Busy, desc="Blocked on memory write, will go to E"; NO_F, AccessPermission:Busy, desc="Blocked on a flush"; NO_F_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram"; @@ -199,7 +199,17 @@ machine(Directory, "AMD Hammer-like protocol") } DataBlock getDataBlock(Address addr), return_by_ref="yes" { - return getDirectoryEntry(addr).DataBlk; + Entry dir_entry := getDirectoryEntry(addr); + if(is_valid(dir_entry)) { + return dir_entry.DataBlk; + } + + TBE tbe := TBEs[addr]; + if(is_valid(tbe)) { + return tbe.DataBlk; + } + + error("Data block missing!"); } PfEntry getProbeFilterEntry(Address addr), return_by_pointer="yes" { @@ -222,7 +232,7 @@ machine(Directory, "AMD Hammer-like protocol") return getDirectoryEntry(addr).DirectoryState; } } - + void setState(TBE tbe, PfEntry pf_entry, Address addr, State state) { if (is_valid(tbe)) { tbe.TBEState := state; @@ -1168,9 +1178,7 @@ machine(Directory, "AMD Hammer-like protocol") } action(l_writeDataToMemory, "l", desc="Write PUTX/PUTO data to memory") { - peek(unblockNetwork_in, ResponseMsg) { - assert(in_msg.Dirty); - assert(in_msg.MessageSize == MessageSizeType:Writeback_Data); + peek(memQueue_in, MemoryMsg) { getDirectoryEntry(address).DataBlk := in_msg.DataBlk; DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n", in_msg.Address, in_msg.DataBlk); @@ -1236,8 +1244,11 @@ machine(Directory, "AMD Hammer-like protocol") action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") { peek(unblockNetwork_in, ResponseMsg) { enqueue(memQueue_out, MemoryMsg, latency="1") { + assert(in_msg.Dirty); + assert(in_msg.MessageSize == MessageSizeType:Writeback_Data); out_msg.Address := address; out_msg.Type := MemoryRequestType:MEMORY_WB; + out_msg.DataBlk := in_msg.DataBlk; DPRINTF(RubySlicc, "%s\n", out_msg); } } @@ -1854,26 +1865,26 @@ machine(Directory, "AMD Hammer-like protocol") // WB State Transistions transition(WB, Writeback_Dirty, WB_O_W) { - l_writeDataToMemory; rs_removeSharer; l_queueMemoryWBRequest; j_popIncomingUnblockQueue; } transition(WB, Writeback_Exclusive_Dirty, WB_E_W) { - l_writeDataToMemory; rs_removeSharer; l_queueMemoryWBRequest; j_popIncomingUnblockQueue; } transition(WB_E_W, Memory_Ack, E) { + l_writeDataToMemory; pfd_probeFilterDeallocate; k_wakeUpDependents; l_popMemQueue; } transition(WB_O_W, Memory_Ack, O) { + l_writeDataToMemory; k_wakeUpDependents; l_popMemQueue; } diff --git a/src/mem/protocol/MOESI_hammer-msg.sm b/src/mem/protocol/MOESI_hammer-msg.sm index 6ead7200a..41d176a9c 100644 --- a/src/mem/protocol/MOESI_hammer-msg.sm +++ b/src/mem/protocol/MOESI_hammer-msg.sm @@ -73,6 +73,16 @@ enumeration(TriggerType, desc="...") { structure(TriggerMsg, desc="...", interface="Message") { Address Address, desc="Physical address for this request"; TriggerType Type, desc="Type of trigger"; + + bool functionalRead(Packet *pkt) { + // Trigger messages do not hold any data! + return false; + } + + bool functionalWrite(Packet *pkt) { + // Trigger messages do not hold any data! + return false; + } } // RequestMsg (and also forwarded requests) @@ -87,6 +97,16 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") { Time InitialRequestTime, default="0", desc="time the initial requests was sent from the L1Cache"; Time ForwardRequestTime, default="0", desc="time the dir forwarded the request"; int SilentAcks, default="0", desc="silent acks from the full-bit directory"; + + bool functionalRead(Packet *pkt) { + // Request messages do not hold any data + return false; + } + + bool functionalWrite(Packet *pkt) { + // Request messages do not hold any data + return false; + } } // ResponseMsg (and also unblock requests) @@ -103,6 +123,27 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") { Time InitialRequestTime, default="0", desc="time the initial requests was sent from the L1Cache"; Time ForwardRequestTime, default="0", desc="time the dir forwarded the request"; int SilentAcks, default="0", desc="silent acks from the full-bit directory"; + + bool functionalRead(Packet *pkt) { + // The check below ensures that data is read only from messages that + // actually hold data. + if (Type == CoherenceResponseType:DATA || + Type == CoherenceResponseType:DATA_SHARED || + Type == CoherenceResponseType:DATA_EXCLUSIVE || + Type == CoherenceResponseType:WB_DIRTY || + Type == CoherenceResponseType:WB_EXCLUSIVE_DIRTY) { + return testAndRead(Address, DataBlk, pkt); + } + + return false; + } + + bool functionalWrite(Packet *pkt) { + // Message type does not matter since all messages are written. + // If a protocol reads data from a packet that is not supposed + // to hold the data, then the fault lies with the protocol. + return testAndWrite(Address, DataBlk, pkt); + } } enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") { @@ -126,6 +167,14 @@ structure(DMARequestMsg, desc="...", interface="NetworkMessage") { DataBlock DataBlk, desc="DataBlk attached to this request"; int Len, desc="The length of the request"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + return testAndRead(LineAddress, DataBlk, pkt); + } + + bool functionalWrite(Packet *pkt) { + return testAndWrite(LineAddress, DataBlk, pkt); + } } structure(DMAResponseMsg, desc="...", interface="NetworkMessage") { @@ -135,4 +184,12 @@ structure(DMAResponseMsg, desc="...", interface="NetworkMessage") { NetDest Destination, desc="Destination"; DataBlock DataBlk, desc="DataBlk attached to this request"; MessageSizeType MessageSize, desc="size category of the message"; + + bool functionalRead(Packet *pkt) { + return testAndRead(LineAddress, DataBlk, pkt); + } + + bool functionalWrite(Packet *pkt) { + return testAndWrite(LineAddress, DataBlk, pkt); + } } diff --git a/src/mem/protocol/Network_test-msg.sm b/src/mem/protocol/Network_test-msg.sm index 6492024d8..9e21d39bb 100644 --- a/src/mem/protocol/Network_test-msg.sm +++ b/src/mem/protocol/Network_test-msg.sm @@ -40,4 +40,8 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") { NetDest Destination, desc="Multicast destination mask"; DataBlock DataBlk, desc="data for the cache line"; MessageSizeType MessageSize, desc="size category of the message"; + + void functionalWrite(Packet *pkt) { + error("Network test does not support functional accesses!"); + } } diff --git a/src/mem/protocol/RubySlicc_Exports.sm b/src/mem/protocol/RubySlicc_Exports.sm index b42f9c3a9..2a4281757 100644 --- a/src/mem/protocol/RubySlicc_Exports.sm +++ b/src/mem/protocol/RubySlicc_Exports.sm @@ -27,24 +27,23 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * $Id$ - * - */ - -// defines +// Declarations of external types that are common to all protocols external_type(int, primitive="yes", default="0"); external_type(bool, primitive="yes", default="false"); external_type(std::string, primitive="yes"); external_type(uint64, primitive="yes"); external_type(Time, primitive="yes", default="0"); +external_type(PacketPtr, primitive="yes"); +external_type(Packet, primitive="yes"); external_type(Address); + structure(DataBlock, external = "yes", desc="..."){ void clear(); void copyPartial(DataBlock, int, int); } -// Declarations of external types that are common to all protocols +bool testAndRead(Address addr, DataBlock datablk, Packet *pkt); +bool testAndWrite(Address addr, DataBlock datablk, Packet *pkt); // AccessPermission // The following five states define the access permission of all memory blocks. @@ -265,6 +264,14 @@ structure(SequencerMsg, desc="...", interface="Message") { DataBlock DataBlk, desc="Data"; int Len, desc="size in bytes of access"; PrefetchBit Prefetch, desc="Is this a prefetch request"; + + bool functionalRead(Packet *pkt) { + return testAndRead(PhysicalAddress, DataBlk, pkt); + } + + bool functionalWrite(Packet *pkt) { + return testAndWrite(PhysicalAddress, DataBlk, pkt); + } } // MaskPredictorType diff --git a/src/mem/protocol/RubySlicc_MemControl.sm b/src/mem/protocol/RubySlicc_MemControl.sm index 66bb37bca..08bff6e36 100644 --- a/src/mem/protocol/RubySlicc_MemControl.sm +++ b/src/mem/protocol/RubySlicc_MemControl.sm @@ -61,4 +61,12 @@ structure(MemoryMsg, desc="...", interface="Message") { PrefetchBit Prefetch, desc="Is this a prefetch request"; bool ReadX, desc="Exclusive"; int Acks, desc="How many acks to expect"; + + bool functionalRead(Packet *pkt) { + return testAndRead(Address, DataBlk, pkt); + } + + bool functionalWrite(Packet *pkt) { + return testAndWrite(Address, DataBlk, pkt); + } } |