33a34
> #include <algorithm>
38a40,75
> Bridge::BridgePort::BridgePort(const std::string &_name,
> Bridge *_bridge, BridgePort *_otherPort,
> int _delay, int _queueLimit)
> : Port(_name), bridge(_bridge), otherPort(_otherPort),
> delay(_delay), outstandingResponses(0),
> queueLimit(_queueLimit), sendEvent(this)
> {
> }
>
> Bridge::Bridge(const std::string &n, int qsa, int qsb,
> Tick _delay, int write_ack)
> : MemObject(n),
> portA(n + "-portA", this, &portB, _delay, qsa),
> portB(n + "-portB", this, &portA, _delay, qsa),
> ackWrites(write_ack)
> {
> }
>
> Port *
> Bridge::getPort(const std::string &if_name)
> {
> BridgePort *port;
>
> if (if_name == "side_a")
> port = &portA;
> else if (if_name == "side_b")
> port = &portB;
> else
> return NULL;
>
> if (port->getPeer() != NULL)
> panic("bridge side %s already connected to.", if_name);
> return port;
> }
>
>
43c80
< if (sideA == NULL || sideB == NULL)
---
> if (portA.getPeer() == NULL || portB.getPeer() == NULL)
48c85
< /** Function called by the port when the bus is recieving a Timing
---
> /** Function called by the port when the bus is receiving a Timing
51c88
< Bridge::recvTiming(Packet *pkt, Side id)
---
> Bridge::BridgePort::recvTiming(Packet *pkt)
53,56c90,91
< if (blockedA && id == SideA)
< return false;
< if (blockedB && id == SideB)
< return false;
---
> DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
> pkt->getSrc(), pkt->getDest(), pkt->getAddr());
58,75c93,103
< if (delay) {
< if (!sendEvent.scheduled())
< sendEvent.schedule(curTick + delay);
< if (id == SideA) {
< inboundA.push_back(std::make_pair<Packet*, Tick>(pkt, curTick));
< blockCheck(SideA);
< } else {
< inboundB.push_back(std::make_pair<Packet*, Tick>(pkt, curTick));
< blockCheck(SideB);
< }
< } else {
< if (id == SideB) {
< sideA->sendPkt(pkt);
< blockCheck(SideB);
< } else {
< sideB->sendPkt(pkt);
< blockCheck(SideA);
< }
---
> 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.
> PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState);
> assert(buf != NULL);
> // set up new packet dest & senderState based on values saved
> // from original request
> buf->fixResponse(pkt);
> DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
> delete buf;
77d104
< return true;
78a106
> return otherPort->queueForSendTiming(pkt);
81,102d108
< void
< Bridge::blockCheck(Side id)
< {
< /* Check that we still have buffer space available. */
< if (id == SideB) {
< if (sideA->numQueued() + inboundB.size() >= queueSizeA && !blockedB) {
< sideB->sendStatusChange(Port::Blocked);
< blockedB = true;
< } else if (sideA->numQueued() + inboundB.size() < queueSizeA && blockedB) {
< sideB->sendStatusChange(Port::Unblocked);
< blockedB = false;
< }
< } else {
< if (sideB->numQueued() + inboundA.size() >= queueSizeB && !blockedA) {
< sideA->sendStatusChange(Port::Blocked);
< blockedA = true;
< } else if (sideB->numQueued() + inboundA.size() < queueSizeB && blockedA) {
< sideA->sendStatusChange(Port::Unblocked);
< blockedA = false;
< }
< }
< }
104c110,111
< void Bridge::timerEvent()
---
> bool
> Bridge::BridgePort::queueForSendTiming(Packet *pkt)
106c113,114
< Tick t = 0;
---
> if (queueFull())
> return false;
108,115c116,124
< assert(inboundA.size() || inboundB.size());
< if (inboundA.size()) {
< while (inboundA.front().second <= curTick + delay){
< sideB->sendPkt(inboundA.front());
< inboundA.pop_front();
< }
< if (inboundA.size())
< t = inboundA.front().second + delay;
---
> Tick readyTime = curTick + delay;
> PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
>
> // 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
> // should already be an event scheduled for sending the head
> // packet.
> if (sendQueue.empty()) {
> sendEvent.schedule(readyTime);
117,129d125
< if (inboundB.size()) {
< while (inboundB.front().second <= curTick + delay){
< sideB->sendPkt(inboundA.front());
< inboundB.pop_front();
< }
< if (inboundB.size())
< if (t == 0)
< t = inboundB.front().second + delay;
< else
< t = std::min(t,inboundB.front().second + delay);
< } else {
< panic("timerEvent() called but nothing to do?");
< }
131,132c127,133
< if (t != 0)
< sendEvent.schedule(t);
---
> sendQueue.push_back(buf);
>
> // Did we just become blocked? If yes, let other side know.
> if (queueFull())
> otherPort->sendStatusChange(Port::Blocked);
>
> return true;
137c138
< Bridge::BridgePort::sendPkt(Packet *pkt)
---
> Bridge::BridgePort::finishSend(PacketBuffer *buf)
139,140c140,157
< if (!sendTiming(pkt))
< outbound.push_back(std::make_pair<Packet*,Tick>(pkt, curTick));
---
> 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));
> }
142a160
>
144c162
< Bridge::BridgePort::sendPkt(std::pair<Packet*, Tick> p)
---
> Bridge::BridgePort::trySend()
146,147c164,182
< if (!sendTiming(p.first))
< outbound.push_back(p);
---
> assert(!sendQueue.empty());
>
> PacketBuffer *buf = sendQueue.front();
>
> assert(buf->ready <= curTick);
>
> Packet *pkt = buf->pkt;
>
> DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
> buf->origSrc, pkt->getDest(), pkt->getAddr());
>
> if (sendTiming(pkt)) {
> // send successful
> sendQueue.pop_front();
> buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
> finishSend(buf);
> } else {
> DPRINTF(BusBridge, " unsuccessful\n");
> }
154,159c189,191
< Packet *pkt;
< assert(outbound.size() > 0);
< assert(outbound.front().second >= curTick + bridge->delay);
< pkt = outbound.front().first;
< outbound.pop_front();
< bridge->blockCheck(side);
---
> PacketBuffer *buf = sendQueue.front();
> Packet *pkt = buf->pkt;
> finishSend(buf);
163c195
< /** Function called by the port when the bus is recieving a Atomic
---
> /** Function called by the port when the bus is receiving a Atomic
166c198
< Bridge::recvAtomic(Packet *pkt, Side id)
---
> Bridge::BridgePort::recvAtomic(Packet *pkt)
168,173c200
< pkt->time += delay;
<
< if (id == SideA)
< return sideB->sendAtomic(pkt);
< else
< return sideA->sendAtomic(pkt);
---
> return otherPort->sendAtomic(pkt) + delay;
176c203
< /** Function called by the port when the bus is recieving a Functional
---
> /** Function called by the port when the bus is receiving a Functional
179c206
< Bridge::recvFunctional(Packet *pkt, Side id)
---
> Bridge::BridgePort::recvFunctional(Packet *pkt)
181,182c208
< pkt->time += delay;
< std::list<std::pair<Packet*, Tick> >::iterator i;
---
> std::list<PacketBuffer*>::iterator i;
185,187c211,213
< for(i = inboundA.begin(); i != inboundA.end(); ++i) {
< if (pkt->intersect(i->first)) {
< pktContinue &= fixPacket(pkt, i->first);
---
> for (i = sendQueue.begin(); i != sendQueue.end(); ++i) {
> if (pkt->intersect((*i)->pkt)) {
> pktContinue &= fixPacket(pkt, (*i)->pkt);
191,208d216
< for(i = inboundB.begin(); i != inboundB.end(); ++i) {
< if (pkt->intersect(i->first)) {
< pktContinue &= fixPacket(pkt, i->first);
< }
< }
<
< for(i = sideA->outbound.begin(); i != sideA->outbound.end(); ++i) {
< if (pkt->intersect(i->first)) {
< pktContinue &= fixPacket(pkt, i->first);
< }
< }
<
< for(i = sideB->outbound.begin(); i != sideB->outbound.end(); ++i) {
< if (pkt->intersect(i->first)) {
< pktContinue &= fixPacket(pkt, i->first);
< }
< }
<
210,213c218
< if (id == SideA)
< sideB->sendFunctional(pkt);
< else
< sideA->sendFunctional(pkt);
---
> otherPort->sendFunctional(pkt);
217c222
< /** Function called by the port when the bus is recieving a status change.*/
---
> /** Function called by the port when the bus is receiving a status change.*/
219c224
< Bridge::recvStatusChange(Port::Status status, Side id)
---
> Bridge::BridgePort::recvStatusChange(Port::Status status)
222c227
< return ;
---
> return;
224,227c229
< if (id == SideA)
< sideB->sendStatusChange(status);
< else
< sideA->sendStatusChange(status);
---
> otherPort->sendStatusChange(status);
231c233,234
< Bridge::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id)
---
> Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
> AddrRangeList &snoop)
233,236c236
< if (id == SideA)
< sideB->getPeerAddressRanges(resp, snoop);
< else
< sideA->getPeerAddressRanges(resp, snoop);
---
> otherPort->getPeerAddressRanges(resp, snoop);