xbar.cc revision 9240
16112SN/A/* 26112SN/A * Copyright (c) 2011-2012 ARM Limited 36112SN/A * All rights reserved 49988Snilay@cs.wisc.edu * 58835SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 69988Snilay@cs.wisc.edu * not be construed as granting a license to any other intellectual 77935SN/A * property including but not limited to intellectual property relating 87935SN/A * to a hardware implementation of the functionality of the software 97935SN/A * licensed hereunder. You may use the software subject to the license 106112SN/A * terms below provided that you ensure that this notice is replicated 116112SN/A * unmodified and in its entirety in all distributions of the software, 126112SN/A * modified or unmodified, in source code or in binary form. 1310315Snilay@cs.wisc.edu * 148835SAli.Saidi@ARM.com * Copyright (c) 2006 The Regents of The University of Michigan 159885Sstever@gmail.com * All rights reserved. 169885Sstever@gmail.com * 1711570SCurtis.Dunham@arm.com * Redistribution and use in source and binary forms, with or without 189988Snilay@cs.wisc.edu * modification, are permitted provided that the following conditions are 1911312Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 208835SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 218835SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 2210315Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer in the 238835SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 2410242Ssteve.reinhardt@amd.com * neither the name of the copyright holders nor the names of its 256112SN/A * contributors may be used to endorse or promote products derived from 269449SAli.Saidi@ARM.com * this software without specific prior written permission. 278464SN/A * 2810736Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2911219Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 308721SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3111570SCurtis.Dunham@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3211570SCurtis.Dunham@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3311570SCurtis.Dunham@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3411570SCurtis.Dunham@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 358835SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 368835SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3711440SCurtis.Dunham@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3811440SCurtis.Dunham@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 397935SN/A * 407935SN/A * Authors: Ali Saidi 417935SN/A * Andreas Hansson 427935SN/A * William Wang 437935SN/A */ 447935SN/A 457935SN/A/** 469885Sstever@gmail.com * @file 479885Sstever@gmail.com * Definition of a bus object. 489885Sstever@gmail.com */ 499885Sstever@gmail.com 509885Sstever@gmail.com#include "base/misc.hh" 5110315Snilay@cs.wisc.edu#include "base/trace.hh" 529988Snilay@cs.wisc.edu#include "debug/Bus.hh" 5310315Snilay@cs.wisc.edu#include "debug/BusAddrRanges.hh" 549885Sstever@gmail.com#include "debug/Drain.hh" 556112SN/A#include "mem/bus.hh" 566112SN/A 576112SN/ABaseBus::BaseBus(const BaseBusParams *p) 589481Snilay@cs.wisc.edu : MemObject(p), 596112SN/A headerCycles(p->header_cycles), width(p->width), 606112SN/A defaultPortID(InvalidPortID), 618241SN/A useDefaultRange(p->use_default_range), 628241SN/A defaultBlockSize(p->block_size), 636112SN/A cachedBlockSize(0), cachedBlockSizeValid(false) 646112SN/A{} 656112SN/A 666112SN/ABaseBus::~BaseBus() 679481Snilay@cs.wisc.edu{ 6811956Sgabeblack@google.com for (MasterPortIter m = masterPorts.begin(); m != masterPorts.end(); 696112SN/A ++m) { 709885Sstever@gmail.com delete *m; 716112SN/A } 726112SN/A 736112SN/A for (SlavePortIter s = slavePorts.begin(); s != slavePorts.end(); 746112SN/A ++s) { 756112SN/A delete *s; 766112SN/A } 776112SN/A} 786112SN/A 796112SN/AMasterPort & 8011570SCurtis.Dunham@arm.comBaseBus::getMasterPort(const std::string &if_name, int idx) 816112SN/A{ 826112SN/A if (if_name == "master" && idx < masterPorts.size()) { 838835SAli.Saidi@ARM.com // the master port index translates directly to the vector position 846112SN/A return *masterPorts[idx]; 856112SN/A } else if (if_name == "default") { 869988Snilay@cs.wisc.edu return *masterPorts[defaultPortID]; 879988Snilay@cs.wisc.edu } else { 8810451Snilay@cs.wisc.edu return MemObject::getMasterPort(if_name, idx); 896112SN/A } 906112SN/A} 916112SN/A 926112SN/ASlavePort & 936112SN/ABaseBus::getSlavePort(const std::string &if_name, int idx) 946112SN/A{ 956112SN/A if (if_name == "slave" && idx < slavePorts.size()) { 966112SN/A // the slave port index translates directly to the vector position 976112SN/A return *slavePorts[idx]; 986112SN/A } else { 996112SN/A return MemObject::getSlavePort(if_name, idx); 1008835SAli.Saidi@ARM.com } 1019449SAli.Saidi@ARM.com} 1026112SN/A 1036112SN/ATick 1046112SN/ABaseBus::calcPacketTiming(PacketPtr pkt) 1056112SN/A{ 1066112SN/A // determine the current time rounded to the closest following 1076112SN/A // clock edge 1086112SN/A Tick now = nextCycle(); 1098835SAli.Saidi@ARM.com 1106112SN/A Tick headerTime = now + headerCycles * clock; 1119924Ssteve.reinhardt@amd.com 1126112SN/A // The packet will be sent. Figure out how long it occupies the bus, and 1136112SN/A // how much of that time is for the first "word", aka bus width. 1146112SN/A int numCycles = 0; 1156112SN/A if (pkt->hasData()) { 1166112SN/A // If a packet has data, it needs ceil(size/width) cycles to send it 11711570SCurtis.Dunham@arm.com int dataSize = pkt->getSize(); 11811570SCurtis.Dunham@arm.com numCycles += dataSize/width; 11911570SCurtis.Dunham@arm.com if (dataSize % width) 12011570SCurtis.Dunham@arm.com numCycles++; 1218835SAli.Saidi@ARM.com } 1226112SN/A 1236112SN/A // The first word will be delivered after the current tick, the delivery 1246112SN/A // of the address if any, and one bus cycle to deliver the data 1256112SN/A pkt->firstWordTime = headerTime + clock; 1266112SN/A 1276112SN/A pkt->finishTime = headerTime + numCycles * clock; 1289885Sstever@gmail.com 1296112SN/A return headerTime; 1306112SN/A} 1316112SN/A 1326112SN/Atemplate <typename PortClass> 1336112SN/ABaseBus::Layer<PortClass>::Layer(BaseBus& _bus, const std::string& _name, 1346112SN/A Tick _clock) : 1356112SN/A bus(_bus), _name(_name), state(IDLE), clock(_clock), drainEvent(NULL), 1366112SN/A releaseEvent(this) 1376112SN/A{ 13810242Ssteve.reinhardt@amd.com} 1396112SN/A 1408546SN/Atemplate <typename PortClass> 1419449SAli.Saidi@ARM.comvoid BaseBus::Layer<PortClass>::occupyLayer(Tick until) 14211956Sgabeblack@google.com{ 1436112SN/A // ensure the state is busy or in retry and never idle at this 1446112SN/A // point, as the bus should transition from idle as soon as it has 1456112SN/A // decided to forward the packet to prevent any follow-on calls to 1466112SN/A // sendTiming seeing an unoccupied bus 1476112SN/A assert(state != IDLE); 1486112SN/A 1496112SN/A // note that we do not change the bus state here, if we are going 1506112SN/A // from idle to busy it is handled by tryTiming, and if we 1519481Snilay@cs.wisc.edu // are in retry we should remain in retry such that 15210798Ssteve.reinhardt@amd.com // succeededTiming still sees the accurate state 1539481Snilay@cs.wisc.edu 1549481Snilay@cs.wisc.edu // until should never be 0 as express snoops never occupy the bus 1559481Snilay@cs.wisc.edu assert(until != 0); 1569481Snilay@cs.wisc.edu bus.schedule(releaseEvent, until); 1579481Snilay@cs.wisc.edu 1589988Snilay@cs.wisc.edu DPRINTF(BaseBus, "The bus is now busy from tick %d to %d\n", 1599481Snilay@cs.wisc.edu curTick(), until); 1609481Snilay@cs.wisc.edu} 16111440SCurtis.Dunham@arm.com 16211440SCurtis.Dunham@arm.comtemplate <typename PortClass> 16311440SCurtis.Dunham@arm.combool 16411440SCurtis.Dunham@arm.comBaseBus::Layer<PortClass>::tryTiming(PortClass* port) 16511440SCurtis.Dunham@arm.com{ 16611440SCurtis.Dunham@arm.com // first we see if the bus is busy, next we check if we are in a 1679481Snilay@cs.wisc.edu // retry with a port other than the current one 1689481Snilay@cs.wisc.edu if (state == BUSY || (state == RETRY && port != retryList.front())) { 1699481Snilay@cs.wisc.edu // put the port at the end of the retry list 1709481Snilay@cs.wisc.edu retryList.push_back(port); 1719481Snilay@cs.wisc.edu return false; 17211440SCurtis.Dunham@arm.com } 1739481Snilay@cs.wisc.edu 1746112SN/A // update the state which is shared for request, response and 17511066Snilay@cs.wisc.edu // snoop responses, if we were idle we are now busy, if we are in 1769885Sstever@gmail.com // a retry, then do not change 17711680SCurtis.Dunham@arm.com if (state == IDLE) 1786112SN/A state = BUSY; 1799885Sstever@gmail.com 18011219Snilay@cs.wisc.edu return true; 18111731Sjason@lowepower.com} 18211570SCurtis.Dunham@arm.com 18310636Snilay@cs.wisc.edutemplate <typename PortClass> 1849988Snilay@cs.wisc.eduvoid 18511066Snilay@cs.wisc.eduBaseBus::Layer<PortClass>::succeededTiming(Tick busy_time) 1866112SN/A{ 1876112SN/A // if a retrying port succeeded, also take it off the retry list 18811570SCurtis.Dunham@arm.com if (state == RETRY) { 18911570SCurtis.Dunham@arm.com DPRINTF(BaseBus, "Remove retry from list %s\n", 19011570SCurtis.Dunham@arm.com retryList.front()->name()); 19111570SCurtis.Dunham@arm.com retryList.pop_front(); 1926112SN/A state = BUSY; 1938835SAli.Saidi@ARM.com } 1949348SAli.Saidi@ARM.com 19510036SAli.Saidi@ARM.com // we should either have gone from idle to busy in the 1966112SN/A // tryTiming test, or just gone from a retry to busy 1978835SAli.Saidi@ARM.com assert(state == BUSY); 19811731Sjason@lowepower.com 1999885Sstever@gmail.com // occupy the bus accordingly 2006112SN/A occupyLayer(busy_time); 2016112SN/A} 20211219Snilay@cs.wisc.edu 2036112SN/Atemplate <typename PortClass> 2048983Snate@binkert.orgvoid 2056112SN/ABaseBus::Layer<PortClass>::failedTiming(PortClass* port, Tick busy_time) 2069885Sstever@gmail.com{ 2079885Sstever@gmail.com // if we are not in a retry, i.e. busy (but never idle), or we are 2089885Sstever@gmail.com // in a retry but not for the current port, then add the port at 2099885Sstever@gmail.com // the end of the retry list 2109885Sstever@gmail.com if (state != RETRY || port != retryList.front()) { 21111731Sjason@lowepower.com retryList.push_back(port); 21211570SCurtis.Dunham@arm.com } 2139988Snilay@cs.wisc.edu 21411570SCurtis.Dunham@arm.com // even if we retried the current one and did not succeed, 21511570SCurtis.Dunham@arm.com // we are no longer retrying but instead busy 21611570SCurtis.Dunham@arm.com state = BUSY; 21711570SCurtis.Dunham@arm.com 21810036SAli.Saidi@ARM.com // occupy the bus accordingly 2199885Sstever@gmail.com occupyLayer(busy_time); 22011731Sjason@lowepower.com} 2219885Sstever@gmail.com 2226112SN/Atemplate <typename PortClass> 2236112SN/Avoid 2249988Snilay@cs.wisc.eduBaseBus::Layer<PortClass>::releaseLayer() 2256112SN/A{ 2266112SN/A // releasing the bus means we should now be idle 2276112SN/A assert(state == BUSY); 2286112SN/A assert(!releaseEvent.scheduled()); 2297761SN/A 2307761SN/A // update the state 2319988Snilay@cs.wisc.edu state = IDLE; 2326112SN/A 2336112SN/A // bus is now idle, so if someone is waiting we can retry 2346112SN/A if (!retryList.empty()) { 2356112SN/A // note that we block (return false on recvTiming) both 2366112SN/A // because the bus is busy and because the destination is 2379988Snilay@cs.wisc.edu // busy, and in the latter case the bus may be released before 2386112SN/A // we see a retry from the destination 2396112SN/A retryWaiting(); 2406112SN/A } else if (drainEvent) { 2416112SN/A DPRINTF(Drain, "Bus done draining, processing drain event\n"); 2429988Snilay@cs.wisc.edu //If we weren't able to drain before, do it now. 2436112SN/A drainEvent->process(); 2446112SN/A // Clear the drain event once we're done with it. 24511066Snilay@cs.wisc.edu drainEvent = NULL; 2466112SN/A } 2476112SN/A} 2486112SN/A 2496112SN/Atemplate <typename PortClass> 2506112SN/Avoid 2519988Snilay@cs.wisc.eduBaseBus::Layer<PortClass>::retryWaiting() 2526112SN/A{ 2536112SN/A // this should never be called with an empty retry list 2546112SN/A assert(!retryList.empty()); 2556112SN/A 2569988Snilay@cs.wisc.edu // we always go to retrying from idle 2576112SN/A assert(state == IDLE); 2586112SN/A 25911066Snilay@cs.wisc.edu // update the state which is shared for request, response and 2606112SN/A // snoop responses 2616112SN/A state = RETRY; 2626112SN/A 2639988Snilay@cs.wisc.edu // note that we might have blocked on the receiving port being 2646112SN/A // busy (rather than the bus itself) and now call retry before the 2656112SN/A // destination called retry on the bus 26611066Snilay@cs.wisc.edu retryList.front()->sendRetry(); 2676112SN/A 2686112SN/A // If the bus is still in the retry state, sendTiming wasn't 2696112SN/A // called in zero time (e.g. the cache does this) 2706112SN/A if (state == RETRY) { 2716112SN/A retryList.pop_front(); 2729988Snilay@cs.wisc.edu 2736112SN/A //Burn a cycle for the missed grant. 2746112SN/A 2756112SN/A // update the state which is shared for request, response and 2766112SN/A // snoop responses 2779988Snilay@cs.wisc.edu state = BUSY; 2786112SN/A 2796112SN/A // determine the current time rounded to the closest following 28011066Snilay@cs.wisc.edu // clock edge 2816112SN/A Tick now = bus.nextCycle(); 2826112SN/A 2836112SN/A occupyLayer(now + clock); 2849988Snilay@cs.wisc.edu } 2856112SN/A} 2866112SN/A 28711066Snilay@cs.wisc.edutemplate <typename PortClass> 2886112SN/Avoid 2896112SN/ABaseBus::Layer<PortClass>::recvRetry() 2906112SN/A{ 2919988Snilay@cs.wisc.edu // we got a retry from a peer that we tried to send something to 2926112SN/A // and failed, but we sent it on the account of someone else, and 2936112SN/A // that source port should be on our retry list, however if the 29411066Snilay@cs.wisc.edu // bus layer is released before this happens and the retry (from 2956112SN/A // the bus point of view) is successful then this no longer holds 2966112SN/A // and we could in fact have an empty retry list 2976112SN/A if (retryList.empty()) 29811731Sjason@lowepower.com return; 2996112SN/A 3009988Snilay@cs.wisc.edu // if the bus layer is idle 30111731Sjason@lowepower.com if (state == IDLE) { 3026112SN/A // note that we do not care who told us to retry at the moment, we 3036112SN/A // merely let the first one on the retry list go 3046112SN/A retryWaiting(); 3059988Snilay@cs.wisc.edu } 3066112SN/A} 3076112SN/A 30811066Snilay@cs.wisc.eduPortID 3096112SN/ABaseBus::findPort(Addr addr) 3106112SN/A{ 3116112SN/A /* An interval tree would be a better way to do this. --ali. */ 3129988Snilay@cs.wisc.edu PortID dest_id = checkPortCache(addr); 31311731Sjason@lowepower.com if (dest_id != InvalidPortID) 31411731Sjason@lowepower.com return dest_id; 31511731Sjason@lowepower.com 31611731Sjason@lowepower.com // Check normal port ranges 31711731Sjason@lowepower.com PortMapConstIter i = portMap.find(RangeSize(addr,1)); 31811731Sjason@lowepower.com if (i != portMap.end()) { 31911731Sjason@lowepower.com dest_id = i->second; 32011731Sjason@lowepower.com updatePortCache(dest_id, i->first.start, i->first.end); 32111731Sjason@lowepower.com return dest_id; 32211731Sjason@lowepower.com } 32311731Sjason@lowepower.com 32411731Sjason@lowepower.com // Check if this matches the default range 32511731Sjason@lowepower.com if (useDefaultRange) { 32611731Sjason@lowepower.com AddrRangeConstIter a_end = defaultRange.end(); 3276112SN/A for (AddrRangeConstIter i = defaultRange.begin(); i != a_end; i++) { 3286112SN/A if (*i == addr) { 32911066Snilay@cs.wisc.edu DPRINTF(BusAddrRanges, " found addr %#llx on default\n", 3306112SN/A addr); 33111731Sjason@lowepower.com return defaultPortID; 3326112SN/A } 3339988Snilay@cs.wisc.edu } 3346112SN/A } else if (defaultPortID != InvalidPortID) { 3356112SN/A DPRINTF(BusAddrRanges, "Unable to find destination for addr %#llx, " 33611066Snilay@cs.wisc.edu "will use default port\n", addr); 3376112SN/A return defaultPortID; 3386112SN/A } 3396112SN/A 34011731Sjason@lowepower.com // we should use the range for the default port and it did not 3416112SN/A // match, or the default port is not set 3429988Snilay@cs.wisc.edu fatal("Unable to find destination for addr %#llx on bus %s\n", addr, 34311731Sjason@lowepower.com name()); 3446112SN/A} 34511731Sjason@lowepower.com 3466112SN/A/** Function called by the port when the bus is receiving a range change.*/ 3479988Snilay@cs.wisc.eduvoid 3486112SN/ABaseBus::recvRangeChange(PortID master_port_id) 3496112SN/A{ 35011066Snilay@cs.wisc.edu AddrRangeIter iter; 3516112SN/A 35211731Sjason@lowepower.com if (inRecvRangeChange.count(master_port_id)) 35311731Sjason@lowepower.com return; 35411731Sjason@lowepower.com inRecvRangeChange.insert(master_port_id); 35511731Sjason@lowepower.com 35611731Sjason@lowepower.com DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", 35711731Sjason@lowepower.com master_port_id); 35811731Sjason@lowepower.com 3596112SN/A clearPortCache(); 3606112SN/A if (master_port_id == defaultPortID) { 3617761SN/A defaultRange.clear(); 3627761SN/A // Only try to update these ranges if the user set a default responder. 3639988Snilay@cs.wisc.edu if (useDefaultRange) { 3647761SN/A // get the address ranges of the connected slave port 3656112SN/A AddrRangeList ranges = 3667761SN/A masterPorts[master_port_id]->getAddrRanges(); 3676112SN/A for(iter = ranges.begin(); iter != ranges.end(); iter++) { 3689988Snilay@cs.wisc.edu defaultRange.push_back(*iter); 3697761SN/A DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", 3707761SN/A iter->start, iter->end); 37111066Snilay@cs.wisc.edu } 3727761SN/A } 3737761SN/A } else { 3747761SN/A 3759988Snilay@cs.wisc.edu assert(master_port_id < masterPorts.size() && master_port_id >= 0); 3767761SN/A MasterPort *port = masterPorts[master_port_id]; 3777761SN/A 37811066Snilay@cs.wisc.edu // Clean out any previously existent ids 3797761SN/A for (PortMapIter portIter = portMap.begin(); 3807761SN/A portIter != portMap.end(); ) { 3817761SN/A if (portIter->second == master_port_id) 3829988Snilay@cs.wisc.edu portMap.erase(portIter++); 3837761SN/A else 3847761SN/A portIter++; 38511066Snilay@cs.wisc.edu } 3867761SN/A 3877761SN/A // get the address ranges of the connected slave port 3887761SN/A AddrRangeList ranges = port->getAddrRanges(); 3899988Snilay@cs.wisc.edu 3907761SN/A for (iter = ranges.begin(); iter != ranges.end(); iter++) { 3917761SN/A DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", 39211066Snilay@cs.wisc.edu iter->start, iter->end, master_port_id); 3937761SN/A if (portMap.insert(*iter, master_port_id) == portMap.end()) { 3947761SN/A PortID conflict_id = portMap.find(*iter)->second; 3957761SN/A fatal("%s has two ports with same range:\n\t%s\n\t%s\n", 3969988Snilay@cs.wisc.edu name(), 3977761SN/A masterPorts[master_port_id]->getSlavePort().name(), 3987761SN/A masterPorts[conflict_id]->getSlavePort().name()); 39911066Snilay@cs.wisc.edu } 4007761SN/A } 4017761SN/A } 4027761SN/A DPRINTF(BusAddrRanges, "port list has %d entries\n", portMap.size()); 4039988Snilay@cs.wisc.edu 4047761SN/A // tell all our neighbouring master ports that our address range 4057761SN/A // has changed 40611066Snilay@cs.wisc.edu for (SlavePortConstIter p = slavePorts.begin(); p != slavePorts.end(); 4077761SN/A ++p) 4087761SN/A (*p)->sendRangeChange(); 4097761SN/A 4109988Snilay@cs.wisc.edu inRecvRangeChange.erase(master_port_id); 4117761SN/A} 4127761SN/A 41311066Snilay@cs.wisc.eduAddrRangeList 4147761SN/ABaseBus::getAddrRanges() const 4157761SN/A{ 4167761SN/A AddrRangeList ranges; 4179988Snilay@cs.wisc.edu 4187761SN/A DPRINTF(BusAddrRanges, "received address range request, returning:\n"); 4197761SN/A 42011066Snilay@cs.wisc.edu for (AddrRangeConstIter dflt_iter = defaultRange.begin(); 4217761SN/A dflt_iter != defaultRange.end(); dflt_iter++) { 4227761SN/A ranges.push_back(*dflt_iter); 4237761SN/A DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start, 4249988Snilay@cs.wisc.edu dflt_iter->end); 4257761SN/A } 4267761SN/A for (PortMapConstIter portIter = portMap.begin(); 42711066Snilay@cs.wisc.edu portIter != portMap.end(); portIter++) { 4287761SN/A bool subset = false; 4297761SN/A for (AddrRangeConstIter dflt_iter = defaultRange.begin(); 4307761SN/A dflt_iter != defaultRange.end(); dflt_iter++) { 4319988Snilay@cs.wisc.edu if ((portIter->first.start < dflt_iter->start && 4327761SN/A portIter->first.end >= dflt_iter->start) || 4337761SN/A (portIter->first.start < dflt_iter->end && 43411066Snilay@cs.wisc.edu portIter->first.end >= dflt_iter->end)) 4357761SN/A fatal("Devices can not set ranges that itersect the default set\ 4367761SN/A but are not a subset of the default set.\n"); 4377761SN/A if (portIter->first.start >= dflt_iter->start && 4389988Snilay@cs.wisc.edu portIter->first.end <= dflt_iter->end) { 4397761SN/A subset = true; 4407761SN/A DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n", 44111066Snilay@cs.wisc.edu portIter->first.start, portIter->first.end); 4427761SN/A } 4437761SN/A } 4447761SN/A if (!subset) { 4459988Snilay@cs.wisc.edu ranges.push_back(portIter->first); 4467761SN/A DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", 4477761SN/A portIter->first.start, portIter->first.end); 44811066Snilay@cs.wisc.edu } 4497761SN/A } 4507761SN/A 4517761SN/A return ranges; 4529988Snilay@cs.wisc.edu} 4537761SN/A 4547761SN/Aunsigned 45511066Snilay@cs.wisc.eduBaseBus::findBlockSize() 4567761SN/A{ 4577761SN/A if (cachedBlockSizeValid) 4587761SN/A return cachedBlockSize; 4599988Snilay@cs.wisc.edu 4607761SN/A unsigned max_bs = 0; 4617761SN/A 46211066Snilay@cs.wisc.edu for (MasterPortConstIter m = masterPorts.begin(); m != masterPorts.end(); 4637761SN/A ++m) { 4647761SN/A unsigned tmp_bs = (*m)->peerBlockSize(); 4657761SN/A if (tmp_bs > max_bs) 4669988Snilay@cs.wisc.edu max_bs = tmp_bs; 4677761SN/A } 4687761SN/A 46911066Snilay@cs.wisc.edu for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end(); 4707761SN/A ++s) { 4717761SN/A unsigned tmp_bs = (*s)->peerBlockSize(); 4727761SN/A if (tmp_bs > max_bs) 4739988Snilay@cs.wisc.edu max_bs = tmp_bs; 4747761SN/A } 4757761SN/A if (max_bs == 0) 47611066Snilay@cs.wisc.edu max_bs = defaultBlockSize; 4777761SN/A 4787761SN/A if (max_bs != 64 && max_bs != 32) 4797761SN/A warn_once("Blocksize found to not be 32 or 64... hmm... probably not.\n"); 4809988Snilay@cs.wisc.edu cachedBlockSize = max_bs; 4817761SN/A cachedBlockSizeValid = true; 4827761SN/A return max_bs; 48311066Snilay@cs.wisc.edu} 4847761SN/A 4857761SN/Atemplate <typename PortClass> 4867761SN/Aunsigned int 4879988Snilay@cs.wisc.eduBaseBus::Layer<PortClass>::drain(Event * de) 4887761SN/A{ 4897761SN/A //We should check that we're not "doing" anything, and that noone is 49011066Snilay@cs.wisc.edu //waiting. We might be idle but have someone waiting if the device we 4917761SN/A //contacted for a retry didn't actually retry. 4927761SN/A if (!retryList.empty() || state != IDLE) { 4937761SN/A DPRINTF(Drain, "Bus not drained\n"); 4949988Snilay@cs.wisc.edu drainEvent = de; 4957761SN/A return 1; 4967761SN/A } 49711066Snilay@cs.wisc.edu return 0; 4987761SN/A} 4997761SN/A 5007761SN/A/** 5019988Snilay@cs.wisc.edu * Bus layer template instantiations. Could be removed with _impl.hh 5027761SN/A * file, but since there are only two given options (MasterPort and 5036112SN/A * SlavePort) it seems a bit excessive at this point. 50411066Snilay@cs.wisc.edu */ 5056112SN/Atemplate class BaseBus::Layer<SlavePort>; 5066112SN/Atemplate class BaseBus::Layer<MasterPort>; 5076112SN/A