changeset 98e05d58f9eb in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=98e05d58f9eb
description:
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:
src/dev/dma_device.cc | 95 +++++++++++++++++++++++--------------------
src/dev/dma_device.hh | 110 ++++++++++++++++++++++++++++++--------------------
2 files changed, 117 insertions(+), 88 deletions(-)
diffs (289 lines):
diff -r d6bca167cee4 -r 98e05d58f9eb src/dev/dma_device.cc
--- a/src/dev/dma_device.cc Tue Oct 23 04:24:32 2012 -0400
+++ b/src/dev/dma_device.cc Tue Oct 23 04:49:33 2012 -0400
@@ -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 @@
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 @@
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 @@
// 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 @@
// 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());
+ trySendTimingReq();
+ } else if (state == Enums::atomic) {
+ // send everything there is to send in zero time
+ while (!transmitList.empty()) {
+ PacketPtr pkt = transmitList.front();
+ transmitList.pop_front();
- 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());
- } else if (state == Enums::atomic) {
- 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.");
}
diff -r d6bca167cee4 -r 98e05d58f9eb src/dev/dma_device.hh
--- a/src/dev/dma_device.hh Tue Oct 23 04:24:32 2012 -0400
+++ b/src/dev/dma_device.hh Tue Oct 23 04:49:33 2012 -0400
@@ -51,49 +51,24 @@
class DmaPort : public MasterPort
{
- protected:
- struct DmaReqState : public Packet::SenderState
- {
- /** Event to call on the device when this transaction (all packets)
- * complete. */
- Event *completionEvent;
+ private:
- /** Total number of bytes that this transaction involves. */
- Addr totBytes;
+ /**
+ * Take the first packet of the transmit list and attempt to send
+ * it as a timing request. If it is successful, schedule the
+ * sending of the next packet, otherwise remember that we are
+ * waiting for a retry.
+ */
+ void trySendTimingReq();
- /** Number of bytes that have been acked for this transaction. */
- Addr numBytes;
-
- /** Amount to delay completion of dma by */
- Tick delay;
-
- DmaReqState(Event *ce, Addr tb, Tick _delay)
- : completionEvent(ce), totBytes(tb), numBytes(0), delay(_delay)
- {}
- };
-
- MemObject *device;
-
- /** Use a deque as we never to any insertion or removal in the middle */
- std::deque<PacketPtr> transmitList;
-
- /** The system that device/port are in. This is used to select which mode
- * we are currently operating in. */
- System *sys;
-
- /** Id for all requests */
- MasterID masterId;
-
- /** Number of outstanding packets the dma port has. */
- uint32_t pendingCount;
-
- /** If we need to drain, keep the drain event around until we're done
- * here.*/
- Event *drainEvent;
-
- /** If the port is currently waiting for a retry before it can
- * send whatever it is that it's sending. */
- bool inRetry;
+ /**
+ * For timing, attempt to send the first item on the transmit
+ * list, and if it is successful and there are more packets
+ * waiting, then schedule the sending of the next packet. For
+ * atomic, simply send and process everything on the transmit
+ * list.
+ */
+ void sendDma();
/**
* Handle a response packet by updating the corresponding DMA
@@ -107,11 +82,59 @@
*/
void handleResp(PacketPtr pkt, Tick delay = 0);
+ struct DmaReqState : public Packet::SenderState
+ {
+ /** Event to call on the device when this transaction (all packets)
+ * complete. */
+ Event *completionEvent;
+
+ /** Total number of bytes that this transaction involves. */
+ const Addr totBytes;
+
+ /** Number of bytes that have been acked for this transaction. */
+ Addr numBytes;
+
+ /** Amount to delay completion of dma by */
+ const Tick delay;
+
+ DmaReqState(Event *ce, Addr tb, Tick _delay)
+ : completionEvent(ce), totBytes(tb), numBytes(0), delay(_delay)
+ {}
+ };
+
+ /** The device that owns this port. */
+ MemObject *device;
+
+ /** Use a deque as we never do any insertion or removal in the middle */
+ std::deque<PacketPtr> transmitList;
+
+ /** Event used to schedule a future sending from the transmit list. */
+ EventWrapper<DmaPort, &DmaPort::sendDma> sendEvent;
+
+ /** The system that device/port are in. This is used to select which mode
+ * we are currently operating in. */
+ System *sys;
+
+ /** Id for all requests */
+ const MasterID masterId;
+
+ /** Number of outstanding packets the dma port has. */
+ uint32_t pendingCount;
+
+ /** If we need to drain, keep the drain event around until we're done
+ * here.*/
+ Event *drainEvent;
+
+ /** If the port is currently waiting for a retry before it can
+ * send whatever it is that it's sending. */
+ bool inRetry;
+
+ protected:
+
bool recvTimingResp(PacketPtr pkt);
void recvRetry() ;
void queueDma(PacketPtr pkt);
- void sendDma();
public:
@@ -148,7 +171,7 @@
dmaPort.dmaAction(MemCmd::ReadReq, addr, size, event, data, delay);
}
- bool dmaPending() { return dmaPort.dmaPending(); }
+ bool dmaPending() const { return dmaPort.dmaPending(); }
virtual void init();
@@ -159,7 +182,6 @@
virtual BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
- friend class DmaPort;
};
#endif // __DEV_DMA_DEVICE_HH__
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev