summaryrefslogtreecommitdiff
path: root/src/mem/bridge.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/bridge.cc')
-rw-r--r--src/mem/bridge.cc93
1 files changed, 44 insertions, 49 deletions
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc
index 736e8dc81..5b8b9164b 100644
--- a/src/mem/bridge.cc
+++ b/src/mem/bridge.cc
@@ -90,7 +90,17 @@ Bridge::BridgePort::recvTiming(Packet *pkt)
DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr());
- if (pkt->isResponse()) {
+ return otherPort->queueForSendTiming(pkt);
+}
+
+
+bool
+Bridge::BridgePort::queueForSendTiming(Packet *pkt)
+{
+ if (queueFull())
+ return false;
+
+ if (pkt->isResponse()) {
// This is a response for a request we forwarded earlier. The
// corresponding PacketBuffer should be stored in the packet's
// senderState field.
@@ -99,22 +109,16 @@ Bridge::BridgePort::recvTiming(Packet *pkt)
// set up new packet dest & senderState based on values saved
// from original request
buf->fixResponse(pkt);
+ DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n",
+ pkt->senderState, buf);
DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
delete buf;
}
- return otherPort->queueForSendTiming(pkt);
-}
-
-
-bool
-Bridge::BridgePort::queueForSendTiming(Packet *pkt)
-{
- if (queueFull())
- return false;
-
Tick readyTime = curTick + delay;
PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
+ DPRINTF(BusBridge, "old sender state: %#X, new sender state: %#X\n",
+ buf->origSenderState, buf);
// If we're about to put this packet at the head of the queue, we
// need to schedule an event to do the transmit. Otherwise there
@@ -126,43 +130,16 @@ Bridge::BridgePort::queueForSendTiming(Packet *pkt)
sendQueue.push_back(buf);
- // Did we just become blocked? If yes, let other side know.
- if (queueFull())
- otherPort->sendStatusChange(Port::Blocked);
-
return true;
}
-
-void
-Bridge::BridgePort::finishSend(PacketBuffer *buf)
-{
- if (buf->expectResponse) {
- // Must wait for response. We just need to count outstanding
- // responses (in case we want to cap them); PacketBuffer
- // pointer will be recovered on response.
- ++outstandingResponses;
- DPRINTF(BusBridge, " successful: awaiting response (%d)\n",
- outstandingResponses);
- } else {
- // no response expected... deallocate packet buffer now.
- DPRINTF(BusBridge, " successful: no response expected\n");
- delete buf;
- }
-
- // If there are more packets to send, schedule event to try again.
- if (!sendQueue.empty()) {
- buf = sendQueue.front();
- sendEvent.schedule(std::max(buf->ready, curTick + 1));
- }
-}
-
-
void
Bridge::BridgePort::trySend()
{
assert(!sendQueue.empty());
+ bool was_full = queueFull();
+
PacketBuffer *buf = sendQueue.front();
assert(buf->ready <= curTick);
@@ -176,20 +153,41 @@ Bridge::BridgePort::trySend()
// send successful
sendQueue.pop_front();
buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
- finishSend(buf);
+
+ if (buf->expectResponse) {
+ // Must wait for response. We just need to count outstanding
+ // responses (in case we want to cap them); PacketBuffer
+ // pointer will be recovered on response.
+ ++outstandingResponses;
+ DPRINTF(BusBridge, " successful: awaiting response (%d)\n",
+ outstandingResponses);
+ } else {
+ // no response expected... deallocate packet buffer now.
+ DPRINTF(BusBridge, " successful: no response expected\n");
+ delete buf;
+ }
+
+ // If there are more packets to send, schedule event to try again.
+ if (!sendQueue.empty()) {
+ buf = sendQueue.front();
+ sendEvent.schedule(std::max(buf->ready, curTick + 1));
+ }
+ // Let things start sending again
+ if (was_full) {
+ DPRINTF(BusBridge, "Queue was full, sending retry\n");
+ otherPort->sendRetry();
+ }
+
} else {
DPRINTF(BusBridge, " unsuccessful\n");
}
}
-Packet *
+void
Bridge::BridgePort::recvRetry()
{
- PacketBuffer *buf = sendQueue.front();
- Packet *pkt = buf->pkt;
- finishSend(buf);
- return pkt;
+ trySend();
}
/** Function called by the port when the bus is receiving a Atomic
@@ -223,9 +221,6 @@ Bridge::BridgePort::recvFunctional(Packet *pkt)
void
Bridge::BridgePort::recvStatusChange(Port::Status status)
{
- if (status == Port::Blocked || status == Port::Unblocked)
- return;
-
otherPort->sendStatusChange(status);
}