bool
Bridge::BridgePort::recvTiming(PacketPtr pkt)
{
- if (!(pkt->flags & SNOOP_COMMIT))
- return true;
-
-
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->wasNacked()) {
DPRINTF(BusBridge, "Remote queue full, nacking\n");
nackRequest(pkt);
return true;
}
- if (pkt->needsResponse() && pkt->result != Packet::Nacked)
+ if (pkt->needsResponse() && !pkt->wasNacked())
if (respQueueFull()) {
DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n");
DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n",
Bridge::BridgePort::nackRequest(PacketPtr pkt)
{
// Nack the packet
- pkt->result = Packet::Nacked;
+ pkt->setNacked();
pkt->setDest(pkt->getSrc());
//put it on the list to send
void
Bridge::BridgePort::queueForSendTiming(PacketPtr pkt)
{
- if (pkt->isResponse() || pkt->result == Packet::Nacked) {
+ if (pkt->isResponse() || pkt->wasNacked()) {
// This is a response for a request we forwarded earlier. The
// corresponding PacketBuffer should be stored in the packet's
// senderState field.
// 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->wasNacked())
--outstandingResponses;
-
- DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n",
- pkt->senderState, buf);
- DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
+ DPRINTF(BusBridge, "response, new dest %d\n", pkt->getDest());
delete buf;
}
+
+ if (pkt->isRequest() && !pkt->wasNacked()) {
+ ++queuedRequests;
+ }
+
+
+
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
if (sendQueue.empty()) {
sendEvent.schedule(readyTime);
}
- ++queuedRequests;
sendQueue.push_back(buf);
}
{
assert(!sendQueue.empty());
- int pbs = peerBlockSize();
-
PacketBuffer *buf = sendQueue.front();
assert(buf->ready <= curTick);
PacketPtr pkt = buf->pkt;
- pkt->flags &= ~SNOOP_COMMIT; //CLear it if it was set
-
+ // Ugly! @todo When multilevel coherence works this will be removed
if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite &&
- pkt->result != Packet::Nacked && pkt->getOffset(pbs) &&
- pkt->getSize() != pbs) {
- buf->partialWriteFix(this);
- pkt = buf->pkt;
+ !pkt->wasNacked()) {
+ PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq,
+ Packet::Broadcast);
+ funcPkt->dataStatic(pkt->getPtr<uint8_t>());
+ sendFunctional(funcPkt);
+ pkt->cmd = MemCmd::WriteReq;
+ delete funcPkt;
}
DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
buf->origSrc, pkt->getDest(), pkt->getAddr());
+ bool wasReq = pkt->isRequest();
+ bool wasNacked = pkt->wasNacked();
if (sendTiming(pkt)) {
// send successful
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()) {
}
} else {
DPRINTF(BusBridge, " unsuccessful\n");
- buf->undoPartialWriteFix();
inRetry = true;
}
DPRINTF(BusBridge, "trySend: queue size: %d outreq: %d outstanding resp: %d\n",
Tick
Bridge::BridgePort::recvAtomic(PacketPtr pkt)
{
- return otherPort->sendAtomic(pkt) + delay;
+ // fix partial atomic writes... similar to the timing code that does the
+ // same... will be removed once our code gets this right
+ if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite) {
+
+ PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq,
+ Packet::Broadcast);
+ funcPkt->dataStatic(pkt->getPtr<uint8_t>());
+ otherPort->sendFunctional(funcPkt);
+ delete funcPkt;
+ pkt->cmd = MemCmd::WriteReq;
+ }
+ return delay + otherPort->sendAtomic(pkt);
}
/** Function called by the port when the bus is receiving a Functional
Bridge::BridgePort::recvFunctional(PacketPtr pkt)
{
std::list<PacketBuffer*>::iterator i;
- bool pktContinue = true;
for (i = sendQueue.begin(); i != sendQueue.end(); ++i) {
- if (pkt->intersect((*i)->pkt)) {
- pktContinue &= fixPacket(pkt, (*i)->pkt);
- }
+ if (pkt->checkFunctional((*i)->pkt))
+ return;
}
- if (pktContinue) {
- otherPort->sendFunctional(pkt);
- }
+ // fall through if pkt still not satisfied
+ otherPort->sendFunctional(pkt);
}
/** Function called by the port when the bus is receiving a status change.*/
void
Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
- AddrRangeList &snoop)
+ bool &snoop)
{
otherPort->getPeerAddressRanges(resp, snoop);
+ // we don't allow snooping across bridges
+ snoop = false;
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge)
REGISTER_SIM_OBJECT("Bridge", Bridge)
+