From 92de70b69aaf3f399a855057b556ed198139e5d8 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 6 Jul 2009 15:49:47 -0700 Subject: ruby: Import the latest ruby changes from gems. This was done with an automated process, so there could be things that were done in this tree in the past that didn't make it. One known regression is that atomic memory operations do not seem to work properly anymore. --- src/mem/protocol/MI_example-dir.sm | 458 ++++++++++++++++++++++++++++++++----- 1 file changed, 402 insertions(+), 56 deletions(-) (limited to 'src/mem/protocol/MI_example-dir.sm') diff --git a/src/mem/protocol/MI_example-dir.sm b/src/mem/protocol/MI_example-dir.sm index 311f8488b..f597ab73c 100644 --- a/src/mem/protocol/MI_example-dir.sm +++ b/src/mem/protocol/MI_example-dir.sm @@ -1,11 +1,12 @@ -machine(Directory, "Directory protocol") { +machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_DIRECTORY_LATENCY LATENCY_MEMORY_LATENCY { - MessageBuffer forwardFromDir, network="To", virtual_network="2", ordered="true"; + 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"; MessageBuffer requestToDir, network="From", virtual_network="0", ordered="true"; - MessageBuffer unblockToDir, network="From", virtual_network="3", ordered="true"; + MessageBuffer dmaRequestToDir, network="From", virtual_network="5", ordered="true"; // STATES enumeration(State, desc="Directory states", default="Directory_State_I") { @@ -13,17 +14,32 @@ machine(Directory, "Directory protocol") { I, desc="Invalid"; M, desc="Modified"; - MI, desc="Blocked on a writeback"; + M_DRD, desc="Blocked on an invalidation for a DMA read"; + M_DWR, desc="Blocked on an invalidation for a DMA write"; + + M_DWRI, desc="Intermediate state M_DWR-->I"; + + IM, desc="Intermediate state I-->M"; + MI, desc="Intermediate state M-->I"; + ID, desc="Intermediate state for DMA_READ when in I"; + ID_W, desc="Intermediate state for DMA_WRITE when in I"; } // Events enumeration(Event, desc="Directory events") { + // processor requests GETX, desc="A GETX arrives"; GETS, desc="A GETS arrives"; PUTX, desc="A PUTX arrives"; PUTX_NotOwner, desc="A PUTX arrives"; - PUTO, desc="A PUTO arrives"; - Unblock, desc="An unblock message arrives"; + + // 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"; } // TYPES @@ -39,26 +55,58 @@ machine(Directory, "Directory protocol") { external_type(DirectoryMemory) { Entry lookup(Address); bool isPresent(Address); + void invalidateBlock(Address); + } + + external_type(MemoryControl, inport="yes", outport="yes") { + + } + + + // TBE entries for DMA requests + structure(TBE, desc="TBE entries for outstanding DMA requests") { + State TBEState, desc="Transient State"; + DataBlock DataBlk, desc="Data to be written (DMA write only)"; + int Offset, desc="..."; + int Len, desc="..."; } + external_type(TBETable) { + TBE lookup(Address); + void allocate(Address); + void deallocate(Address); + bool isPresent(Address); + } // ** OBJECTS ** + DirectoryMemory directory, factory='RubySystem::getDirectory(m_cfg["directory_name"])'; + + MemoryControl memBuffer, factory='RubySystem::getMemoryControl(m_cfg["memory_controller_name"])'; - DirectoryMemory directory, constructor_hack="i"; + TBETable TBEs, template_hack=""; State getState(Address addr) { - return directory[addr].DirectoryState; + if (TBEs.isPresent(addr)) { + return TBEs[addr].TBEState; + } else if (directory.isPresent(addr)) { + return directory[addr].DirectoryState; + } else { + return State:I; + } } void setState(Address addr, State state) { + + if (TBEs.isPresent(addr)) { + TBEs[addr].TBEState := state; + } + if (directory.isPresent(addr)) { if (state == State:I) { assert(directory[addr].Owner.count() == 0); assert(directory[addr].Sharers.count() == 0); - } - - if (state == State:M) { + } else if (state == State:M) { assert(directory[addr].Owner.count() == 1); assert(directory[addr].Sharers.count() == 0); } @@ -71,9 +119,25 @@ machine(Directory, "Directory protocol") { 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, dmaRequestFromDir); +//added by SS + out_port(memQueue_out, MemoryMsg, memBuffer); // ** IN_PORTS ** + 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.PhysicalAddress); + } else if (in_msg.Type == DMARequestType:WRITE) { + trigger(Event:DMA_WRITE, in_msg.PhysicalAddress); + } else { + error("Invalid message"); + } + } + } + } in_port(requestQueue_in, RequestMsg, requestToDir) { if (requestQueue_in.isReady()) { @@ -88,8 +152,6 @@ machine(Directory, "Directory protocol") { } else { trigger(Event:PUTX_NotOwner, in_msg.Address); } - } else if (in_msg.Type == CoherenceRequestType:PUTO) { - trigger(Event:PUTO, in_msg.Address); } else { error("Invalid message"); } @@ -97,20 +159,23 @@ machine(Directory, "Directory protocol") { } } - in_port(unblockNetwork_in, ResponseMsg, unblockToDir) { - if (unblockNetwork_in.isReady()) { - peek(unblockNetwork_in, ResponseMsg) { - if (in_msg.Type == CoherenceResponseType:UNBLOCK) { - trigger(Event:Unblock, in_msg.Address); +//added by SS + // off-chip memory request/response is done + in_port(memQueue_in, MemoryMsg, memBuffer) { + if (memQueue_in.isReady()) { + peek(memQueue_in, MemoryMsg) { + if (in_msg.Type == MemoryRequestType:MEMORY_READ) { + trigger(Event:Memory_Data, in_msg.Address); + } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { + trigger(Event:Memory_Ack, in_msg.Address); } else { + DEBUG_EXPR(in_msg.Type); error("Invalid message"); } } } } - - // Actions action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") { @@ -125,6 +190,18 @@ machine(Directory, "Directory protocol") { } } + action(l_sendWriteBackAck, "la", desc="Send writeback ack to requestor") { + peek(memQueue_in, MemoryMsg) { + enqueue(forwardNetwork_out, RequestMsg, latency="TO_MEM_CTRL_LATENCY") { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:WB_ACK; + out_msg.Requestor := in_msg.OriginalRequestorMachId; + out_msg.Destination.add(in_msg.OriginalRequestorMachId); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + } + action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") { peek(requestQueue_in, RequestMsg) { enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") { @@ -141,31 +218,90 @@ machine(Directory, "Directory protocol") { directory[address].Owner.clear(); } +// action(d_sendData, "d", desc="Send data to requestor") { +// peek(requestQueue_in, RequestMsg) { +// enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") { +// out_msg.Address := address; +// +// if (in_msg.Type == CoherenceRequestType:GETS && directory[address].Sharers.count() == 0) { +// // out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE_CLEAN; +// out_msg.Type := CoherenceResponseType:DATA; +// } else { +// out_msg.Type := CoherenceResponseType:DATA; +// } +// +// out_msg.Sender := machineID; +// out_msg.Destination.add(in_msg.Requestor); +// out_msg.DataBlk := directory[in_msg.Address].DataBlk; +// out_msg.MessageSize := MessageSizeType:Response_Data; +// } +// } +// } + action(d_sendData, "d", desc="Send data to requestor") { - peek(requestQueue_in, RequestMsg) { - enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") { + peek(memQueue_in, MemoryMsg) { + enqueue(responseNetwork_out, ResponseMsg, latency="TO_MEM_CTRL_LATENCY") { out_msg.Address := address; + out_msg.Type := CoherenceResponseType:DATA; + out_msg.Sender := machineID; + out_msg.Destination.add(in_msg.OriginalRequestorMachId); + out_msg.DataBlk := in_msg.DataBlk; + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } - if (in_msg.Type == CoherenceRequestType:GETS && directory[address].Sharers.count() == 0) { - // out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE_CLEAN; - out_msg.Type := CoherenceResponseType:DATA; - } else { - out_msg.Type := CoherenceResponseType:DATA; - } +// action(dr_sendDMAData, "dr", desc="Send Data to DMA controller from directory") { +// peek(dmaRequestQueue_in, DMARequestMsg) { +// enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") { +// out_msg.PhysicalAddress := address; +// out_msg.Type := DMAResponseType:DATA; +// out_msg.DataBlk := directory[in_msg.PhysicalAddress].DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be +// out_msg.Destination.add(map_Address_to_DMA(address)); +// out_msg.MessageSize := MessageSizeType:Response_Data; +// } +// } +// } + + action(dr_sendDMAData, "dr", desc="Send Data to DMA controller from directory") { + peek(memQueue_in, MemoryMsg) { + enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") { + out_msg.PhysicalAddress := address; + out_msg.Type := DMAResponseType:DATA; + out_msg.DataBlk := in_msg.DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be + out_msg.Destination.add(map_Address_to_DMA(address)); + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } - out_msg.Sender := machineID; - out_msg.Destination.add(in_msg.Requestor); - out_msg.DataBlk := directory[in_msg.Address].DataBlk; - out_msg.Dirty := false; // By definition, the block is now clean - out_msg.Acks := directory[address].Sharers.count(); - if (directory[address].Sharers.isElement(in_msg.Requestor)) { - out_msg.Acks := out_msg.Acks - 1; - } + + + action(drp_sendDMAData, "drp", desc="Send Data to DMA controller from incoming PUTX") { + peek(requestQueue_in, RequestMsg) { + enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") { + out_msg.PhysicalAddress := address; + out_msg.Type := DMAResponseType:DATA; + out_msg.DataBlk := in_msg.DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be + out_msg.Destination.add(map_Address_to_DMA(address)); out_msg.MessageSize := MessageSizeType:Response_Data; } } } + action(da_sendDMAAck, "da", desc="Send Ack to DMA controller") { + enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") { + out_msg.PhysicalAddress := address; + out_msg.Type := DMAResponseType:ACK; + out_msg.Destination.add(map_Address_to_DMA(address)); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + + action(d_deallocateDirectory, "\d", desc="Deallocate Directory Entry") { + directory.invalidateBlock(address); + } + action(e_ownerIsRequestor, "e", desc="The owner is now the requestor") { peek(requestQueue_in, RequestMsg) { directory[address].Owner.clear(); @@ -184,26 +320,32 @@ machine(Directory, "Directory protocol") { out_msg.Type := in_msg.Type; out_msg.Requestor := in_msg.Requestor; out_msg.Destination := directory[in_msg.Address].Owner; - out_msg.Acks := directory[address].Sharers.count(); - if (directory[address].Sharers.isElement(in_msg.Requestor)) { - out_msg.Acks := out_msg.Acks - 1; - } - out_msg.MessageSize := MessageSizeType:Forwarded_Control; + out_msg.MessageSize := MessageSizeType:Writeback_Control; } } } + action(inv_sendCacheInvalidate, "inv", desc="Invalidate a cache block") { + peek(dmaRequestQueue_in, DMARequestMsg) { + enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:INV; + out_msg.Requestor := machineID; + out_msg.Destination := directory[in_msg.PhysicalAddress].Owner; + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + } action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") { requestQueue_in.dequeue(); } - action(j_popIncomingUnblockQueue, "j", desc="Pop incoming unblock queue") { - unblockNetwork_in.dequeue(); + action(p_popIncomingDMARequestQueue, "p", desc="Pop incoming DMA queue") { + dmaRequestQueue_in.dequeue(); } - action(l_writeDataToMemory, "l", desc="Write PUTX/PUTO data to memory") { - // peek(unblockNetwork_in, ResponseMsg) { + action(l_writeDataToMemory, "l", desc="Write PUTX data to memory") { peek(requestQueue_in, RequestMsg) { // assert(in_msg.Dirty); // assert(in_msg.MessageSize == MessageSizeType:Writeback_Data); @@ -213,16 +355,218 @@ machine(Directory, "Directory protocol") { } } + action(dw_writeDMAData, "dw", desc="DMA Write data to memory") { + peek(dmaRequestQueue_in, DMARequestMsg) { + directory[in_msg.PhysicalAddress].DataBlk.copyPartial(in_msg.DataBlk, in_msg.Offset, in_msg.Len); + } + } + + action(dwt_writeDMADataFromTBE, "dwt", desc="DMA Write data to memory from TBE") { + directory[address].DataBlk.copyPartial(TBEs[address].DataBlk, TBEs[address].Offset, TBEs[address].Len); + } + + action(v_allocateTBE, "v", desc="Allocate TBE") { + peek(dmaRequestQueue_in, DMARequestMsg) { + TBEs.allocate(address); + TBEs[address].DataBlk := in_msg.DataBlk; + TBEs[address].Offset := in_msg.Offset; + TBEs[address].Len := in_msg.Len; + } + } + + action(w_deallocateTBE, "w", desc="Deallocate TBE") { + TBEs.deallocate(address); + } + + action(z_recycleRequestQueue, "z", desc="recycle request queue") { + requestQueue_in.recycle(); + } + action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") { + peek(requestQueue_in, RequestMsg) { + enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_READ; + out_msg.Sender := machineID; + out_msg.OriginalRequestorMachId := in_msg.Requestor; + out_msg.MessageSize := in_msg.MessageSize; + out_msg.DataBlk := directory[in_msg.Address].DataBlk; + DEBUG_EXPR(out_msg); + } + } + } + + action(qf_queueMemoryFetchRequestDMA, "qfd", desc="Queue off-chip fetch request") { + peek(dmaRequestQueue_in, DMARequestMsg) { + enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_READ; + out_msg.Sender := machineID; + //out_msg.OriginalRequestorMachId := machineID; + out_msg.MessageSize := in_msg.MessageSize; + out_msg.DataBlk := directory[address].DataBlk; + DEBUG_EXPR(out_msg); + } + } + } +// action(qw_queueMemoryWBRequest, "qw", desc="Queue off-chip writeback request") { +// peek(dmaRequestQueue_in, DMARequestMsg) { +// enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") { +// out_msg.Address := address; +// out_msg.Type := MemoryRequestType:MEMORY_WB; +// out_msg.OriginalRequestorMachId := machineID; +// out_msg.DataBlk := in_msg.DataBlk; +// out_msg.MessageSize := in_msg.MessageSize; + +// DEBUG_EXPR(out_msg); +// } +// } +// } + + + action(qw_queueMemoryWBRequest_partial, "qwp", desc="Queue off-chip writeback request") { + peek(dmaRequestQueue_in, DMARequestMsg) { + enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_WB; + //out_msg.OriginalRequestorMachId := machineID; + //out_msg.DataBlk := in_msg.DataBlk; + out_msg.DataBlk.copyPartial(in_msg.DataBlk, in_msg.Offset, in_msg.Len); + out_msg.MessageSize := in_msg.MessageSize; + //out_msg.Prefetch := in_msg.Prefetch; + + DEBUG_EXPR(out_msg); + } + } + } + + action(qw_queueMemoryWBRequest_partialTBE, "qwt", desc="Queue off-chip writeback request") { + peek(requestQueue_in, RequestMsg) { + enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_WB; + out_msg.OriginalRequestorMachId := in_msg.Requestor; + //out_msg.DataBlk := in_msg.DataBlk; + out_msg.DataBlk.copyPartial(TBEs[address].DataBlk, TBEs[address].Offset, TBEs[address].Len); + out_msg.MessageSize := in_msg.MessageSize; + //out_msg.Prefetch := in_msg.Prefetch; + + DEBUG_EXPR(out_msg); + } + } + } + + + + action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") { + peek(requestQueue_in, RequestMsg) { + enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_WB; + out_msg.OriginalRequestorMachId := in_msg.Requestor; + out_msg.DataBlk := in_msg.DataBlk; + out_msg.MessageSize := in_msg.MessageSize; + //out_msg.Prefetch := in_msg.Prefetch; + + DEBUG_EXPR(out_msg); + } + } + } + + action(l_popMemQueue, "q", desc="Pop off-chip request queue") { + memQueue_in.dequeue(); + } + // TRANSITIONS - transition(I, GETX, M) { - d_sendData; + transition({M_DRD, M_DWR}, GETX) { + z_recycleRequestQueue; + } + + transition({IM, MI, ID, ID_W}, {GETX, GETS, DMA_READ, DMA_WRITE, PUTX, PUTX_NotOwner} ) { + z_recycleRequestQueue; + } + + transition(I, GETX, IM) { + //d_sendData; + qf_queueMemoryFetchRequest; e_ownerIsRequestor; i_popIncomingRequestQueue; } + transition(IM, Memory_Data, M) { + d_sendData; + //e_ownerIsRequestor; + l_popMemQueue; + } + + + transition(I, DMA_READ, ID) { + //dr_sendDMAData; + qf_queueMemoryFetchRequestDMA; + p_popIncomingDMARequestQueue; + } + + transition(ID, Memory_Data, I) { + dr_sendDMAData; + //p_popIncomingDMARequestQueue; + l_popMemQueue; + } + + + + transition(I, DMA_WRITE, ID_W) { + dw_writeDMAData; +// da_sendDMAAck; + qw_queueMemoryWBRequest_partial; + p_popIncomingDMARequestQueue; + } + + transition(ID_W, Memory_Ack, I) { + da_sendDMAAck; + l_popMemQueue; + } + + transition(M, DMA_READ, M_DRD) { + inv_sendCacheInvalidate; + p_popIncomingDMARequestQueue; + } + + transition(M_DRD, PUTX, I) { + drp_sendDMAData; + c_clearOwner; + a_sendWriteBackAck; + // d_deallocateDirectory; + i_popIncomingRequestQueue; + } + + transition(M, DMA_WRITE, M_DWR) { + v_allocateTBE; + inv_sendCacheInvalidate; + p_popIncomingDMARequestQueue; + } + + transition(M_DWR, PUTX, M_DWRI) { + dwt_writeDMADataFromTBE; + qw_queueMemoryWBRequest_partialTBE; + //a_sendWriteBackAck; + c_clearOwner; + //da_sendDMAAck; + w_deallocateTBE; + i_popIncomingRequestQueue; + } + + transition(M_DWRI, Memory_Ack, I) { + //dwt_writeDMADataFromTBE; + l_sendWriteBackAck; + //c_clearOwner; + da_sendDMAAck; + //w_deallocateTBE; + l_popMemQueue; + } + + transition(M, GETX, M) { @@ -231,14 +575,20 @@ machine(Directory, "Directory protocol") { i_popIncomingRequestQueue; } - // transition(M, PUTX, MI) { - transition(M, PUTX, I) { + transition(M, PUTX, MI) { c_clearOwner; - l_writeDataToMemory; - a_sendWriteBackAck; +// l_writeDataToMemory; + l_queueMemoryWBRequest; +// a_sendWriteBackAck; + d_deallocateDirectory; i_popIncomingRequestQueue; } + transition(MI, Memory_Ack, I) { + l_sendWriteBackAck; + l_popMemQueue; + } + transition(M, PUTX_NotOwner, M) { b_sendWriteBackNack; i_popIncomingRequestQueue; @@ -246,12 +596,8 @@ machine(Directory, "Directory protocol") { transition(I, PUTX_NotOwner, I) { b_sendWriteBackNack; + d_deallocateDirectory; i_popIncomingRequestQueue; } - - transition(MI, Unblock, M) { - j_popIncomingUnblockQueue; - } - } -- cgit v1.2.3