-
-machine(DMA, "DMA Controller")
-: int request_latency,
- int response_latency
+/*
+ * Copyright (c) 2009-2013 Mark D. Hill and David A. Wood
+ * Copyright (c) 2010-2011 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * 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.
+ */
+
+machine(DMA, "DMA Controller")
+ : DMASequencer * dma_sequencer;
+ Cycles request_latency := 14;
+ Cycles response_latency := 14;
+
+ MessageBuffer * responseFromDir, network="From", virtual_network="2",
+ vnet_type="response";
+
+ MessageBuffer * reqToDir, network="To", virtual_network="1",
+ vnet_type="request";
+ MessageBuffer * respToDir, network="To", virtual_network="2",
+ vnet_type="dmaresponse";
+
+ MessageBuffer * mandatoryQueue;
+ MessageBuffer * triggerQueue;
{
-
- MessageBuffer goo1, network="From", virtual_network="0", ordered="false";
- MessageBuffer goo2, network="From", virtual_network="1", ordered="false";
- MessageBuffer responseFromDir, network="From", virtual_network="2", ordered="false";
-
- MessageBuffer foo1, network="To", virtual_network="0", ordered="false";
- MessageBuffer reqToDir, network="To", virtual_network="1", ordered="false";
- MessageBuffer respToDir, network="To", virtual_network="2", ordered="false";
-
- enumeration(State, desc="DMA states", default="DMA_State_READY") {
- READY, desc="Ready to accept a new request";
- BUSY_RD, desc="Busy: currently processing a request";
- BUSY_WR, desc="Busy: currently processing a request";
- }
-
+ state_declaration(State, desc="DMA states", default="DMA_State_READY") {
+ READY, AccessPermission:Invalid, desc="Ready to accept a new request";
+ BUSY_RD, AccessPermission:Busy, desc="Busy: currently processing a request";
+ BUSY_WR, AccessPermission:Busy, desc="Busy: currently processing a request";
+ }
+
enumeration(Event, desc="DMA events") {
ReadRequest, desc="A new read request";
WriteRequest, desc="A new write request";
}
structure(TBE, desc="...") {
- Address address, desc="Physical address";
+ Addr address, desc="Physical address";
int NumAcks, default="0", desc="Number of Acks pending";
DataBlock DataBlk, desc="Data";
}
- external_type(DMASequencer) {
- void ackCallback();
- void dataCallback(DataBlock);
- }
-
- external_type(TBETable) {
- TBE lookup(Address);
- void allocate(Address);
- void deallocate(Address);
- bool isPresent(Address);
+ structure(TBETable, external = "yes") {
+ TBE lookup(Addr);
+ void allocate(Addr);
+ void deallocate(Addr);
+ bool isPresent(Addr);
}
- MessageBuffer mandatoryQueue, ordered="false";
- MessageBuffer triggerQueue, ordered="true";
- DMASequencer dma_sequencer, factory='RubySystem::getDMASequencer(m_cfg["dma_sequencer"])';
- TBETable TBEs, template_hack="<DMA_TBE>";
+ TBETable TBEs, template="<DMA_TBE>", constructor="m_number_of_TBEs";
State cur_state;
- State getState(Address addr) {
+ Tick clockEdge();
+ void set_tbe(TBE b);
+ void unset_tbe();
+
+ State getState(TBE tbe, Addr addr) {
return cur_state;
}
- void setState(Address addr, State state) {
+ void setState(TBE tbe, Addr addr, State state) {
cur_state := state;
}
- out_port(reqToDirectory_out, RequestMsg, reqToDir, desc="...");
- out_port(respToDirectory_out, ResponseMsg, respToDir, desc="...");
- out_port(foo1_out, ResponseMsg, foo1, desc="...");
- out_port(triggerQueue_out, TriggerMsg, triggerQueue, desc="...");
+ AccessPermission getAccessPermission(Addr addr) {
+ return AccessPermission:NotPresent;
+ }
- in_port(goo1_in, RequestMsg, goo1) {
- if (goo1_in.isReady()) {
- peek(goo1_in, RequestMsg) {
- assert(false);
- }
- }
+ void setAccessPermission(Addr addr, State state) {
}
-
- in_port(goo2_in, RequestMsg, goo2) {
- if (goo2_in.isReady()) {
- peek(goo2_in, RequestMsg) {
- assert(false);
- }
- }
+
+ void functionalRead(Addr addr, Packet *pkt) {
+ error("DMA does not support functional read.");
}
+ int functionalWrite(Addr addr, Packet *pkt) {
+ error("DMA does not support functional write.");
+ }
+
+ out_port(reqToDirectory_out, RequestMsg, reqToDir, desc="...");
+ out_port(respToDirectory_out, ResponseMsg, respToDir, desc="...");
+ out_port(triggerQueue_out, TriggerMsg, triggerQueue, desc="...");
+
in_port(dmaRequestQueue_in, SequencerMsg, mandatoryQueue, desc="...") {
- if (dmaRequestQueue_in.isReady()) {
+ if (dmaRequestQueue_in.isReady(clockEdge())) {
peek(dmaRequestQueue_in, SequencerMsg) {
if (in_msg.Type == SequencerRequestType:LD ) {
- trigger(Event:ReadRequest, in_msg.LineAddress);
+ trigger(Event:ReadRequest, in_msg.LineAddress,
+ TBEs[in_msg.LineAddress]);
} else if (in_msg.Type == SequencerRequestType:ST) {
- trigger(Event:WriteRequest, in_msg.LineAddress);
+ trigger(Event:WriteRequest, in_msg.LineAddress,
+ TBEs[in_msg.LineAddress]);
} else {
error("Invalid request type");
}
}
in_port(dmaResponseQueue_in, ResponseMsg, responseFromDir, desc="...") {
- if (dmaResponseQueue_in.isReady()) {
+ if (dmaResponseQueue_in.isReady(clockEdge())) {
peek( dmaResponseQueue_in, ResponseMsg) {
if (in_msg.Type == CoherenceResponseType:DMA_ACK) {
- trigger(Event:DMA_Ack, makeLineAddress(in_msg.Address));
+ trigger(Event:DMA_Ack, makeLineAddress(in_msg.addr),
+ TBEs[makeLineAddress(in_msg.addr)]);
} else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE ||
- in_msg.Type == CoherenceResponseType:DATA) {
- trigger(Event:Data, makeLineAddress(in_msg.Address));
+ in_msg.Type == CoherenceResponseType:DATA) {
+ trigger(Event:Data, makeLineAddress(in_msg.addr),
+ TBEs[makeLineAddress(in_msg.addr)]);
} else if (in_msg.Type == CoherenceResponseType:ACK) {
- trigger(Event:Inv_Ack, makeLineAddress(in_msg.Address));
+ trigger(Event:Inv_Ack, makeLineAddress(in_msg.addr),
+ TBEs[makeLineAddress(in_msg.addr)]);
} else {
error("Invalid response type");
}
// Trigger Queue
in_port(triggerQueue_in, TriggerMsg, triggerQueue) {
- if (triggerQueue_in.isReady()) {
+ if (triggerQueue_in.isReady(clockEdge())) {
peek(triggerQueue_in, TriggerMsg) {
if (in_msg.Type == TriggerType:ALL_ACKS) {
- trigger(Event:All_Acks, in_msg.Address);
+ trigger(Event:All_Acks, in_msg.addr, TBEs[in_msg.addr]);
} else {
error("Unexpected message");
}
action(s_sendReadRequest, "s", desc="Send a DMA read request to memory") {
peek(dmaRequestQueue_in, SequencerMsg) {
- enqueue(reqToDirectory_out, RequestMsg, latency=request_latency) {
- out_msg.Address := in_msg.PhysicalAddress;
+ enqueue(reqToDirectory_out, RequestMsg, request_latency) {
+ out_msg.addr := in_msg.PhysicalAddress;
out_msg.Type := CoherenceRequestType:DMA_READ;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
out_msg.Destination.add(map_Address_to_Directory(address));
out_msg.Requestor := machineID;
+ out_msg.RequestorMachine := MachineType:DMA;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
action(s_sendWriteRequest, "\s", desc="Send a DMA write request to memory") {
peek(dmaRequestQueue_in, SequencerMsg) {
- enqueue(reqToDirectory_out, RequestMsg, latency=request_latency) {
- out_msg.Address := in_msg.PhysicalAddress;
+ enqueue(reqToDirectory_out, RequestMsg, request_latency) {
+ out_msg.addr := in_msg.PhysicalAddress;
out_msg.Type := CoherenceRequestType:DMA_WRITE;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
out_msg.Destination.add(map_Address_to_Directory(address));
out_msg.Requestor := machineID;
+ out_msg.RequestorMachine := MachineType:DMA;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
}
action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") {
- if (TBEs[address].NumAcks == 0) {
+ assert(is_valid(tbe));
+ if (tbe.NumAcks == 0) {
enqueue(triggerQueue_out, TriggerMsg) {
- out_msg.Address := address;
+ out_msg.addr := address;
out_msg.Type := TriggerType:ALL_ACKS;
}
}
action(u_updateAckCount, "u", desc="Update ack count") {
peek(dmaResponseQueue_in, ResponseMsg) {
- TBEs[address].NumAcks := TBEs[address].NumAcks - in_msg.Acks;
+ assert(is_valid(tbe));
+ tbe.NumAcks := tbe.NumAcks - in_msg.Acks;
}
}
action( u_sendExclusiveUnblockToDir, "\u", desc="send exclusive unblock to directory") {
- enqueue(respToDirectory_out, ResponseMsg, latency=response_latency) {
- out_msg.Address := address;
+ enqueue(respToDirectory_out, ResponseMsg, response_latency) {
+ out_msg.addr := address;
out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE;
out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Sender := machineID;
+ out_msg.SenderMachine := MachineType:DMA;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
action(p_popRequestQueue, "p", desc="Pop request queue") {
- dmaRequestQueue_in.dequeue();
+ dmaRequestQueue_in.dequeue(clockEdge());
}
action(p_popResponseQueue, "\p", desc="Pop request queue") {
- dmaResponseQueue_in.dequeue();
+ dmaResponseQueue_in.dequeue(clockEdge());
}
action(p_popTriggerQueue, "pp", desc="Pop trigger queue") {
- triggerQueue_in.dequeue();
+ triggerQueue_in.dequeue(clockEdge());
}
action(t_updateTBEData, "t", desc="Update TBE Data") {
peek(dmaResponseQueue_in, ResponseMsg) {
- TBEs[address].DataBlk := in_msg.DataBlk;
+ assert(is_valid(tbe));
+ tbe.DataBlk := in_msg.DataBlk;
}
}
action(d_dataCallbackFromTBE, "/d", desc="data callback with data from TBE") {
- dma_sequencer.dataCallback(TBEs[address].DataBlk);
+ assert(is_valid(tbe));
+ dma_sequencer.dataCallback(tbe.DataBlk);
}
action(v_allocateTBE, "v", desc="Allocate TBE entry") {
TBEs.allocate(address);
+ set_tbe(TBEs[address]);
}
action(w_deallocateTBE, "w", desc="Deallocate TBE entry") {
TBEs.deallocate(address);
+ unset_tbe();
}
- action(z_stall, "z", desc="dma is busy..stall") {
- // do nothing
- }
-
-
transition(READY, ReadRequest, BUSY_RD) {
s_sendReadRequest;
p_popResponseQueue;
}
- transition(BUSY_RD, Data) {
+ transition(BUSY_RD, Data, READY) {
t_updateTBEData;
- u_updateAckCount;
- o_checkForCompletion;
+ d_dataCallbackFromTBE;
+ w_deallocateTBE;
+ //u_updateAckCount;
+ //o_checkForCompletion;
p_popResponseQueue;
}
transition(BUSY_RD, All_Acks, READY) {
d_dataCallbackFromTBE;
- u_sendExclusiveUnblockToDir;
+ //u_sendExclusiveUnblockToDir;
w_deallocateTBE;
p_popTriggerQueue;
}
}
transition(BUSY_WR, All_Acks, READY) {
- a_ackCallback;
+ a_ackCallback;
u_sendExclusiveUnblockToDir;
w_deallocateTBE;
p_popTriggerQueue;