xbar.cc revision 9294
17513SN/A/* 27513SN/A * Copyright (c) 2011-2012 ARM Limited 37513SN/A * All rights reserved 410036SN/A * 58835SN/A * The license below extends only to copyright in the software and shall 610036SN/A * 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 107513SN/A * terms below provided that you ensure that this notice is replicated 117513SN/A * unmodified and in its entirety in all distributions of the software, 127513SN/A * modified or unmodified, in source code or in binary form. 1310315SN/A * 148835SN/A * Copyright (c) 2006 The Regents of The University of Michigan 159885SN/A * All rights reserved. 169885SN/A * 1711570SCurtis.Dunham@arm.com * Redistribution and use in source and binary forms, with or without 1810036SN/A * modification, are permitted provided that the following conditions are 1911312Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 208835SN/A * notice, this list of conditions and the following disclaimer; 218835SN/A * redistributions in binary form must reproduce the above copyright 2210315SN/A * notice, this list of conditions and the following disclaimer in the 238835SN/A * documentation and/or other materials provided with the distribution; 2410038SN/A * neither the name of the copyright holders nor the names of its 259481SN/A * contributors may be used to endorse or promote products derived from 269481SN/A * this software without specific prior written permission. 278721SN/A * 2811066Snilay@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, 358835SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 368835SN/A * 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/** 468893SN/A * @file 477513SN/A * Definition of a bus object. 489885SN/A */ 499885SN/A 509885SN/A#include "base/misc.hh" 5110315SN/A#include "base/trace.hh" 5210036SN/A#include "debug/Bus.hh" 5310315SN/A#include "debug/BusAddrRanges.hh" 549885SN/A#include "debug/Drain.hh" 559885SN/A#include "mem/bus.hh" 567513SN/A 577513SN/ABaseBus::BaseBus(const BaseBusParams *p) 5810038SN/A : MemObject(p), 5910315SN/A headerCycles(p->header_cycles), width(p->width), 607513SN/A gotAddrRanges(p->port_default_connection_count + 619885SN/A p->port_master_connection_count, false), 627513SN/A gotAllAddrRanges(false), defaultPortID(InvalidPortID), 6311570SCurtis.Dunham@arm.com useDefaultRange(p->use_default_range), 647513SN/A blockSize(p->block_size) 658835SN/A{} 667513SN/A 6710038SN/ABaseBus::~BaseBus() 687513SN/A{ 6910036SN/A for (MasterPortIter m = masterPorts.begin(); m != masterPorts.end(); 707513SN/A ++m) { 717513SN/A delete *m; 728835SN/A } 739481SN/A 7410038SN/A for (SlavePortIter s = slavePorts.begin(); s != slavePorts.end(); 757513SN/A ++s) { 767513SN/A delete *s; 777513SN/A } 787513SN/A} 797513SN/A 807513SN/Avoid 8111570SCurtis.Dunham@arm.comBaseBus::init() 8211570SCurtis.Dunham@arm.com{ 8311570SCurtis.Dunham@arm.com // determine the maximum peer block size, look at both the 8411570SCurtis.Dunham@arm.com // connected master and slave modules 858835SN/A uint32_t peer_block_size = 0; 867513SN/A 879885SN/A for (MasterPortConstIter m = masterPorts.begin(); m != masterPorts.end(); 8810315SN/A ++m) { 899481SN/A peer_block_size = std::max((*m)->peerBlockSize(), peer_block_size); 907513SN/A } 917513SN/A 927513SN/A for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end(); 937513SN/A ++s) { 947513SN/A peer_block_size = std::max((*s)->peerBlockSize(), peer_block_size); 957513SN/A } 967513SN/A 9711066Snilay@cs.wisc.edu // if the peers do not have a block size, use the default value 989885SN/A // set through the bus parameters 998893SN/A if (peer_block_size != 0) 1007513SN/A blockSize = peer_block_size; 1019885SN/A 10211219Snilay@cs.wisc.edu // check if the block size is a value known to work 10311570SCurtis.Dunham@arm.com if (blockSize != 16 || blockSize != 32 || blockSize != 64 || 10411066Snilay@cs.wisc.edu blockSize != 128) 10510036SN/A warn_once("Block size is neither 16, 32, 64 or 128 bytes.\n"); 1069481SN/A} 10711066Snilay@cs.wisc.edu 1087513SN/ABaseMasterPort & 1099481SN/ABaseBus::getMasterPort(const std::string &if_name, PortID idx) 11011570SCurtis.Dunham@arm.com{ 11111570SCurtis.Dunham@arm.com if (if_name == "master" && idx < masterPorts.size()) { 11211570SCurtis.Dunham@arm.com // the master port index translates directly to the vector position 11311570SCurtis.Dunham@arm.com return *masterPorts[idx]; 1147513SN/A } else if (if_name == "default") { 1158835SN/A return *masterPorts[defaultPortID]; 1169481SN/A } else { 11710036SN/A return MemObject::getMasterPort(if_name, idx); 1187513SN/A } 1198835SN/A} 1209885SN/A 1219481SN/ABaseSlavePort & 1227513SN/ABaseBus::getSlavePort(const std::string &if_name, PortID idx) 12311219Snilay@cs.wisc.edu{ 1247513SN/A if (if_name == "slave" && idx < slavePorts.size()) { 1258893SN/A // the slave port index translates directly to the vector position 1267513SN/A return *slavePorts[idx]; 1279885SN/A } else { 1289885SN/A return MemObject::getSlavePort(if_name, idx); 1299885SN/A } 1309885SN/A} 1319885SN/A 13211570SCurtis.Dunham@arm.comTick 13310036SN/ABaseBus::calcPacketTiming(PacketPtr pkt) 1349885SN/A{ 13511570SCurtis.Dunham@arm.com // determine the current time rounded to the closest following 13611570SCurtis.Dunham@arm.com // clock edge 13711570SCurtis.Dunham@arm.com Tick now = nextCycle(); 13811570SCurtis.Dunham@arm.com 13910036SN/A Tick headerTime = now + headerCycles * clock; 1409885SN/A 1419885SN/A // The packet will be sent. Figure out how long it occupies the bus, and 14210038SN/A // how much of that time is for the first "word", aka bus width. 14310038SN/A int numCycles = 0; 14410038SN/A if (pkt->hasData()) { 14510038SN/A // If a packet has data, it needs ceil(size/width) cycles to send it 14610038SN/A int dataSize = pkt->getSize(); 14711066Snilay@cs.wisc.edu numCycles += dataSize/width; 14810038SN/A if (dataSize % width) 14910038SN/A numCycles++; 15010038SN/A } 15110038SN/A 15210038SN/A // The first word will be delivered after the current tick, the delivery 15310038SN/A // of the address if any, and one bus cycle to deliver the data 15410038SN/A pkt->firstWordTime = headerTime + clock; 15510038SN/A 15610038SN/A pkt->finishTime = headerTime + numCycles * clock; 15710038SN/A 15810038SN/A return headerTime; 15910038SN/A} 16010038SN/A 16111570SCurtis.Dunham@arm.comtemplate <typename PortClass> 16210038SN/ABaseBus::Layer<PortClass>::Layer(BaseBus& _bus, const std::string& _name, 16310038SN/A Tick _clock) : 16410038SN/A bus(_bus), _name(_name), state(IDLE), clock(_clock), drainEvent(NULL), 16511570SCurtis.Dunham@arm.com releaseEvent(this) 16611570SCurtis.Dunham@arm.com{ 16711570SCurtis.Dunham@arm.com} 16811570SCurtis.Dunham@arm.com 16910038SN/Atemplate <typename PortClass> 17010038SN/Avoid BaseBus::Layer<PortClass>::occupyLayer(Tick until) 1717513SN/A{ 1727513SN/A // ensure the state is busy or in retry and never idle at this 1738835SN/A // point, as the bus should transition from idle as soon as it has 17410036SN/A // decided to forward the packet to prevent any follow-on calls to 17510038SN/A // sendTiming seeing an unoccupied bus 1767513SN/A assert(state != IDLE); 1778835SN/A 1788835SN/A // note that we do not change the bus state here, if we are going 1798835SN/A // from idle to busy it is handled by tryTiming, and if we 1808835SN/A // are in retry we should remain in retry such that 1819885SN/A // succeededTiming still sees the accurate state 18211570SCurtis.Dunham@arm.com 18310036SN/A // until should never be 0 as express snoops never occupy the bus 18410038SN/A assert(until != 0); 1859265SN/A bus.schedule(releaseEvent, until); 18611570SCurtis.Dunham@arm.com 18711570SCurtis.Dunham@arm.com DPRINTF(BaseBus, "The bus is now busy from tick %d to %d\n", 18811570SCurtis.Dunham@arm.com curTick(), until); 18911570SCurtis.Dunham@arm.com} 1908835SN/A 1918893SN/Atemplate <typename PortClass> 1927513SN/Abool 1937513SN/ABaseBus::Layer<PortClass>::tryTiming(PortClass* port) 19411066Snilay@cs.wisc.edu{ 1959885SN/A // first we see if the bus is busy, next we check if we are in a 1968893SN/A // retry with a port other than the current one 1977513SN/A if (state == BUSY || (state == RETRY && port != retryList.front())) { 1989885SN/A // put the port at the end of the retry list 19911219Snilay@cs.wisc.edu retryList.push_back(port); 20011570SCurtis.Dunham@arm.com return false; 20111066Snilay@cs.wisc.edu } 20210036SN/A 2039481SN/A // update the state which is shared for request, response and 20411066Snilay@cs.wisc.edu // snoop responses, if we were idle we are now busy, if we are in 2057513SN/A // a retry, then do not change 2069481SN/A if (state == IDLE) 20711570SCurtis.Dunham@arm.com state = BUSY; 20811570SCurtis.Dunham@arm.com 20911570SCurtis.Dunham@arm.com return true; 21011570SCurtis.Dunham@arm.com} 2117513SN/A 2128835SN/Atemplate <typename PortClass> 2139481SN/Avoid 21410036SN/ABaseBus::Layer<PortClass>::succeededTiming(Tick busy_time) 2157513SN/A{ 2168835SN/A // if a retrying port succeeded, also take it off the retry list 2179885SN/A if (state == RETRY) { 2189481SN/A DPRINTF(BaseBus, "Remove retry from list %s\n", 2197513SN/A retryList.front()->name()); 22011219Snilay@cs.wisc.edu retryList.pop_front(); 2217513SN/A state = BUSY; 2228893SN/A } 2237513SN/A 2249885SN/A // we should either have gone from idle to busy in the 2259885SN/A // tryTiming test, or just gone from a retry to busy 2269885SN/A assert(state == BUSY); 2279885SN/A 2289885SN/A // occupy the bus accordingly 22911570SCurtis.Dunham@arm.com occupyLayer(busy_time); 23010036SN/A} 2319885SN/A 23211570SCurtis.Dunham@arm.comtemplate <typename PortClass> 23311570SCurtis.Dunham@arm.comvoid 23411570SCurtis.Dunham@arm.comBaseBus::Layer<PortClass>::failedTiming(PortClass* port, Tick busy_time) 23511570SCurtis.Dunham@arm.com{ 23610036SN/A // if we are not in a retry, i.e. busy (but never idle), or we are 2379885SN/A // in a retry but not for the current port, then add the port at 2389885SN/A // the end of the retry list 2398835SN/A if (state != RETRY || port != retryList.front()) { 2408835SN/A retryList.push_back(port); 24110036SN/A } 2428835SN/A 2439481SN/A // even if we retried the current one and did not succeed, 2449481SN/A // we are no longer retrying but instead busy 24511219Snilay@cs.wisc.edu state = BUSY; 24610036SN/A 2479481SN/A // occupy the bus accordingly 24810038SN/A occupyLayer(busy_time); 24910038SN/A} 25010038SN/A 25110038SN/Atemplate <typename PortClass> 25210038SN/Avoid 25310038SN/ABaseBus::Layer<PortClass>::releaseLayer() 25410038SN/A{ 25510038SN/A // releasing the bus means we should now be idle 25610038SN/A assert(state == BUSY); 25710038SN/A assert(!releaseEvent.scheduled()); 2589481SN/A 2599481SN/A // update the state 2609481SN/A state = IDLE; 2619481SN/A 2629481SN/A // bus is now idle, so if someone is waiting we can retry 2639481SN/A if (!retryList.empty()) { 26410038SN/A // note that we block (return false on recvTiming) both 2659481SN/A // because the bus is busy and because the destination is 2669481SN/A // busy, and in the latter case the bus may be released before 26710038SN/A // we see a retry from the destination 2689481SN/A retryWaiting(); 26910038SN/A } else if (drainEvent) { 27010038SN/A DPRINTF(Drain, "Bus done draining, processing drain event\n"); 27111066Snilay@cs.wisc.edu //If we weren't able to drain before, do it now. 27210038SN/A drainEvent->process(); 27310038SN/A // Clear the drain event once we're done with it. 27410038SN/A drainEvent = NULL; 27510038SN/A } 27610038SN/A} 27710038SN/A 27810038SN/Atemplate <typename PortClass> 27911066Snilay@cs.wisc.eduvoid 28010038SN/ABaseBus::Layer<PortClass>::retryWaiting() 28110038SN/A{ 28210038SN/A // this should never be called with an empty retry list 28310038SN/A assert(!retryList.empty()); 28410038SN/A 28510038SN/A // we always go to retrying from idle 28610038SN/A assert(state == IDLE); 28710038SN/A 28810038SN/A // update the state which is shared for request, response and 28910038SN/A // snoop responses 29010038SN/A state = RETRY; 29110038SN/A 29210038SN/A // note that we might have blocked on the receiving port being 29311570SCurtis.Dunham@arm.com // busy (rather than the bus itself) and now call retry before the 29410038SN/A // destination called retry on the bus 29510038SN/A retryList.front()->sendRetry(); 29610038SN/A 29711570SCurtis.Dunham@arm.com // If the bus is still in the retry state, sendTiming wasn't 29811570SCurtis.Dunham@arm.com // called in zero time (e.g. the cache does this) 29911570SCurtis.Dunham@arm.com if (state == RETRY) { 30011570SCurtis.Dunham@arm.com retryList.pop_front(); 30110038SN/A 3029481SN/A //Burn a cycle for the missed grant. 3037513SN/A 3047513SN/A // update the state which is shared for request, response and 3058835SN/A // snoop responses 30610036SN/A state = BUSY; 30710038SN/A 3087513SN/A // determine the current time rounded to the closest following 3098835SN/A // clock edge 3108835SN/A Tick now = bus.nextCycle(); 3118835SN/A 3128835SN/A occupyLayer(now + clock); 3139885SN/A } 31411570SCurtis.Dunham@arm.com} 31510036SN/A 31610038SN/Atemplate <typename PortClass> 3179265SN/Avoid 31811570SCurtis.Dunham@arm.comBaseBus::Layer<PortClass>::recvRetry() 31911570SCurtis.Dunham@arm.com{ 32011570SCurtis.Dunham@arm.com // we got a retry from a peer that we tried to send something to 32111570SCurtis.Dunham@arm.com // and failed, but we sent it on the account of someone else, and 3228835SN/A // that source port should be on our retry list, however if the 3238893SN/A // bus layer is released before this happens and the retry (from 3247513SN/A // the bus point of view) is successful then this no longer holds 3257513SN/A // and we could in fact have an empty retry list 32611066Snilay@cs.wisc.edu if (retryList.empty()) 3279885SN/A return; 3288893SN/A 3299481SN/A // if the bus layer is idle 3309885SN/A if (state == IDLE) { 33111219Snilay@cs.wisc.edu // note that we do not care who told us to retry at the moment, we 33211570SCurtis.Dunham@arm.com // merely let the first one on the retry list go 33311066Snilay@cs.wisc.edu retryWaiting(); 33410036SN/A } 3359481SN/A} 33611066Snilay@cs.wisc.edu 3377513SN/APortID 3389481SN/ABaseBus::findPort(Addr addr) 33911570SCurtis.Dunham@arm.com{ 34011570SCurtis.Dunham@arm.com // we should never see any address lookups before we've got the 34111570SCurtis.Dunham@arm.com // ranges of all connected slave modules 34211570SCurtis.Dunham@arm.com assert(gotAllAddrRanges); 3437513SN/A 3448835SN/A // Check the cache 3459481SN/A PortID dest_id = checkPortCache(addr); 34610036SN/A if (dest_id != InvalidPortID) 3477513SN/A return dest_id; 3488835SN/A 3499885SN/A // Check the address map interval tree 3509481SN/A PortMapConstIter i = portMap.find(addr); 3517513SN/A if (i != portMap.end()) { 35211219Snilay@cs.wisc.edu dest_id = i->second; 3538893SN/A updatePortCache(dest_id, i->first); 3548893SN/A return dest_id; 3557513SN/A } 3569885SN/A 3579885SN/A // Check if this matches the default range 3589885SN/A if (useDefaultRange) { 3599885SN/A if (defaultRange == addr) { 3609885SN/A DPRINTF(BusAddrRanges, " found addr %#llx on default\n", 36111570SCurtis.Dunham@arm.com addr); 36210036SN/A return defaultPortID; 3639885SN/A } 36411570SCurtis.Dunham@arm.com } else if (defaultPortID != InvalidPortID) { 36511570SCurtis.Dunham@arm.com DPRINTF(BusAddrRanges, "Unable to find destination for addr %#llx, " 36611570SCurtis.Dunham@arm.com "will use default port\n", addr); 36711570SCurtis.Dunham@arm.com return defaultPortID; 36810036SN/A } 3699885SN/A 3709885SN/A // we should use the range for the default port and it did not 3717513SN/A // match, or the default port is not set 37210451SN/A fatal("Unable to find destination for addr %#llx on bus %s\n", addr, 37311219Snilay@cs.wisc.edu name()); 3749885SN/A} 37511570SCurtis.Dunham@arm.com 37610036SN/A/** Function called by the port when the bus is receiving a range change.*/ 37711066Snilay@cs.wisc.eduvoid 37811066Snilay@cs.wisc.eduBaseBus::recvRangeChange(PortID master_port_id) 37911570SCurtis.Dunham@arm.com{ 38011570SCurtis.Dunham@arm.com // remember that we got a range from this master port and thus the 38111570SCurtis.Dunham@arm.com // connected slave module 38211388Ssteve.reinhardt@amd.com gotAddrRanges[master_port_id] = true; 38311570SCurtis.Dunham@arm.com 38411066Snilay@cs.wisc.edu // update the global flag 38511219Snilay@cs.wisc.edu if (!gotAllAddrRanges) { 38611066Snilay@cs.wisc.edu // take a logical AND of all the ports and see if we got 3879885SN/A // ranges from everyone 3887524SN/A gotAllAddrRanges = true; 3899481SN/A std::vector<bool>::const_iterator r = gotAddrRanges.begin(); 3908893SN/A while (gotAllAddrRanges && r != gotAddrRanges.end()) { 39111066Snilay@cs.wisc.edu gotAllAddrRanges &= *r++; 3927513SN/A } 39311219Snilay@cs.wisc.edu } 39411219Snilay@cs.wisc.edu 39511219Snilay@cs.wisc.edu // note that we could get the range from the default port at any 39611219Snilay@cs.wisc.edu // point in time, and we cannot assume that the default range is 39711219Snilay@cs.wisc.edu // set before the other ones are, so we do additional checks once 39811219Snilay@cs.wisc.edu // all ranges are provided 39911219Snilay@cs.wisc.edu DPRINTF(BusAddrRanges, "received RangeChange from slave port %s\n", 4007513SN/A masterPorts[master_port_id]->getSlavePort().name()); 4017513SN/A 40210036SN/A if (master_port_id == defaultPortID) { 4037513SN/A // only update if we are indeed checking ranges for the 4047513SN/A // default port since the port might not have a valid range 4057513SN/A // otherwise 4067513SN/A if (useDefaultRange) { 40711066Snilay@cs.wisc.edu AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges(); 40811066Snilay@cs.wisc.edu 4097513SN/A if (ranges.size() != 1) 4107513SN/A fatal("Bus %s may only have a single default range", 4117513SN/A name()); 4127513SN/A 41310036SN/A defaultRange = ranges.front(); 41411570SCurtis.Dunham@arm.com } 4157513SN/A } else { 4167513SN/A // the ports are allowed to update their address ranges 41711066Snilay@cs.wisc.edu // dynamically, so remove any existing entries 4187513SN/A if (gotAddrRanges[master_port_id]) { 4197513SN/A for (PortMapIter p = portMap.begin(); p != portMap.end(); ) { 4207513SN/A if (p->second == master_port_id) 4217513SN/A // erasing invalidates the iterator, so advance it 4227513SN/A // before the deletion takes place 4237513SN/A portMap.erase(p++); 4247513SN/A else 42510451SN/A p++; 4267513SN/A } 4279885SN/A } 4289885SN/A 4299885SN/A AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges(); 43010315SN/A 43110036SN/A for (AddrRangeConstIter r = ranges.begin(); r != ranges.end(); ++r) { 43210315SN/A DPRINTF(BusAddrRanges, "Adding range %#llx : %#llx for id %d\n", 4339885SN/A r->start, r->end, master_port_id); 4349885SN/A if (portMap.insert(*r, master_port_id) == portMap.end()) { 43510315SN/A PortID conflict_id = portMap.find(*r)->second; 43610315SN/A fatal("%s has two ports with same range:\n\t%s\n\t%s\n", 43710315SN/A name(), 43810315SN/A masterPorts[master_port_id]->getSlavePort().name(), 43910315SN/A masterPorts[conflict_id]->getSlavePort().name()); 44010315SN/A } 44110315SN/A } 44210315SN/A } 4437513SN/A 44410451SN/A // if we have received ranges from all our neighbouring slave 4459885SN/A // modules, go ahead and tell our connected master modules in 44611570SCurtis.Dunham@arm.com // turn, this effectively assumes a tree structure of the system 44710036SN/A if (gotAllAddrRanges) { 44811066Snilay@cs.wisc.edu // also check that no range partially overlaps with the 44911066Snilay@cs.wisc.edu // default range, this has to be done after all ranges are set 45011570SCurtis.Dunham@arm.com // as there are no guarantees for when the default range is 45111570SCurtis.Dunham@arm.com // update with respect to the other ones 45211570SCurtis.Dunham@arm.com if (useDefaultRange) { 45311388Ssteve.reinhardt@amd.com for (PortID port_id = 0; port_id < masterPorts.size(); ++port_id) { 45411570SCurtis.Dunham@arm.com if (port_id == defaultPortID) { 45511066Snilay@cs.wisc.edu if (!gotAddrRanges[port_id]) 45610451SN/A fatal("Bus %s uses default range, but none provided", 45711066Snilay@cs.wisc.edu name()); 4589885SN/A } else { 4597524SN/A AddrRangeList ranges = 46011066Snilay@cs.wisc.edu masterPorts[port_id]->getAddrRanges(); 4619265SN/A 4628893SN/A for (AddrRangeConstIter r = ranges.begin(); 4637513SN/A r != ranges.end(); ++r) { 4647513SN/A // see if the new range is partially 4658983SN/A // overlapping the default range 4669265SN/A if (r->intersects(defaultRange) && 4679885SN/A !r->isSubset(defaultRange)) 4689885SN/A fatal("Range %#llx : %#llx intersects the " \ 46911570SCurtis.Dunham@arm.com "default range of %s but is not a " \ 47010036SN/A "subset\n", r->start, r->end, name()); 4718983SN/A } 4727513SN/A } 4737513SN/A } 4747513SN/A } 47511570SCurtis.Dunham@arm.com 47611570SCurtis.Dunham@arm.com // tell all our neighbouring master ports that our address 47711570SCurtis.Dunham@arm.com // ranges have changed 47811570SCurtis.Dunham@arm.com for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end(); 4797513SN/A ++s) 4808893SN/A (*s)->sendRangeChange(); 4817513SN/A } 4829885SN/A 4839885SN/A clearPortCache(); 48410036SN/A} 4859885SN/A 4869885SN/AAddrRangeList 487BaseBus::getAddrRanges() const 488{ 489 // we should never be asked without first having sent a range 490 // change, and the latter is only done once we have all the ranges 491 // of the connected devices 492 assert(gotAllAddrRanges); 493 494 DPRINTF(BusAddrRanges, "received address range request, returning:\n"); 495 496 // start out with the default range 497 AddrRangeList ranges; 498 ranges.push_back(defaultRange); 499 DPRINTF(BusAddrRanges, " -- %#llx : %#llx DEFAULT\n", 500 defaultRange.start, defaultRange.end); 501 502 // add any range that is not a subset of the default range 503 for (PortMapConstIter p = portMap.begin(); p != portMap.end(); ++p) { 504 if (useDefaultRange && p->first.isSubset(defaultRange)) { 505 DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n", 506 p->first.start, p->first.end); 507 } else { 508 ranges.push_back(p->first); 509 DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", 510 p->first.start, p->first.end); 511 } 512 } 513 514 return ranges; 515} 516 517unsigned 518BaseBus::deviceBlockSize() const 519{ 520 return blockSize; 521} 522 523template <typename PortClass> 524unsigned int 525BaseBus::Layer<PortClass>::drain(Event * de) 526{ 527 //We should check that we're not "doing" anything, and that noone is 528 //waiting. We might be idle but have someone waiting if the device we 529 //contacted for a retry didn't actually retry. 530 if (!retryList.empty() || state != IDLE) { 531 DPRINTF(Drain, "Bus not drained\n"); 532 drainEvent = de; 533 return 1; 534 } 535 return 0; 536} 537 538/** 539 * Bus layer template instantiations. Could be removed with _impl.hh 540 * file, but since there are only two given options (MasterPort and 541 * SlavePort) it seems a bit excessive at this point. 542 */ 543template class BaseBus::Layer<SlavePort>; 544template class BaseBus::Layer<MasterPort>; 545