1 2/* 3 * Copyright (c) 2006 The Regents of The University of Michigan 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Ali Saidi 30 * Steve Reinhardt 31 */ 32 33/** 34 * @file 35 * Definition of a simple bus bridge without buffering. 36 */ 37 38#include <algorithm> 39 40#include "base/range_ops.hh" 41#include "base/trace.hh" 42#include "mem/bridge.hh" 43#include "params/Bridge.hh" 44 45Bridge::BridgePort::BridgePort(const std::string &_name, 46 Bridge *_bridge, BridgePort *_otherPort, 47 int _delay, int _nack_delay, int _req_limit, 48 int _resp_limit, 49 std::vector<Range<Addr> > filter_ranges) 50 : Port(_name, _bridge), bridge(_bridge), otherPort(_otherPort), 51 delay(_delay), nackDelay(_nack_delay), filterRanges(filter_ranges), 52 outstandingResponses(0), queuedRequests(0), inRetry(false), 53 reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this) 54{ 55} 56 57Bridge::Bridge(Params *p) 58 : MemObject(p), 59 portA(p->name + "-portA", this, &portB, p->delay, p->nack_delay, 60 p->req_size_a, p->resp_size_a, p->filter_ranges_a), 61 portB(p->name + "-portB", this, &portA, p->delay, p->nack_delay, 62 p->req_size_b, p->resp_size_b, p->filter_ranges_b), 63 ackWrites(p->write_ack), _params(p) 64{ 65 if (ackWrites) 66 panic("No support for acknowledging writes\n"); 67} 68 69Port * 70Bridge::getPort(const std::string &if_name, int idx) 71{ 72 BridgePort *port; 73 74 if (if_name == "side_a") 75 port = &portA; 76 else if (if_name == "side_b") 77 port = &portB; 78 else 79 return NULL; 80 81 if (port->getPeer() != NULL && !port->getPeer()->isDefaultPort()) 82 panic("bridge side %s already connected to %s.", 83 if_name, port->getPeer()->name()); 84 return port; 85} 86 87 88void 89Bridge::init() 90{ 91 // Make sure that both sides are connected to. 92 if (!portA.isConnected() || !portB.isConnected()) 93 fatal("Both ports of bus bridge are not connected to a bus.\n"); 94 95 if (portA.peerBlockSize() != portB.peerBlockSize()) 96 fatal("port A size %d, port B size %d \n " \ 97 "Busses don't have the same block size... Not supported.\n", 98 portA.peerBlockSize(), portB.peerBlockSize()); 99} 100 101bool 102Bridge::BridgePort::respQueueFull() 103{ 104 assert(outstandingResponses >= 0 && outstandingResponses <= respQueueLimit); 105 return outstandingResponses >= respQueueLimit; 106} 107 108bool 109Bridge::BridgePort::reqQueueFull() 110{ 111 assert(queuedRequests >= 0 && queuedRequests <= reqQueueLimit); 112 return queuedRequests >= reqQueueLimit; 113} 114 115/** Function called by the port when the bus is receiving a Timing 116 * transaction.*/ 117bool 118Bridge::BridgePort::recvTiming(PacketPtr pkt) 119{ 120 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", 121 pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 122 123 DPRINTF(BusBridge, "Local queue size: %d outreq: %d outresp: %d\n", 124 sendQueue.size(), queuedRequests, outstandingResponses); 125 DPRINTF(BusBridge, "Remote queue size: %d outreq: %d outresp: %d\n", 126 otherPort->sendQueue.size(), otherPort->queuedRequests, 127 otherPort->outstandingResponses); 128 129 if (pkt->isRequest() && otherPort->reqQueueFull()) { 130 DPRINTF(BusBridge, "Remote queue full, nacking\n"); 131 nackRequest(pkt); 132 return true; 133 } 134 135 if (pkt->needsResponse()) { 136 if (respQueueFull()) { 137 DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n"); 138 DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n", 139 sendQueue.size(), queuedRequests, outstandingResponses); 140 nackRequest(pkt); 141 return true; 142 } else { 143 DPRINTF(BusBridge, "Request Needs response, reserving space\n"); 144 ++outstandingResponses; 145 } 146 } 147 148 otherPort->queueForSendTiming(pkt); 149 150 return true; 151} 152 153void 154Bridge::BridgePort::nackRequest(PacketPtr pkt) 155{ 156 // Nack the packet 157 pkt->makeTimingResponse(); 158 pkt->setNacked(); 159 160 //put it on the list to send
|