changeset 14c356da6ed3 in /z/repo/m5
details: http://repo.m5sim.org/m5?cmd=changeset;node=14c356da6ed3
description:
ruby: MOESI hammer support for DMA reads and writes
diffstat:
5 files changed, 657 insertions(+), 62 deletions(-)
src/mem/protocol/MOESI_hammer-dir.sm | 517 +++++++++++++++++++++++++++++-----
src/mem/protocol/MOESI_hammer-dma.sm | 165 ++++++++++
src/mem/protocol/MOESI_hammer-msg.sm | 32 ++
src/mem/protocol/MOESI_hammer.slicc | 1
src/mem/ruby/config/defaults.rb | 4
diffs (truncated from 940 to 300 lines):
diff -r 53caf4b9186d -r 14c356da6ed3 src/mem/protocol/MOESI_hammer-dir.sm
--- a/src/mem/protocol/MOESI_hammer-dir.sm Wed Nov 18 16:34:32 2009 -0800
+++ b/src/mem/protocol/MOESI_hammer-dir.sm Wed Nov 18 16:34:32 2009 -0800
@@ -39,11 +39,17 @@
MessageBuffer forwardFromDir, network="To", virtual_network="2",
ordered="false";
MessageBuffer responseFromDir, network="To", virtual_network="1",
ordered="false";
- //MessageBuffer dmaRequestFromDir, network="To", virtual_network="4",
ordered="true";
+ //
+ // For a finite buffered network, note that the DMA response network only
+ // works at this relatively higher numbered (lower priority) virtual network
+ // because the trigger queue decouples cache responses from DMA responses.
+ //
+ MessageBuffer dmaResponseFromDir, network="To", virtual_network="4",
ordered="true";
+ MessageBuffer unblockToDir, network="From", virtual_network="0",
ordered="false";
+ MessageBuffer responseToDir, network="From", virtual_network="1",
ordered="false";
MessageBuffer requestToDir, network="From", virtual_network="3",
ordered="false";
- MessageBuffer unblockToDir, network="From", virtual_network="0",
ordered="false";
- //MessageBuffer dmaRequestToDir, network="From", virtual_network="5",
ordered="true";
+ MessageBuffer dmaRequestToDir, network="From", virtual_network="5",
ordered="true";
// STATES
enumeration(State, desc="Directory states", default="Directory_State_E") {
@@ -57,6 +63,13 @@
O_B_W, desc="Owner, Blocked, waiting for Dram";
NO_W, desc="Not Owner, waiting for Dram";
O_W, desc="Owner, waiting for Dram";
+ NO_DW_B_W, desc="Not Owner, Dma Write waiting for Dram and cache
responses";
+ NO_DR_B_W, desc="Not Owner, Dma Read waiting for Dram and cache
responses";
+ NO_DR_B_D, desc="Not Owner, Dma Read waiting for cache responses
including dirty data";
+ NO_DR_B, desc="Not Owner, Dma Read waiting for cache responses";
+ NO_DW_W, desc="Not Owner, Dma Write waiting for Dram";
+ O_DR_B_W, desc="Owner, Dma Read waiting for Dram and cache
responses";
+ O_DR_B, desc="Owner, Dma Read waiting for cache responses";
WB, desc="Blocked on a writeback";
WB_O_W, desc="Blocked on memory write, will go to O";
WB_E_W, desc="Blocked on memory write, will go to E";
@@ -73,9 +86,23 @@
Writeback_Exclusive_Clean, desc="The final part of a PutX (no data,
exclusive)";
Writeback_Exclusive_Dirty, desc="The final part of a PutX (data,
exclusive)";
+ // DMA requests
+ DMA_READ, desc="A DMA Read memory request";
+ DMA_WRITE, desc="A DMA Write memory request";
+
// Memory Controller
Memory_Data, desc="Fetched data from memory arrives";
Memory_Ack, desc="Writeback Ack from memory arrives";
+
+ // Cache responses required to handle DMA
+ Ack, desc="Received an ack message";
+ Shared_Ack, desc="Received an ack message, responder has a shared
copy";
+ Shared_Data, desc="Received a data message, responder has a shared
copy";
+ Exclusive_Data, desc="Received a data message, responder had an exclusive
copy, they gave it to us";
+
+ // Triggers
+ All_acks_and_data, desc="Received all required data and message
acks";
+ All_acks_and_data_no_sharers, desc="Received all acks and no other
processor has a shared copy";
}
// TYPES
@@ -100,9 +127,13 @@
Address PhysicalAddress, desc="physical address";
State TBEState, desc="Transient State";
CoherenceResponseType ResponseType, desc="The type for the subsequent
response message";
- DataBlock DataBlk, desc="Data to be written (DMA write only)";
+ DataBlock DmaDataBlk, desc="DMA Data to be written. Partial blocks need
to merged with system memory";
+ DataBlock DataBlk, desc="The current view of system memory";
int Len, desc="...";
MachineID DmaRequestor, desc="DMA requestor";
+ int NumPendingMsgs, desc="Number of pending acks/messages";
+ bool CacheDirty, desc="Indicates whether a cache has responded with
dirty data";
+ bool Sharers, desc="Indicates whether a cache has indicated it is
currently a sharer";
}
external_type(TBETable) {
@@ -135,10 +166,14 @@
directory[addr].DirectoryState := state;
}
+ MessageBuffer triggerQueue, ordered="true";
+
// ** OUT_PORTS **
+ out_port(requestQueue_out, ResponseMsg, requestToDir); // For recycling
requests
out_port(forwardNetwork_out, RequestMsg, forwardFromDir);
out_port(responseNetwork_out, ResponseMsg, responseFromDir);
- out_port(requestQueue_out, ResponseMsg, requestToDir); // For recycling
requests
+ out_port(dmaResponseNetwork_out, DMAResponseMsg, dmaResponseFromDir);
+ out_port(triggerQueue_out, TriggerMsg, triggerQueue);
//
// Memory buffer for memory controller to DIMM communication
@@ -147,6 +182,21 @@
// ** IN_PORTS **
+ // Trigger Queue
+ in_port(triggerQueue_in, TriggerMsg, triggerQueue) {
+ if (triggerQueue_in.isReady()) {
+ peek(triggerQueue_in, TriggerMsg) {
+ if (in_msg.Type == TriggerType:ALL_ACKS) {
+ trigger(Event:All_acks_and_data, in_msg.Address);
+ } else if (in_msg.Type == TriggerType:ALL_ACKS_NO_SHARERS) {
+ trigger(Event:All_acks_and_data_no_sharers, in_msg.Address);
+ } else {
+ error("Unexpected message");
+ }
+ }
+ }
+ }
+
in_port(unblockNetwork_in, ResponseMsg, unblockToDir) {
if (unblockNetwork_in.isReady()) {
peek(unblockNetwork_in, ResponseMsg) {
@@ -167,6 +217,39 @@
}
}
+ // Response Network
+ in_port(responseToDir_in, ResponseMsg, responseToDir) {
+ if (responseToDir_in.isReady()) {
+ peek(responseToDir_in, ResponseMsg) {
+ if (in_msg.Type == CoherenceResponseType:ACK) {
+ trigger(Event:Ack, in_msg.Address);
+ } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) {
+ trigger(Event:Shared_Ack, in_msg.Address);
+ } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) {
+ trigger(Event:Shared_Data, in_msg.Address);
+ } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
+ trigger(Event:Exclusive_Data, in_msg.Address);
+ } else {
+ error("Unexpected message");
+ }
+ }
+ }
+ }
+
+ in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir) {
+ if (dmaRequestQueue_in.isReady()) {
+ peek(dmaRequestQueue_in, DMARequestMsg) {
+ if (in_msg.Type == DMARequestType:READ) {
+ trigger(Event:DMA_READ, in_msg.LineAddress);
+ } else if (in_msg.Type == DMARequestType:WRITE) {
+ trigger(Event:DMA_WRITE, in_msg.LineAddress);
+ } else {
+ error("Invalid message");
+ }
+ }
+ }
+ }
+
in_port(requestQueue_in, RequestMsg, requestToDir) {
if (requestQueue_in.isReady()) {
peek(requestQueue_in, RequestMsg) {
@@ -233,10 +316,61 @@
}
}
+ action(vd_allocateDmaRequestInTBE, "vd", desc="Record Data in TBE") {
+ peek(dmaRequestQueue_in, DMARequestMsg) {
+ TBEs.allocate(address);
+ TBEs[address].DmaDataBlk := in_msg.DataBlk;
+ TBEs[address].PhysicalAddress := in_msg.PhysicalAddress;
+ TBEs[address].Len := in_msg.Len;
+ TBEs[address].DmaRequestor := in_msg.Requestor;
+ TBEs[address].ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
+ //
+ // One ack for each last-level cache
+ //
+ TBEs[address].NumPendingMsgs := getNumberOfLastLevelCaches();
+ //
+ // Assume initially that the caches store a clean copy and that memory
+ // will provide the data
+ //
+ TBEs[address].CacheDirty := false;
+ }
+ }
+
action(w_deallocateTBE, "w", desc="Deallocate TBE") {
TBEs.deallocate(address);
}
+ action(m_decrementNumberOfMessages, "m", desc="Decrement the number of
messages for which we're waiting") {
+ peek(responseToDir_in, ResponseMsg) {
+ assert(in_msg.Acks > 0);
+ DEBUG_EXPR(TBEs[address].NumPendingMsgs);
+ //
+ // Note that cache data responses will have an ack count of 2. However,
+ // directory DMA requests must wait for acks from all LLC caches, so
+ // only decrement by 1.
+ //
+ TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - 1;
+ DEBUG_EXPR(TBEs[address].NumPendingMsgs);
+ }
+ }
+
+ action(n_popResponseQueue, "n", desc="Pop response queue") {
+ responseToDir_in.dequeue();
+ }
+
+ action(o_checkForCompletion, "o", desc="Check if we have received all the
messages required for completion") {
+ if (TBEs[address].NumPendingMsgs == 0) {
+ enqueue(triggerQueue_out, TriggerMsg) {
+ out_msg.Address := address;
+ if (TBEs[address].Sharers) {
+ out_msg.Type := TriggerType:ALL_ACKS;
+ } else {
+ out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS;
+ }
+ }
+ }
+ }
+
action(d_sendData, "d", desc="Send data to requestor") {
peek(memQueue_in, MemoryMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="1") {
@@ -252,18 +386,66 @@
}
}
+ action(dr_sendDmaData, "dr", desc="Send Data to DMA controller from memory")
{
+ peek(memQueue_in, MemoryMsg) {
+ enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") {
+ out_msg.PhysicalAddress := address;
+ out_msg.LineAddress := address;
+ out_msg.Type := DMAResponseType:DATA;
+ //
+ // we send the entire data block and rely on the dma controller to
+ // split it up if need be
+ //
+ out_msg.DataBlk := in_msg.DataBlk;
+ out_msg.Destination.add(TBEs[address].DmaRequestor);
+ out_msg.MessageSize := MessageSizeType:Response_Data;
+ }
+ }
+ }
+
+ action(dt_sendDmaDataFromTbe, "dt", desc="Send Data to DMA controller from
tbe") {
+ peek(triggerQueue_in, TriggerMsg) {
+ enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") {
+ out_msg.PhysicalAddress := address;
+ out_msg.LineAddress := address;
+ out_msg.Type := DMAResponseType:DATA;
+ //
+ // we send the entire data block and rely on the dma controller to
+ // split it up if need be
+ //
+ out_msg.DataBlk := TBEs[address].DataBlk;
+ out_msg.Destination.add(TBEs[address].DmaRequestor);
+ out_msg.MessageSize := MessageSizeType:Response_Data;
+ }
+ }
+ }
+
+ action(da_sendDmaAck, "da", desc="Send Ack to DMA controller") {
+ enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") {
+ out_msg.PhysicalAddress := address;
+ out_msg.LineAddress := address;
+ out_msg.Type := DMAResponseType:ACK;
+ out_msg.Destination.add(TBEs[address].DmaRequestor);
+ out_msg.MessageSize := MessageSizeType:Writeback_Control;
+ }
+ }
+
action(rx_recordExclusiveInTBE, "rx", desc="Record Exclusive in TBE") {
peek(requestQueue_in, RequestMsg) {
TBEs[address].ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
}
}
- action(r_recordDataInTBE, "r", desc="Record Data in TBE") {
+ action(r_recordDataInTBE, "rt", desc="Record Data in TBE") {
peek(requestQueue_in, RequestMsg) {
TBEs[address].ResponseType := CoherenceResponseType:DATA;
}
}
+ action(r_setSharerBit, "r", desc="We saw other sharers") {
+ TBEs[address].Sharers := true;
+ }
+
action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch
request") {
peek(requestQueue_in, RequestMsg) {
enqueue(memQueue_out, MemoryMsg, latency="1") {
@@ -272,56 +454,25 @@
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.MessageSize := in_msg.MessageSize;
- out_msg.DataBlk := directory[in_msg.Address].DataBlk;
+ out_msg.DataBlk := directory[address].DataBlk;
DEBUG_EXPR(out_msg);
}
}
}
-// action(qx_queueMemoryFetchExclusiveRequest, "xf", desc="Queue off-chip
fetch request") {
-// peek(requestQueue_in, RequestMsg) {
-// enqueue(memQueue_out, MemoryMsg, latency=memory_request_latency) {
-// out_msg.Address := address;
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev