dma_device.cc (9294:8fb03b13de02) dma_device.cc (9307:98e05d58f9eb)
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 35 unchanged lines hidden (view full) ---

44
45#include "base/chunk_generator.hh"
46#include "debug/DMA.hh"
47#include "debug/Drain.hh"
48#include "dev/dma_device.hh"
49#include "sim/system.hh"
50
51DmaPort::DmaPort(MemObject *dev, System *s)
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 35 unchanged lines hidden (view full) ---

44
45#include "base/chunk_generator.hh"
46#include "debug/DMA.hh"
47#include "debug/Drain.hh"
48#include "dev/dma_device.hh"
49#include "sim/system.hh"
50
51DmaPort::DmaPort(MemObject *dev, System *s)
52 : MasterPort(dev->name() + ".dma", dev), device(dev), sys(s),
53 masterId(s->getMasterId(dev->name())),
52 : MasterPort(dev->name() + ".dma", dev), device(dev), sendEvent(this),
53 sys(s), masterId(s->getMasterId(dev->name())),
54 pendingCount(0), drainEvent(NULL),
55 inRetry(false)
56{ }
57
58void
59DmaPort::handleResp(PacketPtr pkt, Tick delay)
60{
61 // should always see a response with a sender state

--- 85 unchanged lines hidden (view full) ---

147 DPRINTF(Drain, "DmaPort not drained\n");
148 return 1;
149}
150
151void
152DmaPort::recvRetry()
153{
154 assert(transmitList.size());
54 pendingCount(0), drainEvent(NULL),
55 inRetry(false)
56{ }
57
58void
59DmaPort::handleResp(PacketPtr pkt, Tick delay)
60{
61 // should always see a response with a sender state

--- 85 unchanged lines hidden (view full) ---

147 DPRINTF(Drain, "DmaPort not drained\n");
148 return 1;
149}
150
151void
152DmaPort::recvRetry()
153{
154 assert(transmitList.size());
155 bool result = true;
156 do {
157 PacketPtr pkt = transmitList.front();
158 DPRINTF(DMA, "Retry on %s addr %#x\n",
159 pkt->cmdString(), pkt->getAddr());
160 result = sendTimingReq(pkt);
161 if (result) {
162 DPRINTF(DMA, "-- Done\n");
163 transmitList.pop_front();
164 inRetry = false;
165 } else {
166 inRetry = true;
167 DPRINTF(DMA, "-- Failed, queued\n");
168 }
169 } while (result && transmitList.size());
170
171 DPRINTF(DMA, "TransmitList: %d, inRetry: %d\n",
172 transmitList.size(), inRetry);
155 trySendTimingReq();
173}
174
175void
176DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
177 uint8_t *data, Tick delay, Request::Flags flag)
178{
179 // one DMA request sender state for every action, that is then
180 // split into many requests and packets based on the block size,

--- 12 unchanged lines hidden (view full) ---

193 pkt->dataStatic(data + gen.complete());
194
195 pkt->senderState = reqState;
196
197 DPRINTF(DMA, "--Queuing DMA for addr: %#x size: %d\n", gen.addr(),
198 gen.size());
199 queueDma(pkt);
200 }
156}
157
158void
159DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
160 uint8_t *data, Tick delay, Request::Flags flag)
161{
162 // one DMA request sender state for every action, that is then
163 // split into many requests and packets based on the block size,

--- 12 unchanged lines hidden (view full) ---

176 pkt->dataStatic(data + gen.complete());
177
178 pkt->senderState = reqState;
179
180 DPRINTF(DMA, "--Queuing DMA for addr: %#x size: %d\n", gen.addr(),
181 gen.size());
182 queueDma(pkt);
183 }
184
185 // in zero time also initiate the sending of the packets we have
186 // just created, for atomic this involves actually completing all
187 // the requests
188 sendDma();
201}
202
203void
204DmaPort::queueDma(PacketPtr pkt)
205{
206 transmitList.push_back(pkt);
207
208 // remember that we have another packet pending, this will only be
209 // decremented once a response comes back
210 pendingCount++;
189}
190
191void
192DmaPort::queueDma(PacketPtr pkt)
193{
194 transmitList.push_back(pkt);
195
196 // remember that we have another packet pending, this will only be
197 // decremented once a response comes back
198 pendingCount++;
199}
211
200
212 sendDma();
201void
202DmaPort::trySendTimingReq()
203{
204 // send the first packet on the transmit list and schedule the
205 // following send if it is successful
206 PacketPtr pkt = transmitList.front();
207
208 DPRINTF(DMA, "Trying to send %s addr %#x\n", pkt->cmdString(),
209 pkt->getAddr());
210
211 inRetry = !sendTimingReq(pkt);
212 if (!inRetry) {
213 transmitList.pop_front();
214 DPRINTF(DMA, "-- Done\n");
215 // if there is more to do, then do so
216 if (!transmitList.empty())
217 // this should ultimately wait for as many cycles as the
218 // device needs to send the packet, but currently the port
219 // does not have any known width so simply wait a single
220 // cycle
221 device->schedule(sendEvent, device->clockEdge(Cycles(1)));
222 } else {
223 DPRINTF(DMA, "-- Failed, waiting for retry\n");
224 }
225
226 DPRINTF(DMA, "TransmitList: %d, inRetry: %d\n",
227 transmitList.size(), inRetry);
213}
214
215void
216DmaPort::sendDma()
217{
218 // some kind of selcetion between access methods
219 // more work is going to have to be done to make
220 // switching actually work
221 assert(transmitList.size());
228}
229
230void
231DmaPort::sendDma()
232{
233 // some kind of selcetion between access methods
234 // more work is going to have to be done to make
235 // switching actually work
236 assert(transmitList.size());
222 PacketPtr pkt = transmitList.front();
223
224 Enums::MemoryMode state = sys->getMemoryMode();
225 if (state == Enums::timing) {
237
238 Enums::MemoryMode state = sys->getMemoryMode();
239 if (state == Enums::timing) {
226 if (inRetry) {
227 DPRINTF(DMA, "Can't send immediately, waiting for retry\n");
240 // if we are either waiting for a retry or are still waiting
241 // after sending the last packet, then do not proceed
242 if (inRetry || sendEvent.scheduled()) {
243 DPRINTF(DMA, "Can't send immediately, waiting to send\n");
228 return;
229 }
230
244 return;
245 }
246
231 DPRINTF(DMA, "Attempting to send %s addr %#x\n",
232 pkt->cmdString(), pkt->getAddr());
233
234 bool result;
235 do {
236 result = sendTimingReq(pkt);
237 if (result) {
238 transmitList.pop_front();
239 DPRINTF(DMA, "-- Done\n");
240 } else {
241 inRetry = true;
242 DPRINTF(DMA, "-- Failed: queued\n");
243 }
244 } while (result && transmitList.size());
247 trySendTimingReq();
245 } else if (state == Enums::atomic) {
248 } else if (state == Enums::atomic) {
246 transmitList.pop_front();
249 // send everything there is to send in zero time
250 while (!transmitList.empty()) {
251 PacketPtr pkt = transmitList.front();
252 transmitList.pop_front();
247
253
248 DPRINTF(DMA, "Sending DMA for addr: %#x size: %d\n",
249 pkt->req->getPaddr(), pkt->req->getSize());
250 Tick lat = sendAtomic(pkt);
254 DPRINTF(DMA, "Sending DMA for addr: %#x size: %d\n",
255 pkt->req->getPaddr(), pkt->req->getSize());
256 Tick lat = sendAtomic(pkt);
251
257
252 handleResp(pkt, lat);
258 handleResp(pkt, lat);
259 }
253 } else
254 panic("Unknown memory mode.");
255}
256
257BaseMasterPort &
258DmaDevice::getMasterPort(const std::string &if_name, PortID idx)
259{
260 if (if_name == "dma") {
261 return dmaPort;
262 }
263 return PioDevice::getMasterPort(if_name, idx);
264}
260 } else
261 panic("Unknown memory mode.");
262}
263
264BaseMasterPort &
265DmaDevice::getMasterPort(const std::string &if_name, PortID idx)
266{
267 if (if_name == "dma") {
268 return dmaPort;
269 }
270 return PioDevice::getMasterPort(if_name, idx);
271}