-
-machine(DMA, "DMA Controller")
-: DMASequencer * dma_sequencer,
- int request_latency = 14,
- int response_latency = 14
+/*
+ * 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";
-
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";
}
- structure(DMASequencer, external = "yes") {
- void ackCallback();
- void dataCallback(DataBlock);
- }
-
structure(TBETable, external = "yes") {
- TBE lookup(Address);
- void allocate(Address);
- void deallocate(Address);
- bool isPresent(Address);
+ TBE lookup(Addr);
+ void allocate(Addr);
+ void deallocate(Addr);
+ bool isPresent(Addr);
}
- MessageBuffer mandatoryQueue, ordered="false";
- MessageBuffer triggerQueue, ordered="true";
- TBETable TBEs, template_hack="<DMA_TBE>";
+ TBETable TBEs, template="<DMA_TBE>", constructor="m_number_of_TBEs";
State cur_state;
+ Tick clockEdge();
void set_tbe(TBE b);
void unset_tbe();
- State getState(TBE tbe, Address addr) {
+ State getState(TBE tbe, Addr addr) {
return cur_state;
}
- void setState(TBE tbe, 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,
}
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),
- TBEs[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),
- TBEs[makeLineAddress(in_msg.Address)]);
+ 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),
- TBEs[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, TBEs[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;
}
}
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_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") {
unset_tbe();
}
- action(z_stall, "z", desc="dma is busy..stall") {
- // do nothing
- }
-
-
transition(READY, ReadRequest, BUSY_RD) {
s_sendReadRequest;
}
transition(BUSY_WR, All_Acks, READY) {
- a_ackCallback;
+ a_ackCallback;
u_sendExclusiveUnblockToDir;
w_deallocateTBE;
p_popTriggerQueue;