diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/bridge.cc | 60 | ||||
-rw-r--r-- | src/mem/bridge.hh | 25 | ||||
-rw-r--r-- | src/mem/cache/cache_impl.hh | 6 |
3 files changed, 70 insertions, 21 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..5951eeb98 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; } @@ -109,18 +108,24 @@ class Bridge : public MemObject assert(!partialWriteFixed); assert(expectResponse); - int pbs = port->peerBlockSize(); + Addr pbs = port->peerBlockSize(); + Addr blockAddr = pkt->getAddr() & ~(pbs-1); partialWriteFixed = true; PacketDataPtr data; data = new uint8_t[pbs]; - PacketPtr funcPkt = new Packet(pkt->req, MemCmd::ReadReq, - Packet::Broadcast, pbs); - - funcPkt->dataStatic(data); - port->sendFunctional(funcPkt); - assert(funcPkt->result == Packet::Success); + RequestPtr funcReq = new Request(blockAddr, 4, 0); + PacketPtr funcPkt = new Packet(funcReq, MemCmd::ReadReq, + Packet::Broadcast); + for (int x = 0; x < pbs; x+=4) { + funcReq->setPhys(blockAddr + x, 4, 0); + funcPkt->reinitFromRequest(); + funcPkt->dataStatic(data + x); + port->sendFunctional(funcPkt); + assert(funcPkt->result == Packet::Success); + } delete funcPkt; + delete funcReq; oldPkt = pkt; memcpy(data + oldPkt->getOffset(pbs), pkt->getPtr<uint8_t>(), diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index f78909b8f..9b094c1e3 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -1282,9 +1282,9 @@ template<class TagStore, class Coherence> void Cache<TagStore,Coherence>::MemSidePort::recvFunctional(PacketPtr pkt) { - if (checkFunctional(pkt)) { - myCache()->probe(pkt, false, cache->cpuSidePort); - } + myCache()->probe(pkt, false, cache->cpuSidePort); + if (pkt->result != Packet::Success) + checkFunctional(pkt); } |