bridge.cc revision 8713
12568SN/A/* 28713Sandreas.hansson@arm.com * Copyright (c) 2011 ARM Limited 38713Sandreas.hansson@arm.com * All rights reserved 48713Sandreas.hansson@arm.com * 58713Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68713Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78713Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88713Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98713Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108713Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118713Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128713Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 138713Sandreas.hansson@arm.com * 142568SN/A * Copyright (c) 2006 The Regents of The University of Michigan 152568SN/A * All rights reserved. 162568SN/A * 172568SN/A * Redistribution and use in source and binary forms, with or without 182568SN/A * modification, are permitted provided that the following conditions are 192568SN/A * met: redistributions of source code must retain the above copyright 202568SN/A * notice, this list of conditions and the following disclaimer; 212568SN/A * redistributions in binary form must reproduce the above copyright 222568SN/A * notice, this list of conditions and the following disclaimer in the 232568SN/A * documentation and/or other materials provided with the distribution; 242568SN/A * neither the name of the copyright holders nor the names of its 252568SN/A * contributors may be used to endorse or promote products derived from 262568SN/A * this software without specific prior written permission. 272568SN/A * 282568SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292568SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302568SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312568SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322568SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332568SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342568SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352568SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362568SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372568SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382568SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665Ssaidi@eecs.umich.edu * 402665Ssaidi@eecs.umich.edu * Authors: Ali Saidi 412665Ssaidi@eecs.umich.edu * Steve Reinhardt 428713Sandreas.hansson@arm.com * Andreas Hansson 432568SN/A */ 442568SN/A 452568SN/A/** 462982Sstever@eecs.umich.edu * @file 478713Sandreas.hansson@arm.com * Implementation of a memory-mapped bus bridge that connects a master 488713Sandreas.hansson@arm.com * and a slave through a request and response queue. 492568SN/A */ 502568SN/A 512568SN/A#include "base/trace.hh" 528232Snate@binkert.org#include "debug/BusBridge.hh" 532568SN/A#include "mem/bridge.hh" 544762Snate@binkert.org#include "params/Bridge.hh" 552568SN/A 568713Sandreas.hansson@arm.comBridge::BridgeSlavePort::BridgeSlavePort(const std::string &_name, 578713Sandreas.hansson@arm.com Bridge* _bridge, 588713Sandreas.hansson@arm.com BridgeMasterPort* _masterPort, 598713Sandreas.hansson@arm.com int _delay, int _nack_delay, 608713Sandreas.hansson@arm.com int _resp_limit, 618713Sandreas.hansson@arm.com std::vector<Range<Addr> > _ranges) 628713Sandreas.hansson@arm.com : Port(_name, _bridge), bridge(_bridge), masterPort(_masterPort), 638713Sandreas.hansson@arm.com delay(_delay), nackDelay(_nack_delay), 648713Sandreas.hansson@arm.com ranges(_ranges.begin(), _ranges.end()), 658713Sandreas.hansson@arm.com outstandingResponses(0), inRetry(false), 668713Sandreas.hansson@arm.com respQueueLimit(_resp_limit), sendEvent(this) 678713Sandreas.hansson@arm.com{ 688713Sandreas.hansson@arm.com} 698713Sandreas.hansson@arm.com 708713Sandreas.hansson@arm.comBridge::BridgeMasterPort::BridgeMasterPort(const std::string &_name, 718713Sandreas.hansson@arm.com Bridge* _bridge, 728713Sandreas.hansson@arm.com BridgeSlavePort* _slavePort, 738713Sandreas.hansson@arm.com int _delay, int _req_limit) 748713Sandreas.hansson@arm.com : Port(_name, _bridge), bridge(_bridge), slavePort(_slavePort), 758713Sandreas.hansson@arm.com delay(_delay), inRetry(false), reqQueueLimit(_req_limit), sendEvent(this) 762643Sstever@eecs.umich.edu{ 772643Sstever@eecs.umich.edu} 782643Sstever@eecs.umich.edu 794435Ssaidi@eecs.umich.eduBridge::Bridge(Params *p) 805034Smilesck@eecs.umich.edu : MemObject(p), 818713Sandreas.hansson@arm.com slavePort(p->name + "-slave", this, &masterPort, p->delay, 828713Sandreas.hansson@arm.com p->nack_delay, p->resp_size, p->ranges), 838713Sandreas.hansson@arm.com masterPort(p->name + "-master", this, &slavePort, p->delay, p->req_size), 844435Ssaidi@eecs.umich.edu ackWrites(p->write_ack), _params(p) 852643Sstever@eecs.umich.edu{ 864432Ssaidi@eecs.umich.edu if (ackWrites) 874432Ssaidi@eecs.umich.edu panic("No support for acknowledging writes\n"); 882643Sstever@eecs.umich.edu} 892643Sstever@eecs.umich.edu 908713Sandreas.hansson@arm.comPort* 912738Sstever@eecs.umich.eduBridge::getPort(const std::string &if_name, int idx) 922643Sstever@eecs.umich.edu{ 938713Sandreas.hansson@arm.com Port* port; 942643Sstever@eecs.umich.edu 958713Sandreas.hansson@arm.com if (if_name == "slave") 968713Sandreas.hansson@arm.com port = &slavePort; 978713Sandreas.hansson@arm.com else if (if_name == "master") 988713Sandreas.hansson@arm.com port = &masterPort; 992643Sstever@eecs.umich.edu else 1002643Sstever@eecs.umich.edu return NULL; 1012643Sstever@eecs.umich.edu 1028709Sandreas.hansson@arm.com if (port->getPeer() != NULL) 1035283Sgblack@eecs.umich.edu panic("bridge side %s already connected to %s.", 1045283Sgblack@eecs.umich.edu if_name, port->getPeer()->name()); 1052643Sstever@eecs.umich.edu return port; 1062643Sstever@eecs.umich.edu} 1072643Sstever@eecs.umich.edu 1082643Sstever@eecs.umich.edu 1092568SN/Avoid 1102568SN/ABridge::init() 1112568SN/A{ 1128713Sandreas.hansson@arm.com // make sure both sides are connected and have the same block size 1138713Sandreas.hansson@arm.com if (!slavePort.isConnected() || !masterPort.isConnected()) 1144432Ssaidi@eecs.umich.edu fatal("Both ports of bus bridge are not connected to a bus.\n"); 1154432Ssaidi@eecs.umich.edu 1168713Sandreas.hansson@arm.com if (slavePort.peerBlockSize() != masterPort.peerBlockSize()) 1178713Sandreas.hansson@arm.com fatal("Slave port size %d, master port size %d \n " \ 1186764SBrad.Beckmann@amd.com "Busses don't have the same block size... Not supported.\n", 1198713Sandreas.hansson@arm.com slavePort.peerBlockSize(), masterPort.peerBlockSize()); 1208713Sandreas.hansson@arm.com 1218713Sandreas.hansson@arm.com // notify the master side of our address ranges 1228713Sandreas.hansson@arm.com slavePort.sendRangeChange(); 1232568SN/A} 1242568SN/A 1254433Ssaidi@eecs.umich.edubool 1268713Sandreas.hansson@arm.comBridge::BridgeSlavePort::respQueueFull() 1274433Ssaidi@eecs.umich.edu{ 1288713Sandreas.hansson@arm.com return outstandingResponses == respQueueLimit; 1294435Ssaidi@eecs.umich.edu} 1304435Ssaidi@eecs.umich.edu 1314435Ssaidi@eecs.umich.edubool 1328713Sandreas.hansson@arm.comBridge::BridgeMasterPort::reqQueueFull() 1334435Ssaidi@eecs.umich.edu{ 1348713Sandreas.hansson@arm.com return requestQueue.size() == reqQueueLimit; 1354433Ssaidi@eecs.umich.edu} 1362568SN/A 1372568SN/Abool 1388713Sandreas.hansson@arm.comBridge::BridgeMasterPort::recvTiming(PacketPtr pkt) 1392568SN/A{ 1408713Sandreas.hansson@arm.com // should only see responses on the master side 1418713Sandreas.hansson@arm.com assert(pkt->isResponse()); 1428713Sandreas.hansson@arm.com 1438713Sandreas.hansson@arm.com // all checks are done when the request is accepted on the slave 1448713Sandreas.hansson@arm.com // side, so we are guaranteed to have space for the response 1458713Sandreas.hansson@arm.com 1464433Ssaidi@eecs.umich.edu DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", 1478713Sandreas.hansson@arm.com pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 1482643Sstever@eecs.umich.edu 1498713Sandreas.hansson@arm.com DPRINTF(BusBridge, "Request queue size: %d\n", requestQueue.size()); 1504450Ssaidi@eecs.umich.edu 1518713Sandreas.hansson@arm.com slavePort->queueForSendTiming(pkt); 1528713Sandreas.hansson@arm.com 1538713Sandreas.hansson@arm.com return true; 1548713Sandreas.hansson@arm.com} 1558713Sandreas.hansson@arm.com 1568713Sandreas.hansson@arm.combool 1578713Sandreas.hansson@arm.comBridge::BridgeSlavePort::recvTiming(PacketPtr pkt) 1588713Sandreas.hansson@arm.com{ 1598713Sandreas.hansson@arm.com // should only see requests on the slave side 1608713Sandreas.hansson@arm.com assert(pkt->isRequest()); 1618713Sandreas.hansson@arm.com 1628713Sandreas.hansson@arm.com DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", 1638713Sandreas.hansson@arm.com pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 1648713Sandreas.hansson@arm.com 1658713Sandreas.hansson@arm.com DPRINTF(BusBridge, "Response queue size: %d outresp: %d\n", 1668713Sandreas.hansson@arm.com responseQueue.size(), outstandingResponses); 1678713Sandreas.hansson@arm.com 1688713Sandreas.hansson@arm.com if (masterPort->reqQueueFull()) { 1698713Sandreas.hansson@arm.com DPRINTF(BusBridge, "Request queue full, nacking\n"); 1704433Ssaidi@eecs.umich.edu nackRequest(pkt); 1714433Ssaidi@eecs.umich.edu return true; 1723662Srdreslin@umich.edu } 1734433Ssaidi@eecs.umich.edu 1745562Snate@binkert.org if (pkt->needsResponse()) { 1754435Ssaidi@eecs.umich.edu if (respQueueFull()) { 1768713Sandreas.hansson@arm.com DPRINTF(BusBridge, 1778713Sandreas.hansson@arm.com "Response queue full, no space for response, nacking\n"); 1788713Sandreas.hansson@arm.com DPRINTF(BusBridge, 1798713Sandreas.hansson@arm.com "queue size: %d outstanding resp: %d\n", 1808713Sandreas.hansson@arm.com responseQueue.size(), outstandingResponses); 1814433Ssaidi@eecs.umich.edu nackRequest(pkt); 1824433Ssaidi@eecs.umich.edu return true; 1834433Ssaidi@eecs.umich.edu } else { 1844433Ssaidi@eecs.umich.edu DPRINTF(BusBridge, "Request Needs response, reserving space\n"); 1858713Sandreas.hansson@arm.com assert(outstandingResponses != respQueueLimit); 1864433Ssaidi@eecs.umich.edu ++outstandingResponses; 1874433Ssaidi@eecs.umich.edu } 1885562Snate@binkert.org } 1894433Ssaidi@eecs.umich.edu 1908713Sandreas.hansson@arm.com masterPort->queueForSendTiming(pkt); 1914433Ssaidi@eecs.umich.edu 1924433Ssaidi@eecs.umich.edu return true; 1932657Ssaidi@eecs.umich.edu} 1942657Ssaidi@eecs.umich.edu 1954433Ssaidi@eecs.umich.eduvoid 1968713Sandreas.hansson@arm.comBridge::BridgeSlavePort::nackRequest(PacketPtr pkt) 1974433Ssaidi@eecs.umich.edu{ 1984433Ssaidi@eecs.umich.edu // Nack the packet 1994986Ssaidi@eecs.umich.edu pkt->makeTimingResponse(); 2004870Sstever@eecs.umich.edu pkt->setNacked(); 2012657Ssaidi@eecs.umich.edu 2028713Sandreas.hansson@arm.com // The Nack packets are stored in the response queue just like any 2038713Sandreas.hansson@arm.com // other response, but they do not occupy any space as this is 2048713Sandreas.hansson@arm.com // tracked by the outstandingResponses, this guarantees space for 2058713Sandreas.hansson@arm.com // the Nack packets, but implicitly means we have an (unrealistic) 2068713Sandreas.hansson@arm.com // unbounded Nack queue. 2078713Sandreas.hansson@arm.com 2088713Sandreas.hansson@arm.com // put it on the list to send 2097823Ssteve.reinhardt@amd.com Tick readyTime = curTick() + nackDelay; 2104433Ssaidi@eecs.umich.edu PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true); 2114435Ssaidi@eecs.umich.edu 2124435Ssaidi@eecs.umich.edu // nothing on the list, add it and we're done 2138713Sandreas.hansson@arm.com if (responseQueue.empty()) { 2144435Ssaidi@eecs.umich.edu assert(!sendEvent.scheduled()); 2158708Sandreas.hansson@arm.com bridge->schedule(sendEvent, readyTime); 2168713Sandreas.hansson@arm.com responseQueue.push_back(buf); 2174435Ssaidi@eecs.umich.edu return; 2184433Ssaidi@eecs.umich.edu } 2194435Ssaidi@eecs.umich.edu 2204435Ssaidi@eecs.umich.edu assert(sendEvent.scheduled() || inRetry); 2214435Ssaidi@eecs.umich.edu 2224435Ssaidi@eecs.umich.edu // does it go at the end? 2238713Sandreas.hansson@arm.com if (readyTime >= responseQueue.back()->ready) { 2248713Sandreas.hansson@arm.com responseQueue.push_back(buf); 2254435Ssaidi@eecs.umich.edu return; 2264435Ssaidi@eecs.umich.edu } 2274435Ssaidi@eecs.umich.edu 2284435Ssaidi@eecs.umich.edu // ok, somewhere in the middle, fun 2298713Sandreas.hansson@arm.com std::list<PacketBuffer*>::iterator i = responseQueue.begin(); 2308713Sandreas.hansson@arm.com std::list<PacketBuffer*>::iterator end = responseQueue.end(); 2318713Sandreas.hansson@arm.com std::list<PacketBuffer*>::iterator begin = responseQueue.begin(); 2324435Ssaidi@eecs.umich.edu bool done = false; 2334435Ssaidi@eecs.umich.edu 2344435Ssaidi@eecs.umich.edu while (i != end && !done) { 2354435Ssaidi@eecs.umich.edu if (readyTime < (*i)->ready) { 2364435Ssaidi@eecs.umich.edu if (i == begin) 2378708Sandreas.hansson@arm.com bridge->reschedule(sendEvent, readyTime); 2388713Sandreas.hansson@arm.com responseQueue.insert(i,buf); 2394435Ssaidi@eecs.umich.edu done = true; 2404435Ssaidi@eecs.umich.edu } 2414435Ssaidi@eecs.umich.edu i++; 2424435Ssaidi@eecs.umich.edu } 2434435Ssaidi@eecs.umich.edu assert(done); 2444433Ssaidi@eecs.umich.edu} 2454433Ssaidi@eecs.umich.edu 2464433Ssaidi@eecs.umich.eduvoid 2478713Sandreas.hansson@arm.comBridge::BridgeMasterPort::queueForSendTiming(PacketPtr pkt) 2482657Ssaidi@eecs.umich.edu{ 2497823Ssteve.reinhardt@amd.com Tick readyTime = curTick() + delay; 2502643Sstever@eecs.umich.edu PacketBuffer *buf = new PacketBuffer(pkt, readyTime); 2512643Sstever@eecs.umich.edu 2522643Sstever@eecs.umich.edu // If we're about to put this packet at the head of the queue, we 2532643Sstever@eecs.umich.edu // need to schedule an event to do the transmit. Otherwise there 2542643Sstever@eecs.umich.edu // should already be an event scheduled for sending the head 2552643Sstever@eecs.umich.edu // packet. 2568713Sandreas.hansson@arm.com if (requestQueue.empty()) { 2578708Sandreas.hansson@arm.com bridge->schedule(sendEvent, readyTime); 2582568SN/A } 2598713Sandreas.hansson@arm.com 2608713Sandreas.hansson@arm.com assert(requestQueue.size() != reqQueueLimit); 2618713Sandreas.hansson@arm.com 2628713Sandreas.hansson@arm.com requestQueue.push_back(buf); 2638713Sandreas.hansson@arm.com} 2648713Sandreas.hansson@arm.com 2658713Sandreas.hansson@arm.com 2668713Sandreas.hansson@arm.comvoid 2678713Sandreas.hansson@arm.comBridge::BridgeSlavePort::queueForSendTiming(PacketPtr pkt) 2688713Sandreas.hansson@arm.com{ 2698713Sandreas.hansson@arm.com // This is a response for a request we forwarded earlier. The 2708713Sandreas.hansson@arm.com // corresponding PacketBuffer should be stored in the packet's 2718713Sandreas.hansson@arm.com // senderState field. 2728713Sandreas.hansson@arm.com PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState); 2738713Sandreas.hansson@arm.com assert(buf != NULL); 2748713Sandreas.hansson@arm.com // set up new packet dest & senderState based on values saved 2758713Sandreas.hansson@arm.com // from original request 2768713Sandreas.hansson@arm.com buf->fixResponse(pkt); 2778713Sandreas.hansson@arm.com 2788713Sandreas.hansson@arm.com DPRINTF(BusBridge, "response, new dest %d\n", pkt->getDest()); 2798713Sandreas.hansson@arm.com delete buf; 2808713Sandreas.hansson@arm.com 2818713Sandreas.hansson@arm.com Tick readyTime = curTick() + delay; 2828713Sandreas.hansson@arm.com buf = new PacketBuffer(pkt, readyTime); 2838713Sandreas.hansson@arm.com 2848713Sandreas.hansson@arm.com // If we're about to put this packet at the head of the queue, we 2858713Sandreas.hansson@arm.com // need to schedule an event to do the transmit. Otherwise there 2868713Sandreas.hansson@arm.com // should already be an event scheduled for sending the head 2878713Sandreas.hansson@arm.com // packet. 2888713Sandreas.hansson@arm.com if (responseQueue.empty()) { 2898713Sandreas.hansson@arm.com bridge->schedule(sendEvent, readyTime); 2908713Sandreas.hansson@arm.com } 2918713Sandreas.hansson@arm.com responseQueue.push_back(buf); 2922568SN/A} 2932568SN/A 2942568SN/Avoid 2958713Sandreas.hansson@arm.comBridge::BridgeMasterPort::trySend() 2962568SN/A{ 2978713Sandreas.hansson@arm.com assert(!requestQueue.empty()); 2982568SN/A 2998713Sandreas.hansson@arm.com PacketBuffer *buf = requestQueue.front(); 3002643Sstever@eecs.umich.edu 3017823Ssteve.reinhardt@amd.com assert(buf->ready <= curTick()); 3022643Sstever@eecs.umich.edu 3033349Sbinkertn@umich.edu PacketPtr pkt = buf->pkt; 3042643Sstever@eecs.umich.edu 3052643Sstever@eecs.umich.edu DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", 3062643Sstever@eecs.umich.edu buf->origSrc, pkt->getDest(), pkt->getAddr()); 3072643Sstever@eecs.umich.edu 3084986Ssaidi@eecs.umich.edu // If the send was successful, make sure sender state was set to NULL 3094986Ssaidi@eecs.umich.edu // otherwise we could get a NACK back of a packet that didn't expect a 3104986Ssaidi@eecs.umich.edu // response and we would try to use freed memory. 3114986Ssaidi@eecs.umich.edu 3124986Ssaidi@eecs.umich.edu Packet::SenderState *old_sender_state = pkt->senderState; 3138713Sandreas.hansson@arm.com if (!buf->expectResponse) 3144986Ssaidi@eecs.umich.edu pkt->senderState = NULL; 3154432Ssaidi@eecs.umich.edu 3162643Sstever@eecs.umich.edu if (sendTiming(pkt)) { 3172643Sstever@eecs.umich.edu // send successful 3188713Sandreas.hansson@arm.com requestQueue.pop_front(); 3198713Sandreas.hansson@arm.com // we no longer own packet, so it's not safe to look at it 3208713Sandreas.hansson@arm.com buf->pkt = NULL; 3212657Ssaidi@eecs.umich.edu 3228713Sandreas.hansson@arm.com if (!buf->expectResponse) { 3232657Ssaidi@eecs.umich.edu // no response expected... deallocate packet buffer now. 3242657Ssaidi@eecs.umich.edu DPRINTF(BusBridge, " successful: no response expected\n"); 3252657Ssaidi@eecs.umich.edu delete buf; 3262657Ssaidi@eecs.umich.edu } 3272657Ssaidi@eecs.umich.edu 3282657Ssaidi@eecs.umich.edu // If there are more packets to send, schedule event to try again. 3298713Sandreas.hansson@arm.com if (!requestQueue.empty()) { 3308713Sandreas.hansson@arm.com buf = requestQueue.front(); 3314433Ssaidi@eecs.umich.edu DPRINTF(BusBridge, "Scheduling next send\n"); 3328708Sandreas.hansson@arm.com bridge->schedule(sendEvent, std::max(buf->ready, curTick() + 1)); 3332657Ssaidi@eecs.umich.edu } 3342643Sstever@eecs.umich.edu } else { 3352643Sstever@eecs.umich.edu DPRINTF(BusBridge, " unsuccessful\n"); 3364986Ssaidi@eecs.umich.edu pkt->senderState = old_sender_state; 3374435Ssaidi@eecs.umich.edu inRetry = true; 3382643Sstever@eecs.umich.edu } 3394986Ssaidi@eecs.umich.edu 3408713Sandreas.hansson@arm.com DPRINTF(BusBridge, "trySend: request queue size: %d\n", 3418713Sandreas.hansson@arm.com requestQueue.size()); 3422568SN/A} 3432568SN/A 3448713Sandreas.hansson@arm.comvoid 3458713Sandreas.hansson@arm.comBridge::BridgeSlavePort::trySend() 3468713Sandreas.hansson@arm.com{ 3478713Sandreas.hansson@arm.com assert(!responseQueue.empty()); 3488713Sandreas.hansson@arm.com 3498713Sandreas.hansson@arm.com PacketBuffer *buf = responseQueue.front(); 3508713Sandreas.hansson@arm.com 3518713Sandreas.hansson@arm.com assert(buf->ready <= curTick()); 3528713Sandreas.hansson@arm.com 3538713Sandreas.hansson@arm.com PacketPtr pkt = buf->pkt; 3548713Sandreas.hansson@arm.com 3558713Sandreas.hansson@arm.com DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", 3568713Sandreas.hansson@arm.com buf->origSrc, pkt->getDest(), pkt->getAddr()); 3578713Sandreas.hansson@arm.com 3588713Sandreas.hansson@arm.com bool was_nacked_here = buf->nackedHere; 3598713Sandreas.hansson@arm.com 3608713Sandreas.hansson@arm.com // no need to worry about the sender state since we are not 3618713Sandreas.hansson@arm.com // modifying it 3628713Sandreas.hansson@arm.com 3638713Sandreas.hansson@arm.com if (sendTiming(pkt)) { 3648713Sandreas.hansson@arm.com DPRINTF(BusBridge, " successful\n"); 3658713Sandreas.hansson@arm.com // send successful 3668713Sandreas.hansson@arm.com responseQueue.pop_front(); 3678713Sandreas.hansson@arm.com // this is a response... deallocate packet buffer now. 3688713Sandreas.hansson@arm.com delete buf; 3698713Sandreas.hansson@arm.com 3708713Sandreas.hansson@arm.com if (!was_nacked_here) { 3718713Sandreas.hansson@arm.com assert(outstandingResponses != 0); 3728713Sandreas.hansson@arm.com --outstandingResponses; 3738713Sandreas.hansson@arm.com } 3748713Sandreas.hansson@arm.com 3758713Sandreas.hansson@arm.com // If there are more packets to send, schedule event to try again. 3768713Sandreas.hansson@arm.com if (!responseQueue.empty()) { 3778713Sandreas.hansson@arm.com buf = responseQueue.front(); 3788713Sandreas.hansson@arm.com DPRINTF(BusBridge, "Scheduling next send\n"); 3798713Sandreas.hansson@arm.com bridge->schedule(sendEvent, std::max(buf->ready, curTick() + 1)); 3808713Sandreas.hansson@arm.com } 3818713Sandreas.hansson@arm.com } else { 3828713Sandreas.hansson@arm.com DPRINTF(BusBridge, " unsuccessful\n"); 3838713Sandreas.hansson@arm.com inRetry = true; 3848713Sandreas.hansson@arm.com } 3858713Sandreas.hansson@arm.com 3868713Sandreas.hansson@arm.com DPRINTF(BusBridge, "trySend: queue size: %d outstanding resp: %d\n", 3878713Sandreas.hansson@arm.com responseQueue.size(), outstandingResponses); 3888713Sandreas.hansson@arm.com} 3892568SN/A 3902657Ssaidi@eecs.umich.eduvoid 3918713Sandreas.hansson@arm.comBridge::BridgeMasterPort::recvRetry() 3922568SN/A{ 3934435Ssaidi@eecs.umich.edu inRetry = false; 3948713Sandreas.hansson@arm.com Tick nextReady = requestQueue.front()->ready; 3957823Ssteve.reinhardt@amd.com if (nextReady <= curTick()) 3964435Ssaidi@eecs.umich.edu trySend(); 3974435Ssaidi@eecs.umich.edu else 3988708Sandreas.hansson@arm.com bridge->schedule(sendEvent, nextReady); 3992568SN/A} 4002568SN/A 4018713Sandreas.hansson@arm.comvoid 4028713Sandreas.hansson@arm.comBridge::BridgeSlavePort::recvRetry() 4032568SN/A{ 4048713Sandreas.hansson@arm.com inRetry = false; 4058713Sandreas.hansson@arm.com Tick nextReady = responseQueue.front()->ready; 4068713Sandreas.hansson@arm.com if (nextReady <= curTick()) 4078713Sandreas.hansson@arm.com trySend(); 4088713Sandreas.hansson@arm.com else 4098713Sandreas.hansson@arm.com bridge->schedule(sendEvent, nextReady); 4102568SN/A} 4112568SN/A 4128713Sandreas.hansson@arm.comTick 4138713Sandreas.hansson@arm.comBridge::BridgeMasterPort::recvAtomic(PacketPtr pkt) 4148713Sandreas.hansson@arm.com{ 4158713Sandreas.hansson@arm.com // master port should never receive any atomic access (panic only 4168713Sandreas.hansson@arm.com // works once the other side, i.e. the busses, respects this) 4178713Sandreas.hansson@arm.com // 4188713Sandreas.hansson@arm.com //panic("Master port on %s got a recvAtomic\n", bridge->name()); 4198713Sandreas.hansson@arm.com return 0; 4208713Sandreas.hansson@arm.com} 4218713Sandreas.hansson@arm.com 4228713Sandreas.hansson@arm.comTick 4238713Sandreas.hansson@arm.comBridge::BridgeSlavePort::recvAtomic(PacketPtr pkt) 4248713Sandreas.hansson@arm.com{ 4258713Sandreas.hansson@arm.com return delay + masterPort->sendAtomic(pkt); 4268713Sandreas.hansson@arm.com} 4278713Sandreas.hansson@arm.com 4282568SN/Avoid 4298713Sandreas.hansson@arm.comBridge::BridgeMasterPort::recvFunctional(PacketPtr pkt) 4308713Sandreas.hansson@arm.com{ 4318713Sandreas.hansson@arm.com // master port should never receive any functional access (panic 4328713Sandreas.hansson@arm.com // only works once the other side, i.e. the busses, respect this) 4338713Sandreas.hansson@arm.com 4348713Sandreas.hansson@arm.com // panic("Master port on %s got a recvFunctional\n", bridge->name()); 4358713Sandreas.hansson@arm.com} 4368713Sandreas.hansson@arm.com 4378713Sandreas.hansson@arm.comvoid 4388713Sandreas.hansson@arm.comBridge::BridgeSlavePort::recvFunctional(PacketPtr pkt) 4392568SN/A{ 4402643Sstever@eecs.umich.edu std::list<PacketBuffer*>::iterator i; 4412568SN/A 4425314Sstever@gmail.com pkt->pushLabel(name()); 4435314Sstever@gmail.com 4448713Sandreas.hansson@arm.com // check the response queue 4458713Sandreas.hansson@arm.com for (i = responseQueue.begin(); i != responseQueue.end(); ++i) { 4467668Ssteve.reinhardt@amd.com if (pkt->checkFunctional((*i)->pkt)) { 4477668Ssteve.reinhardt@amd.com pkt->makeResponse(); 4484626Sstever@eecs.umich.edu return; 4497668Ssteve.reinhardt@amd.com } 4502568SN/A } 4512568SN/A 4528713Sandreas.hansson@arm.com // also check the master port's request queue 4538713Sandreas.hansson@arm.com if (masterPort->checkFunctional(pkt)) { 4548713Sandreas.hansson@arm.com return; 4558713Sandreas.hansson@arm.com } 4568713Sandreas.hansson@arm.com 4575314Sstever@gmail.com pkt->popLabel(); 4585314Sstever@gmail.com 4594626Sstever@eecs.umich.edu // fall through if pkt still not satisfied 4608713Sandreas.hansson@arm.com masterPort->sendFunctional(pkt); 4618713Sandreas.hansson@arm.com} 4628713Sandreas.hansson@arm.com 4638713Sandreas.hansson@arm.combool 4648713Sandreas.hansson@arm.comBridge::BridgeMasterPort::checkFunctional(PacketPtr pkt) 4658713Sandreas.hansson@arm.com{ 4668713Sandreas.hansson@arm.com bool found = false; 4678713Sandreas.hansson@arm.com std::list<PacketBuffer*>::iterator i = requestQueue.begin(); 4688713Sandreas.hansson@arm.com 4698713Sandreas.hansson@arm.com while(i != requestQueue.end() && !found) { 4708713Sandreas.hansson@arm.com if (pkt->checkFunctional((*i)->pkt)) { 4718713Sandreas.hansson@arm.com pkt->makeResponse(); 4728713Sandreas.hansson@arm.com found = true; 4738713Sandreas.hansson@arm.com } 4748713Sandreas.hansson@arm.com ++i; 4758713Sandreas.hansson@arm.com } 4768713Sandreas.hansson@arm.com 4778713Sandreas.hansson@arm.com return found; 4782568SN/A} 4792568SN/A 4808711Sandreas.hansson@arm.com/** Function called by the port when the bridge is receiving a range change.*/ 4812568SN/Avoid 4828713Sandreas.hansson@arm.comBridge::BridgeMasterPort::recvRangeChange() 4832568SN/A{ 4848713Sandreas.hansson@arm.com // no need to forward as the bridge has a fixed set of ranges 4858713Sandreas.hansson@arm.com} 4868713Sandreas.hansson@arm.com 4878713Sandreas.hansson@arm.comvoid 4888713Sandreas.hansson@arm.comBridge::BridgeSlavePort::recvRangeChange() 4898713Sandreas.hansson@arm.com{ 4908713Sandreas.hansson@arm.com // is a slave port so do nothing 4912568SN/A} 4922568SN/A 4938711Sandreas.hansson@arm.comAddrRangeList 4948713Sandreas.hansson@arm.comBridge::BridgeSlavePort::getAddrRanges() 4952568SN/A{ 4968711Sandreas.hansson@arm.com return ranges; 4972568SN/A} 4982568SN/A 4994762Snate@binkert.orgBridge * 5004762Snate@binkert.orgBridgeParams::create() 5012568SN/A{ 5024762Snate@binkert.org return new Bridge(this); 5032568SN/A} 504