summaryrefslogtreecommitdiff
path: root/src/dev/dma_device.cc
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2012-10-23 04:49:33 -0400
committerAndreas Hansson <andreas.hansson@arm.com>2012-10-23 04:49:33 -0400
commit69e82539fd81299751e1000c0dac49f2eddbbdb6 (patch)
tree90a4d9e4bb2cbf51fbb1340d5faf35cad34b4ebc /src/dev/dma_device.cc
parent37ded2c2cc2523d43cb2a4ae6a421ddba5f22919 (diff)
downloadgem5-69e82539fd81299751e1000c0dac49f2eddbbdb6.tar.xz
dev: Remove zero-time loop in DMA timing send
This patch removes the zero-time loop used to send items from the DMA port transmit list. Instead of having a loop, the DMA port now uses an event to schedule sending of a single packet. Ultimately this patch serves to ease the transition to a blocking 4-phase handshake. A follow-on patch will update the regression statistics.
Diffstat (limited to 'src/dev/dma_device.cc')
-rw-r--r--src/dev/dma_device.cc93
1 files changed, 50 insertions, 43 deletions
diff --git a/src/dev/dma_device.cc b/src/dev/dma_device.cc
index 43d45146f..1aa4a8647 100644
--- a/src/dev/dma_device.cc
+++ b/src/dev/dma_device.cc
@@ -49,8 +49,8 @@
#include "sim/system.hh"
DmaPort::DmaPort(MemObject *dev, System *s)
- : MasterPort(dev->name() + ".dma", dev), device(dev), sys(s),
- masterId(s->getMasterId(dev->name())),
+ : MasterPort(dev->name() + ".dma", dev), device(dev), sendEvent(this),
+ sys(s), masterId(s->getMasterId(dev->name())),
pendingCount(0), drainEvent(NULL),
inRetry(false)
{ }
@@ -152,24 +152,7 @@ void
DmaPort::recvRetry()
{
assert(transmitList.size());
- bool result = true;
- do {
- PacketPtr pkt = transmitList.front();
- DPRINTF(DMA, "Retry on %s addr %#x\n",
- pkt->cmdString(), pkt->getAddr());
- result = sendTimingReq(pkt);
- if (result) {
- DPRINTF(DMA, "-- Done\n");
- transmitList.pop_front();
- inRetry = false;
- } else {
- inRetry = true;
- DPRINTF(DMA, "-- Failed, queued\n");
- }
- } while (result && transmitList.size());
-
- DPRINTF(DMA, "TransmitList: %d, inRetry: %d\n",
- transmitList.size(), inRetry);
+ trySendTimingReq();
}
void
@@ -198,6 +181,11 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
gen.size());
queueDma(pkt);
}
+
+ // in zero time also initiate the sending of the packets we have
+ // just created, for atomic this involves actually completing all
+ // the requests
+ sendDma();
}
void
@@ -208,8 +196,35 @@ DmaPort::queueDma(PacketPtr pkt)
// remember that we have another packet pending, this will only be
// decremented once a response comes back
pendingCount++;
+}
- sendDma();
+void
+DmaPort::trySendTimingReq()
+{
+ // send the first packet on the transmit list and schedule the
+ // following send if it is successful
+ PacketPtr pkt = transmitList.front();
+
+ DPRINTF(DMA, "Trying to send %s addr %#x\n", pkt->cmdString(),
+ pkt->getAddr());
+
+ inRetry = !sendTimingReq(pkt);
+ if (!inRetry) {
+ transmitList.pop_front();
+ DPRINTF(DMA, "-- Done\n");
+ // if there is more to do, then do so
+ if (!transmitList.empty())
+ // this should ultimately wait for as many cycles as the
+ // device needs to send the packet, but currently the port
+ // does not have any known width so simply wait a single
+ // cycle
+ device->schedule(sendEvent, device->clockEdge(Cycles(1)));
+ } else {
+ DPRINTF(DMA, "-- Failed, waiting for retry\n");
+ }
+
+ DPRINTF(DMA, "TransmitList: %d, inRetry: %d\n",
+ transmitList.size(), inRetry);
}
void
@@ -219,37 +234,29 @@ DmaPort::sendDma()
// more work is going to have to be done to make
// switching actually work
assert(transmitList.size());
- PacketPtr pkt = transmitList.front();
Enums::MemoryMode state = sys->getMemoryMode();
if (state == Enums::timing) {
- if (inRetry) {
- DPRINTF(DMA, "Can't send immediately, waiting for retry\n");
+ // if we are either waiting for a retry or are still waiting
+ // after sending the last packet, then do not proceed
+ if (inRetry || sendEvent.scheduled()) {
+ DPRINTF(DMA, "Can't send immediately, waiting to send\n");
return;
}
- DPRINTF(DMA, "Attempting to send %s addr %#x\n",
- pkt->cmdString(), pkt->getAddr());
-
- bool result;
- do {
- result = sendTimingReq(pkt);
- if (result) {
- transmitList.pop_front();
- DPRINTF(DMA, "-- Done\n");
- } else {
- inRetry = true;
- DPRINTF(DMA, "-- Failed: queued\n");
- }
- } while (result && transmitList.size());
+ trySendTimingReq();
} else if (state == Enums::atomic) {
- transmitList.pop_front();
+ // send everything there is to send in zero time
+ while (!transmitList.empty()) {
+ PacketPtr pkt = transmitList.front();
+ transmitList.pop_front();
- DPRINTF(DMA, "Sending DMA for addr: %#x size: %d\n",
- pkt->req->getPaddr(), pkt->req->getSize());
- Tick lat = sendAtomic(pkt);
+ DPRINTF(DMA, "Sending DMA for addr: %#x size: %d\n",
+ pkt->req->getPaddr(), pkt->req->getSize());
+ Tick lat = sendAtomic(pkt);
- handleResp(pkt, lat);
+ handleResp(pkt, lat);
+ }
} else
panic("Unknown memory mode.");
}