52c52
< #include "debug/BusBridge.hh"
---
> #include "debug/Bridge.hh"
56,57c56,57
< Bridge::BridgeSlavePort::BridgeSlavePort(const std::string &_name,
< Bridge* _bridge,
---
> Bridge::BridgeSlavePort::BridgeSlavePort(const std::string& _name,
> Bridge& _bridge,
59,60c59
< int _delay, int _nack_delay,
< int _resp_limit,
---
> int _delay, int _resp_limit,
62,65c61,63
< : SlavePort(_name, _bridge), bridge(_bridge), masterPort(_masterPort),
< delay(_delay), nackDelay(_nack_delay),
< ranges(_ranges.begin(), _ranges.end()),
< outstandingResponses(0), inRetry(false),
---
> : SlavePort(_name, &_bridge), bridge(_bridge), masterPort(_masterPort),
> delay(_delay), ranges(_ranges.begin(), _ranges.end()),
> outstandingResponses(0), retryReq(false),
70,71c68,69
< Bridge::BridgeMasterPort::BridgeMasterPort(const std::string &_name,
< Bridge* _bridge,
---
> Bridge::BridgeMasterPort::BridgeMasterPort(const std::string& _name,
> Bridge& _bridge,
74,76c72,73
< : MasterPort(_name, _bridge), bridge(_bridge), slavePort(_slavePort),
< delay(_delay), inRetry(false), reqQueueLimit(_req_limit),
< sendEvent(*this)
---
> : MasterPort(_name, &_bridge), bridge(_bridge), slavePort(_slavePort),
> delay(_delay), reqQueueLimit(_req_limit), sendEvent(*this)
82,85c79,81
< slavePort(p->name + ".slave", this, masterPort, p->delay,
< p->nack_delay, p->resp_size, p->ranges),
< masterPort(p->name + ".master", this, slavePort, p->delay, p->req_size),
< ackWrites(p->write_ack), _params(p)
---
> slavePort(p->name + ".slave", *this, masterPort, p->delay, p->resp_size,
> p->ranges),
> masterPort(p->name + ".master", *this, slavePort, p->delay, p->req_size)
87,88d82
< if (ackWrites)
< panic("No support for acknowledging writes\n");
136c130
< return requestQueue.size() == reqQueueLimit;
---
> return transmitList.size() == reqQueueLimit;
144c138
< DPRINTF(BusBridge, "recvTiming: response %s addr 0x%x\n",
---
> DPRINTF(Bridge, "recvTimingResp: %s addr 0x%x\n",
147c141
< DPRINTF(BusBridge, "Request queue size: %d\n", requestQueue.size());
---
> DPRINTF(Bridge, "Request queue size: %d\n", transmitList.size());
149c143
< slavePort.queueForSendTiming(pkt);
---
> slavePort.schedTimingResp(pkt, curTick() + delay);
157c151
< DPRINTF(BusBridge, "recvTiming: request %s addr 0x%x\n",
---
> DPRINTF(Bridge, "recvTimingReq: %s addr 0x%x\n",
160,161c154,156
< DPRINTF(BusBridge, "Response queue size: %d outresp: %d\n",
< responseQueue.size(), outstandingResponses);
---
> // ensure we do not have something waiting to retry
> if(retryReq)
> return false;
163,167c158,159
< if (masterPort.reqQueueFull()) {
< DPRINTF(BusBridge, "Request queue full, nacking\n");
< nackRequest(pkt);
< return true;
< }
---
> DPRINTF(Bridge, "Response queue size: %d outresp: %d\n",
> transmitList.size(), outstandingResponses);
169c161,164
< if (pkt->needsResponse()) {
---
> if (masterPort.reqQueueFull()) {
> DPRINTF(Bridge, "Request queue full\n");
> retryReq = true;
> } else if (pkt->needsResponse()) {
171,177c166,167
< DPRINTF(BusBridge,
< "Response queue full, no space for response, nacking\n");
< DPRINTF(BusBridge,
< "queue size: %d outstanding resp: %d\n",
< responseQueue.size(), outstandingResponses);
< nackRequest(pkt);
< return true;
---
> DPRINTF(Bridge, "Response queue full\n");
> retryReq = true;
179c169
< DPRINTF(BusBridge, "Request Needs response, reserving space\n");
---
> DPRINTF(Bridge, "Reserving space for response\n");
181a172,173
> retryReq = false;
> masterPort.schedTimingReq(pkt, curTick() + delay);
185,187c177,181
< masterPort.queueForSendTiming(pkt);
<
< return true;
---
> // remember that we are now stalling a packet and that we have to
> // tell the sending master to retry once space becomes available,
> // we make no distinction whether the stalling is due to the
> // request queue or response queue being full
> return !retryReq;
191c185
< Bridge::BridgeSlavePort::nackRequest(PacketPtr pkt)
---
> Bridge::BridgeSlavePort::retryStalledReq()
193,212c187,190
< // Nack the packet
< pkt->makeTimingResponse();
< pkt->setNacked();
<
< // The Nack packets are stored in the response queue just like any
< // other response, but they do not occupy any space as this is
< // tracked by the outstandingResponses, this guarantees space for
< // the Nack packets, but implicitly means we have an (unrealistic)
< // unbounded Nack queue.
<
< // put it on the list to send
< Tick readyTime = curTick() + nackDelay;
< DeferredResponse resp(pkt, readyTime, true);
<
< // nothing on the list, add it and we're done
< if (responseQueue.empty()) {
< assert(!sendEvent.scheduled());
< bridge->schedule(sendEvent, readyTime);
< responseQueue.push_back(resp);
< return;
---
> if (retryReq) {
> DPRINTF(Bridge, "Request waiting for retry, now retrying\n");
> retryReq = false;
> sendRetry();
214,238d191
<
< assert(sendEvent.scheduled() || inRetry);
<
< // does it go at the end?
< if (readyTime >= responseQueue.back().ready) {
< responseQueue.push_back(resp);
< return;
< }
<
< // ok, somewhere in the middle, fun
< std::list<DeferredResponse>::iterator i = responseQueue.begin();
< std::list<DeferredResponse>::iterator end = responseQueue.end();
< std::list<DeferredResponse>::iterator begin = responseQueue.begin();
< bool done = false;
<
< while (i != end && !done) {
< if (readyTime < (*i).ready) {
< if (i == begin)
< bridge->reschedule(sendEvent, readyTime);
< responseQueue.insert(i, resp);
< done = true;
< }
< i++;
< }
< assert(done);
242c195
< Bridge::BridgeMasterPort::queueForSendTiming(PacketPtr pkt)
---
> Bridge::BridgeMasterPort::schedTimingReq(PacketPtr pkt, Tick when)
244,245d196
< Tick readyTime = curTick() + delay;
<
260,261c211,212
< if (requestQueue.empty()) {
< bridge->schedule(sendEvent, readyTime);
---
> if (transmitList.empty()) {
> bridge.schedule(sendEvent, when);
264c215
< assert(requestQueue.size() != reqQueueLimit);
---
> assert(transmitList.size() != reqQueueLimit);
266c217
< requestQueue.push_back(DeferredRequest(pkt, readyTime));
---
> transmitList.push_back(DeferredPacket(pkt, when));
271c222
< Bridge::BridgeSlavePort::queueForSendTiming(PacketPtr pkt)
---
> Bridge::BridgeSlavePort::schedTimingResp(PacketPtr pkt, Tick when)
280a232
> delete req_state;
285,286c237
< DPRINTF(BusBridge, "response, new dest %d\n", pkt->getDest());
< delete req_state;
---
> DPRINTF(Bridge, "response, new dest %d\n", pkt->getDest());
288,289d238
< Tick readyTime = curTick() + delay;
<
294,295c243,244
< if (responseQueue.empty()) {
< bridge->schedule(sendEvent, readyTime);
---
> if (transmitList.empty()) {
> bridge.schedule(sendEvent, when);
297c246,247
< responseQueue.push_back(DeferredResponse(pkt, readyTime));
---
>
> transmitList.push_back(DeferredPacket(pkt, when));
301c251
< Bridge::BridgeMasterPort::trySend()
---
> Bridge::BridgeMasterPort::trySendTiming()
303c253
< assert(!requestQueue.empty());
---
> assert(!transmitList.empty());
305c255
< DeferredRequest req = requestQueue.front();
---
> DeferredPacket req = transmitList.front();
307c257
< assert(req.ready <= curTick());
---
> assert(req.tick <= curTick());
311c261,262
< DPRINTF(BusBridge, "trySend request: addr 0x%x\n", pkt->getAddr());
---
> DPRINTF(Bridge, "trySend request addr 0x%x, queue size %d\n",
> pkt->getAddr(), transmitList.size());
315c266,267
< requestQueue.pop_front();
---
> transmitList.pop_front();
> DPRINTF(Bridge, "trySend request successful\n");
318,322c270,274
< if (!requestQueue.empty()) {
< req = requestQueue.front();
< DPRINTF(BusBridge, "Scheduling next send\n");
< bridge->schedule(sendEvent,
< std::max(req.ready, curTick() + 1));
---
> if (!transmitList.empty()) {
> req = transmitList.front();
> DPRINTF(Bridge, "Scheduling next send\n");
> bridge.schedule(sendEvent, std::max(req.tick,
> bridge.nextCycle()));
324,325c276,281
< } else {
< inRetry = true;
---
>
> // if we have stalled a request due to a full request queue,
> // then send a retry at this point, also note that if the
> // request we stalled was waiting for the response queue
> // rather than the request queue we might stall it again
> slavePort.retryStalledReq();
328,329c284,285
< DPRINTF(BusBridge, "trySend: request queue size: %d\n",
< requestQueue.size());
---
> // if the send failed, then we try again once we receive a retry,
> // and therefore there is no need to take any action
333c289
< Bridge::BridgeSlavePort::trySend()
---
> Bridge::BridgeSlavePort::trySendTiming()
335c291
< assert(!responseQueue.empty());
---
> assert(!transmitList.empty());
337c293
< DeferredResponse resp = responseQueue.front();
---
> DeferredPacket resp = transmitList.front();
339c295
< assert(resp.ready <= curTick());
---
> assert(resp.tick <= curTick());
343,344c299,300
< DPRINTF(BusBridge, "trySend response: dest %d addr 0x%x\n",
< pkt->getDest(), pkt->getAddr());
---
> DPRINTF(Bridge, "trySend response addr 0x%x, outstanding %d\n",
> pkt->getAddr(), outstandingResponses);
346,347d301
< bool was_nacked_here = resp.nackedHere;
<
349d302
< DPRINTF(BusBridge, " successful\n");
351c304,305
< responseQueue.pop_front();
---
> transmitList.pop_front();
> DPRINTF(Bridge, "trySend response successful\n");
353,356c307,308
< if (!was_nacked_here) {
< assert(outstandingResponses != 0);
< --outstandingResponses;
< }
---
> assert(outstandingResponses != 0);
> --outstandingResponses;
359,363c311,315
< if (!responseQueue.empty()) {
< resp = responseQueue.front();
< DPRINTF(BusBridge, "Scheduling next send\n");
< bridge->schedule(sendEvent,
< std::max(resp.ready, curTick() + 1));
---
> if (!transmitList.empty()) {
> resp = transmitList.front();
> DPRINTF(Bridge, "Scheduling next send\n");
> bridge.schedule(sendEvent, std::max(resp.tick,
> bridge.nextCycle()));
365,367c317,325
< } else {
< DPRINTF(BusBridge, " unsuccessful\n");
< inRetry = true;
---
>
> // if there is space in the request queue and we were stalling
> // a request, it will definitely be possible to accept it now
> // since there is guaranteed space in the response queue
> if (!masterPort.reqQueueFull() && retryReq) {
> DPRINTF(Bridge, "Request waiting for retry, now retrying\n");
> retryReq = false;
> sendRetry();
> }
370,371c328,329
< DPRINTF(BusBridge, "trySend: queue size: %d outstanding resp: %d\n",
< responseQueue.size(), outstandingResponses);
---
> // if the send failed, then we try again once we receive a retry,
> // and therefore there is no need to take any action
377,378c335
< inRetry = false;
< Tick nextReady = requestQueue.front().ready;
---
> Tick nextReady = transmitList.front().tick;
380c337
< trySend();
---
> trySendTiming();
382c339
< bridge->schedule(sendEvent, nextReady);
---
> bridge.schedule(sendEvent, nextReady);
388,389c345
< inRetry = false;
< Tick nextReady = responseQueue.front().ready;
---
> Tick nextReady = transmitList.front().tick;
391c347
< trySend();
---
> trySendTiming();
393c349
< bridge->schedule(sendEvent, nextReady);
---
> bridge.schedule(sendEvent, nextReady);
405c361
< std::list<DeferredResponse>::iterator i;
---
> std::list<DeferredPacket>::iterator i;
410c366
< for (i = responseQueue.begin(); i != responseQueue.end(); ++i) {
---
> for (i = transmitList.begin(); i != transmitList.end(); ++i) {
432c388
< std::list<DeferredRequest>::iterator i = requestQueue.begin();
---
> std::list<DeferredPacket>::iterator i = transmitList.begin();
434c390
< while(i != requestQueue.end() && !found) {
---
> while(i != transmitList.end() && !found) {