diff -r 85d0fc326753 -r a02007211735 src/dev/dma_device.hh --- a/src/dev/dma_device.hh Sat Jul 28 18:13:20 2012 +0100 +++ b/src/dev/dma_device.hh Sat Jul 28 18:25:23 2012 +0100 @@ -44,6 +44,8 @@ #ifndef __DEV_DMA_DEVICE_HH__ #define __DEV_DMA_DEVICE_HH__ +#include + #include "dev/io_device.hh" #include "params/DmaDevice.hh" @@ -71,7 +73,7 @@ }; MemObject *device; - std::list transmitList; + std::deque transmitList; /** The system that device/port are in. This is used to select which mode * we are currently operating in. */ @@ -81,7 +83,7 @@ MasterID masterId; /** Number of outstanding packets the dma port has. */ - int pendingCount; + uint pendingCount; /** If we need to drain, keep the drain event around until we're done * here.*/ @@ -91,11 +93,22 @@ * it is that it's sending. */ bool inRetry; - virtual bool recvTimingResp(PacketPtr pkt); + /** + * Handler a response packet by updating the corresponding DMA + * request state to reflect the bytes received, and also update + * the pending request counter. If the DMA request that this + * packet is part of is complete, then signal the completion event + * if present, potentially with a delay added to it. + * + * @param pkt Response packet to handler + * @param delay Additional delay for scheduling the completion event + */ + void handleResp(PacketPtr pkt, Tick delay = 0); - virtual void recvRetry() ; + bool recvTimingResp(PacketPtr pkt); + void recvRetry() ; - void queueDma(PacketPtr pkt, bool front = false); + void queueDma(PacketPtr pkt); void sendDma(); public: @@ -104,7 +117,7 @@ void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, uint8_t *data, Tick delay, Request::Flags flag = 0); - bool dmaPending() { return pendingCount > 0; } + bool dmaPending() const { return pendingCount > 0; } unsigned int drain(Event *de); }; @@ -125,13 +138,7 @@ public: typedef DmaDeviceParams Params; DmaDevice(const Params *p); - virtual ~DmaDevice(); - - const Params * - params() const - { - return dynamic_cast(_params); - } + virtual ~DmaDevice() { } void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0) @@ -147,7 +154,7 @@ delay); } - bool dmaPending() { return dmaPort->dmaPending(); } + bool dmaPending() const { return dmaPort->dmaPending(); } virtual void init(); diff -r 85d0fc326753 -r a02007211735 src/dev/dma_device.cc --- a/src/dev/dma_device.cc Sat Jul 28 18:13:20 2012 +0100 +++ b/src/dev/dma_device.cc Sat Jul 28 18:25:23 2012 +0100 @@ -39,6 +39,7 @@ * * Authors: Ali Saidi * Nathan Binkert + * Andreas Hansson */ #include "base/chunk_generator.hh" @@ -53,45 +54,64 @@ inRetry(false) { } +void +DmaHandler::handleResp(PacketPtr pkt, Tick delay) +{ + // should always see a response with a sender state + assert(pkt->isResponse()); + if (!pkt->senderState) + panic("DMA %s got packet without sender state\n", name()); + + // get the DMA sender state + DmaReqState *state = dynamic_cast(pkt->senderState); + assert(state); + + DPRINTF(DMA, "Received response %s for addr: %#x size: %d nb: %d," \ + " tot: %d sched %d\n", + pkt->cmdString(), pkt->getAddr(), pkt->req->getSize(), + state->numBytes, state->totBytes, + state->completionEvent ? + state->completionEvent->scheduled() : 0); + + assert(pendingCount != 0); + pendingCount--; + + // update the number of bytes received based on the request rather + // than the packet + state->numBytes += pkt->req->getSize(); + assert(state->totBytes >= state->numBytes); + + // if we have reached the total number of bytes for this DMA + // request, then signal the completion and delete the sate + if (state->totBytes == state->numBytes) { + if (state->completionEvent) { + delay += state->delay; + if (delay) + device->schedule(state->completionEvent, curTick() + delay); + else + state->completionEvent->process(); + } + delete state; + } + + // delete the request that we created and also the packet + delete pkt->req; + delete pkt; + + // we might be drained at this point, if so signal the drain event + if (pendingCount == 0 && drainEvent) { + drainEvent->process(); + drainEvent = NULL; + } +} + bool DmaHandler::recvTimingResp(PacketPtr pkt) { - if (pkt->senderState) { - DmaReqState *state; + // We shouldn't ever get a block in ownership state + assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted())); - DPRINTF(DMA, "Received response %s addr %#x size %#x\n", - pkt->cmdString(), pkt->getAddr(), pkt->req->getSize()); - state = dynamic_cast(pkt->senderState); - pendingCount--; - - assert(pendingCount >= 0); - assert(state); - - // We shouldn't ever get a block in ownership state - assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted())); - - state->numBytes += pkt->req->getSize(); - assert(state->totBytes >= state->numBytes); - if (state->totBytes == state->numBytes) { - if (state->completionEvent) { - if (state->delay) - device->schedule(state->completionEvent, - curTick() + state->delay); - else - state->completionEvent->process(); - } - delete state; - } - delete pkt->req; - delete pkt; - - if (pendingCount == 0 && drainEvent) { - drainEvent->process(); - drainEvent = NULL; - } - } else { - panic("Got packet without sender state... huh?\n"); - } + handleResp(pkt); return true; } @@ -112,8 +132,7 @@ unsigned int DmaDevice::drain(Event *de) { - unsigned int count; - count = pioPort->drain(de) + dmaPort->drain(de); + unsigned int count = pioPort->drain(de) + dmaPort->drain(de); if (count) changeState(Draining); else @@ -156,44 +175,44 @@ void DmaHandler::dmaAction(Packet::Command cmd, Addr addr, int size, - Event *event, uint8_t *data, Tick delay, - Request::Flags flag) + Event *event, uint8_t *data, Tick delay, + Request::Flags flag) { assert(device->getState() == SimObject::Running); + // one DMA request sender state for every action, that is then + // split into many requests and packets based on the block size, + // i.e. cache line size DmaReqState *reqState = new DmaReqState(event, size, delay); DPRINTF(DMA, "Starting DMA for addr: %#x size: %d sched: %d\n", addr, size, - event ? event->scheduled() : -1 ); + event ? event->scheduled() : -1); for (ChunkGenerator gen(addr, size, peerBlockSize()); !gen.done(); gen.next()) { - Request *req = new Request(gen.addr(), gen.size(), flag, masterId); - PacketPtr pkt = new Packet(req, cmd); + Request *req = new Request(gen.addr(), gen.size(), flag, masterId); + PacketPtr pkt = new Packet(req, cmd); - // Increment the data pointer on a write - if (data) - pkt->dataStatic(data + gen.complete()); + // Increment the data pointer on a write + if (data) + pkt->dataStatic(data + gen.complete()); - pkt->senderState = reqState; + pkt->senderState = reqState; - assert(pendingCount >= 0); - pendingCount++; - DPRINTF(DMA, "--Queuing DMA for addr: %#x size: %d\n", gen.addr(), - gen.size()); - queueDma(pkt); + DPRINTF(DMA, "--Queuing DMA for addr: %#x size: %d\n", gen.addr(), + gen.size()); + queueDma(pkt); } - } void -DmaHandler::queueDma(PacketPtr pkt, bool front) +DmaHandler::queueDma(PacketPtr pkt) { + transmitList.push_back(pkt); - if (front) - transmitList.push_front(pkt); - else - transmitList.push_back(pkt); + // remember that we have another packet pending + pendingCount++; + sendDma(); } @@ -230,44 +249,13 @@ } else if (state == Enums::atomic) { transmitList.pop_front(); - Tick lat; - DPRINTF(DMA, "--Sending DMA for addr: %#x size: %d\n", + DPRINTF(DMA, "Sending DMA for addr: %#x size: %d\n", pkt->req->getPaddr(), pkt->req->getSize()); - lat = sendAtomic(pkt); - assert(pkt->senderState); - DmaReqState *state = dynamic_cast(pkt->senderState); - assert(state); - state->numBytes += pkt->req->getSize(); + Tick lat = sendAtomic(pkt); - DPRINTF(DMA, "--Received response for DMA for addr: %#x size: %d nb: %d, tot: %d sched %d\n", - pkt->req->getPaddr(), pkt->req->getSize(), state->numBytes, - state->totBytes, - state->completionEvent ? state->completionEvent->scheduled() : 0 ); - - if (state->totBytes == state->numBytes) { - if (state->completionEvent) { - assert(!state->completionEvent->scheduled()); - device->schedule(state->completionEvent, - curTick() + lat + state->delay); - } - delete state; - delete pkt->req; - } - pendingCount--; - assert(pendingCount >= 0); - delete pkt; - - if (pendingCount == 0 && drainEvent) { - drainEvent->process(); - drainEvent = NULL; - } - - } else - panic("Unknown memory command state."); -} - -DmaDevice::~DmaDevice() -{ + handleResp(pkt, lat); + } else + panic("Unknown memory command state."); } BaseMasterPort &