summaryrefslogtreecommitdiff
path: root/src/mem
diff options
context:
space:
mode:
authorAli Saidi <saidi@eecs.umich.edu>2007-05-13 01:44:42 -0400
committerAli Saidi <saidi@eecs.umich.edu>2007-05-13 01:44:42 -0400
commitaf26532bbd1a97a1f423c2944361290f1b696193 (patch)
tree4b03b299fc927730002c45849c6495409e345122 /src/mem
parent634d2e9d83054d2ddae4333d4e28e9a04cfbfd84 (diff)
downloadgem5-af26532bbd1a97a1f423c2944361290f1b696193.tar.xz
fix handling of atomic packets
fix up code for counting requests and responses --HG-- extra : convert_revision : 0d70981ee41c5d9c36cad01bd505281a096f6119
Diffstat (limited to 'src/mem')
-rw-r--r--src/mem/bridge.cc60
-rw-r--r--src/mem/bridge.hh5
2 files changed, 54 insertions, 11 deletions
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc
index e89473be3..f525ccb48 100644
--- a/src/mem/bridge.cc
+++ b/src/mem/bridge.cc
@@ -119,7 +119,14 @@ Bridge::BridgePort::recvTiming(PacketPtr pkt)
DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr());
- if (pkt->isRequest() && otherPort->reqQueueFull()) {
+ DPRINTF(BusBridge, "Local queue size: %d outreq: %d outresp: %d\n",
+ sendQueue.size(), queuedRequests, outstandingResponses);
+ DPRINTF(BusBridge, "Remove queue size: %d outreq: %d outresp: %d\n",
+ otherPort->sendQueue.size(), otherPort->queuedRequests,
+ otherPort->outstandingResponses);
+
+ if (pkt->isRequest() && otherPort->reqQueueFull() && pkt->result !=
+ Packet::Nacked) {
DPRINTF(BusBridge, "Remote queue full, nacking\n");
nackRequest(pkt);
return true;
@@ -191,7 +198,7 @@ Bridge::BridgePort::nackRequest(PacketPtr pkt)
void
Bridge::BridgePort::queueForSendTiming(PacketPtr pkt)
{
- if (pkt->isResponse() || pkt->result == Packet::Nacked) {
+ if (pkt->isResponse() || pkt->result == Packet::Nacked) {
// This is a response for a request we forwarded earlier. The
// corresponding PacketBuffer should be stored in the packet's
// senderState field.
@@ -201,9 +208,9 @@ Bridge::BridgePort::queueForSendTiming(PacketPtr pkt)
// from original request
buf->fixResponse(pkt);
- // Check if this packet was expecting a response (this is either it or
- // its a nacked packet and we won't be seeing that response)
- if (buf->expectResponse)
+ // Check if this packet was expecting a response and it's a nacked
+ // packet, in which case we will never being seeing it
+ if (buf->expectResponse && pkt->result == Packet::Nacked)
--outstandingResponses;
@@ -213,6 +220,13 @@ Bridge::BridgePort::queueForSendTiming(PacketPtr pkt)
delete buf;
}
+
+ if (pkt->isRequest() && pkt->result != Packet::Nacked) {
+ ++queuedRequests;
+ }
+
+
+
Tick readyTime = curTick + delay;
PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
DPRINTF(BusBridge, "old sender state: %#X, new sender state: %#X\n",
@@ -225,7 +239,6 @@ Bridge::BridgePort::queueForSendTiming(PacketPtr pkt)
if (sendQueue.empty()) {
sendEvent.schedule(readyTime);
}
- ++queuedRequests;
sendQueue.push_back(buf);
}
@@ -254,6 +267,8 @@ Bridge::BridgePort::trySend()
DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
buf->origSrc, pkt->getDest(), pkt->getAddr());
+ bool wasReq = pkt->isRequest();
+ bool wasNacked = pkt->result == Packet::Nacked;
if (sendTiming(pkt)) {
// send successful
@@ -270,8 +285,12 @@ Bridge::BridgePort::trySend()
delete buf;
}
- if (!buf->nacked)
+ if (!wasNacked) {
+ if (wasReq)
--queuedRequests;
+ else
+ --outstandingResponses;
+ }
// If there are more packets to send, schedule event to try again.
if (!sendQueue.empty()) {
@@ -305,7 +324,32 @@ Bridge::BridgePort::recvRetry()
Tick
Bridge::BridgePort::recvAtomic(PacketPtr pkt)
{
- return otherPort->sendAtomic(pkt) + delay;
+ int pbs = otherPort->peerBlockSize();
+ Tick atomic_delay;
+ // fix partial atomic writes... similar to the timing code that does the
+ // same
+ if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite &&
+ pkt->getOffset(pbs) && pkt->getSize() != pbs) {
+ PacketDataPtr data;
+ data = new uint8_t[pbs];
+ PacketPtr funcPkt = new Packet(pkt->req, MemCmd::ReadReq,
+ Packet::Broadcast, pbs);
+
+ funcPkt->dataStatic(data);
+ otherPort->sendFunctional(funcPkt);
+ assert(funcPkt->result == Packet::Success);
+ delete funcPkt;
+ memcpy(data + pkt->getOffset(pbs), pkt->getPtr<uint8_t>(),
+ pkt->getSize());
+ PacketPtr newPkt = new Packet(pkt->req, MemCmd::WriteInvalidateReq,
+ Packet::Broadcast, pbs);
+ pkt->dataDynamicArray(data);
+ atomic_delay = otherPort->sendAtomic(newPkt);
+ delete newPkt;
+ } else {
+ atomic_delay = otherPort->sendAtomic(pkt);
+ }
+ return atomic_delay + delay;
}
/** Function called by the port when the bus is receiving a Functional
diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh
index cb5a6baed..7df3c767f 100644
--- a/src/mem/bridge.hh
+++ b/src/mem/bridge.hh
@@ -82,16 +82,15 @@ class Bridge : public MemObject
bool partialWriteFixed;
PacketPtr oldPkt;
- bool nacked;
PacketBuffer(PacketPtr _pkt, Tick t, bool nack = false)
: ready(t), pkt(_pkt),
origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()),
expectResponse(_pkt->needsResponse() && !nack),
- partialWriteFixed(false), nacked(nack)
+ partialWriteFixed(false)
{
- if (!pkt->isResponse() && !nack)
+ if (!pkt->isResponse() && !nack && pkt->result != Packet::Nacked)
pkt->senderState = this;
}