diff options
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); + } } |