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 "debug/BusBridge.hh" 43#include "mem/bridge.hh" 44#include "params/Bridge.hh" 45 46Bridge::BridgePort::BridgePort(const std::string &_name, 47 Bridge *_bridge, BridgePort *_otherPort, 48 int _delay, int _nack_delay, int _req_limit, 49 int _resp_limit, 50 std::vector<Range<Addr> > filter_ranges) 51 : Port(_name, _bridge), bridge(_bridge), otherPort(_otherPort), 52 delay(_delay), nackDelay(_nack_delay), filterRanges(filter_ranges), 53 outstandingResponses(0), queuedRequests(0), inRetry(false), 54 reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this) 55{ 56} 57 58Bridge::Bridge(Params *p) 59 : MemObject(p), 60 portA(p->name + "-portA", this, &portB, p->delay, p->nack_delay, 61 p->req_size_a, p->resp_size_a, p->filter_ranges_a), 62 portB(p->name + "-portB", this, &portA, p->delay, p->nack_delay, 63 p->req_size_b, p->resp_size_b, p->filter_ranges_b), 64 ackWrites(p->write_ack), _params(p) 65{ 66 if (ackWrites) 67 panic("No support for acknowledging writes\n"); 68} 69 70Port * 71Bridge::getPort(const std::string &if_name, int idx) 72{ 73 BridgePort *port; 74 75 if (if_name == "side_a") 76 port = &portA; 77 else if (if_name == "side_b") 78 port = &portB; 79 else 80 return NULL; 81 82 if (port->getPeer() != NULL && !port->getPeer()->isDefaultPort()) 83 panic("bridge side %s already connected to %s.", 84 if_name, port->getPeer()->name()); 85 return port; 86} 87 88 89void 90Bridge::init() 91{ 92 // Make sure that both sides are connected to. 93 if (!portA.isConnected() || !portB.isConnected()) 94 fatal("Both ports of bus bridge are not connected to a bus.\n"); 95 96 if (portA.peerBlockSize() != portB.peerBlockSize()) 97 fatal("port A size %d, port B size %d \n " \ 98 "Busses don't have the same block size... Not supported.\n", 99 portA.peerBlockSize(), portB.peerBlockSize()); 100} 101 102bool 103Bridge::BridgePort::respQueueFull() 104{ 105 assert(outstandingResponses >= 0 && outstandingResponses <= respQueueLimit); 106 return outstandingResponses >= respQueueLimit; 107} 108 109bool 110Bridge::BridgePort::reqQueueFull() 111{ 112 assert(queuedRequests >= 0 && queuedRequests <= reqQueueLimit); 113 return queuedRequests >= reqQueueLimit; 114} 115 116/** Function called by the port when the bus is receiving a Timing 117 * transaction.*/ 118bool 119Bridge::BridgePort::recvTiming(PacketPtr pkt) 120{ 121 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", 122 pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 123 124 DPRINTF(BusBridge, "Local queue size: %d outreq: %d outresp: %d\n", 125 sendQueue.size(), queuedRequests, outstandingResponses); 126 DPRINTF(BusBridge, "Remote queue size: %d outreq: %d outresp: %d\n", 127 otherPort->sendQueue.size(), otherPort->queuedRequests, 128 otherPort->outstandingResponses); 129 130 if (pkt->isRequest() && otherPort->reqQueueFull()) { 131 DPRINTF(BusBridge, "Remote queue full, nacking\n"); 132 nackRequest(pkt); 133 return true; 134 } 135 136 if (pkt->needsResponse()) { 137 if (respQueueFull()) { 138 DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n"); 139 DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n", 140 sendQueue.size(), queuedRequests, outstandingResponses); 141 nackRequest(pkt); 142 return true; 143 } else { 144 DPRINTF(BusBridge, "Request Needs response, reserving space\n"); 145 ++outstandingResponses; 146 } 147 } 148 149 otherPort->queueForSendTiming(pkt); 150 151 return true; 152} 153 154void 155Bridge::BridgePort::nackRequest(PacketPtr pkt) 156{ 157 // Nack the packet 158 pkt->makeTimingResponse(); 159 pkt->setNacked(); 160 161 //put it on the list to send 162 Tick readyTime = curTick() + nackDelay; 163 PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true); 164 165 // nothing on the list, add it and we're done 166 if (sendQueue.empty()) { 167 assert(!sendEvent.scheduled());
|