xbar.cc revision 9715
12623SN/A/* 22623SN/A * Copyright (c) 2011-2013 ARM Limited 32623SN/A * All rights reserved 42623SN/A * 52623SN/A * The license below extends only to copyright in the software and shall 62623SN/A * not be construed as granting a license to any other intellectual 72623SN/A * property including but not limited to intellectual property relating 82623SN/A * to a hardware implementation of the functionality of the software 92623SN/A * licensed hereunder. You may use the software subject to the license 102623SN/A * terms below provided that you ensure that this notice is replicated 112623SN/A * unmodified and in its entirety in all distributions of the software, 122623SN/A * modified or unmodified, in source code or in binary form. 132623SN/A * 142623SN/A * Copyright (c) 2006 The Regents of The University of Michigan 152623SN/A * All rights reserved. 162623SN/A * 172623SN/A * Redistribution and use in source and binary forms, with or without 182623SN/A * modification, are permitted provided that the following conditions are 192623SN/A * met: redistributions of source code must retain the above copyright 202623SN/A * notice, this list of conditions and the following disclaimer; 212623SN/A * redistributions in binary form must reproduce the above copyright 222623SN/A * notice, this list of conditions and the following disclaimer in the 232623SN/A * documentation and/or other materials provided with the distribution; 242623SN/A * neither the name of the copyright holders nor the names of its 252623SN/A * contributors may be used to endorse or promote products derived from 262623SN/A * this software without specific prior written permission. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392623SN/A * 402856Srdreslin@umich.edu * Authors: Ali Saidi 412856Srdreslin@umich.edu * Andreas Hansson 422856Srdreslin@umich.edu * William Wang 432856Srdreslin@umich.edu */ 442856Srdreslin@umich.edu 452856Srdreslin@umich.edu/** 462856Srdreslin@umich.edu * @file 472856Srdreslin@umich.edu * Definition of a bus object. 482856Srdreslin@umich.edu */ 492856Srdreslin@umich.edu 502623SN/A#include "base/misc.hh" 512623SN/A#include "base/trace.hh" 522623SN/A#include "debug/Bus.hh" 532623SN/A#include "debug/BusAddrRanges.hh" 542623SN/A#include "debug/Drain.hh" 552623SN/A#include "mem/bus.hh" 562680Sktlim@umich.edu 572680Sktlim@umich.eduBaseBus::BaseBus(const BaseBusParams *p) 582623SN/A : MemObject(p), 592623SN/A headerCycles(p->header_cycles), width(p->width), 602680Sktlim@umich.edu gotAddrRanges(p->port_default_connection_count + 612623SN/A p->port_master_connection_count, false), 622623SN/A gotAllAddrRanges(false), defaultPortID(InvalidPortID), 632623SN/A useDefaultRange(p->use_default_range), 642623SN/A blockSize(p->block_size) 652623SN/A{} 662630SN/A 672623SN/ABaseBus::~BaseBus() 682623SN/A{ 692623SN/A for (MasterPortIter m = masterPorts.begin(); m != masterPorts.end(); 702623SN/A ++m) { 712623SN/A delete *m; 722623SN/A } 732630SN/A 742623SN/A for (SlavePortIter s = slavePorts.begin(); s != slavePorts.end(); 752623SN/A ++s) { 762623SN/A delete *s; 772623SN/A } 782623SN/A} 792623SN/A 802623SN/Avoid 812631SN/ABaseBus::init() 822631SN/A{ 832631SN/A // determine the maximum peer block size, look at both the 842623SN/A // connected master and slave modules 852623SN/A uint32_t peer_block_size = 0; 862623SN/A 872623SN/A for (MasterPortConstIter m = masterPorts.begin(); m != masterPorts.end(); 882623SN/A ++m) { 892623SN/A peer_block_size = std::max((*m)->peerBlockSize(), peer_block_size); 902623SN/A } 912623SN/A 922839Sktlim@umich.edu for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end(); 932798Sktlim@umich.edu ++s) { 942623SN/A peer_block_size = std::max((*s)->peerBlockSize(), peer_block_size); 952623SN/A } 962623SN/A 972623SN/A // if the peers do not have a block size, use the default value 982623SN/A // set through the bus parameters 992623SN/A if (peer_block_size != 0) 1002623SN/A blockSize = peer_block_size; 1012623SN/A 1022623SN/A // check if the block size is a value known to work 1032623SN/A if (!(blockSize == 16 || blockSize == 32 || blockSize == 64 || 1042798Sktlim@umich.edu blockSize == 128)) 1052623SN/A warn_once("Block size is neither 16, 32, 64 or 128 bytes.\n"); 1062623SN/A} 1072623SN/A 1082623SN/ABaseMasterPort & 1092623SN/ABaseBus::getMasterPort(const std::string &if_name, PortID idx) 1102623SN/A{ 1112798Sktlim@umich.edu if (if_name == "master" && idx < masterPorts.size()) { 1122623SN/A // the master port index translates directly to the vector position 1132798Sktlim@umich.edu return *masterPorts[idx]; 1142798Sktlim@umich.edu } else if (if_name == "default") { 1152798Sktlim@umich.edu return *masterPorts[defaultPortID]; 1162839Sktlim@umich.edu } else { 1172798Sktlim@umich.edu return MemObject::getMasterPort(if_name, idx); 1182839Sktlim@umich.edu } 1192798Sktlim@umich.edu} 1202798Sktlim@umich.edu 1212839Sktlim@umich.eduBaseSlavePort & 1222798Sktlim@umich.eduBaseBus::getSlavePort(const std::string &if_name, PortID idx) 1232798Sktlim@umich.edu{ 1242839Sktlim@umich.edu if (if_name == "slave" && idx < slavePorts.size()) { 1252839Sktlim@umich.edu // the slave port index translates directly to the vector position 1262798Sktlim@umich.edu return *slavePorts[idx]; 1272798Sktlim@umich.edu } else { 1282623SN/A return MemObject::getSlavePort(if_name, idx); 1292623SN/A } 1302623SN/A} 1312798Sktlim@umich.edu 1322623SN/Avoid 1332798Sktlim@umich.eduBaseBus::calcPacketTiming(PacketPtr pkt) 1342798Sktlim@umich.edu{ 1352798Sktlim@umich.edu // the bus will be called at a time that is not necessarily 1362798Sktlim@umich.edu // coinciding with its own clock, so start by determining how long 1372623SN/A // until the next clock edge (could be zero) 1382798Sktlim@umich.edu Tick offset = clockEdge() - curTick(); 1392798Sktlim@umich.edu 1402798Sktlim@umich.edu // determine how many cycles are needed to send the data 1412798Sktlim@umich.edu unsigned dataCycles = pkt->hasData() ? divCeil(pkt->getSize(), width) : 0; 1422798Sktlim@umich.edu 1432798Sktlim@umich.edu // before setting the bus delay fields of the packet, ensure that 1442798Sktlim@umich.edu // the delay from any previous bus has been accounted for 1452798Sktlim@umich.edu if (pkt->busFirstWordDelay != 0 || pkt->busLastWordDelay != 0) 1462798Sktlim@umich.edu panic("Packet %s already has bus delay (%d, %d) that should be " 1472798Sktlim@umich.edu "accounted for.\n", pkt->cmdString(), pkt->busFirstWordDelay, 1482798Sktlim@umich.edu pkt->busLastWordDelay); 1492798Sktlim@umich.edu 1502798Sktlim@umich.edu // The first word will be delivered on the cycle after the header. 1512623SN/A pkt->busFirstWordDelay = (headerCycles + 1) * clockPeriod() + offset; 1522623SN/A 1532623SN/A // Note that currently busLastWordDelay can be smaller than 1542623SN/A // busFirstWordDelay if the packet has no data 1552623SN/A pkt->busLastWordDelay = (headerCycles + dataCycles) * clockPeriod() + 1562623SN/A offset; 1572623SN/A} 1582623SN/A 1592680Sktlim@umich.edutemplate <typename SrcType, typename DstType> 1602623SN/ABaseBus::Layer<SrcType,DstType>::Layer(DstType& _port, BaseBus& _bus, 1612680Sktlim@umich.edu const std::string& _name) : 1622680Sktlim@umich.edu port(_port), bus(_bus), _name(_name), state(IDLE), drainManager(NULL), 1632680Sktlim@umich.edu retryingPort(NULL), waitingForPeer(NULL), 1642623SN/A releaseEvent(this) 1652623SN/A{ 1662623SN/A} 1672623SN/A 1682623SN/Atemplate <typename SrcType, typename DstType> 1692623SN/Avoid BaseBus::Layer<SrcType,DstType>::occupyLayer(Tick until) 1702623SN/A{ 1712623SN/A // ensure the state is busy at this point, as the bus should 1722623SN/A // transition from idle as soon as it has decided to forward the 1732623SN/A // packet to prevent any follow-on calls to sendTiming seeing an 1742623SN/A // unoccupied bus 1752683Sktlim@umich.edu assert(state == BUSY); 1762623SN/A 1772623SN/A // until should never be 0 as express snoops never occupy the bus 1782623SN/A assert(until != 0); 1792623SN/A bus.schedule(releaseEvent, until); 1802623SN/A 1812623SN/A // account for the occupied ticks 1822623SN/A occupancy += until - curTick(); 1832623SN/A 1842623SN/A DPRINTF(BaseBus, "The bus is now busy from tick %d to %d\n", 1852623SN/A curTick(), until); 1862623SN/A} 1872623SN/A 1882623SN/Atemplate <typename SrcType, typename DstType> 1892623SN/Abool 1902623SN/ABaseBus::Layer<SrcType,DstType>::tryTiming(SrcType* src_port) 1912623SN/A{ 1922683Sktlim@umich.edu // first we see if the layer is busy, next we check if we are in a 1932623SN/A // retry with a port other than the current one, lastly we check 1942644Sstever@eecs.umich.edu // if the destination port is already engaged in a transaction 1952623SN/A // waiting for a retry from the peer 1962644Sstever@eecs.umich.edu if (state == BUSY || (state == RETRY && src_port != retryingPort) || 1972644Sstever@eecs.umich.edu waitingForPeer != NULL) { 1982623SN/A // put the port at the end of the retry list waiting for the 1992623SN/A // layer to be freed up (and in the case of a busy peer, for 2002623SN/A // that transaction to go through, and then the bus to free 2012623SN/A // up) 2022623SN/A waitingForLayer.push_back(src_port); 2032623SN/A return false; 2042623SN/A } 2052623SN/A 2062623SN/A // update the state to busy 2072623SN/A state = BUSY; 2082663Sstever@eecs.umich.edu 2092663Sstever@eecs.umich.edu // reset the retrying port 2102835Srdreslin@umich.edu retryingPort = NULL; 2112683Sktlim@umich.edu 2122623SN/A return true; 2132623SN/A} 2142623SN/A 2152623SN/Atemplate <typename SrcType, typename DstType> 2162623SN/Avoid 2172623SN/ABaseBus::Layer<SrcType,DstType>::succeededTiming(Tick busy_time) 2182683Sktlim@umich.edu{ 2192623SN/A // we should have gone from idle or retry to busy in the tryTiming 2202623SN/A // test 2212623SN/A assert(state == BUSY); 2222641Sstever@eecs.umich.edu 2232641Sstever@eecs.umich.edu // occupy the bus accordingly 2242623SN/A occupyLayer(busy_time); 2252623SN/A} 2262630SN/A 2272623SN/Atemplate <typename SrcType, typename DstType> 2282623SN/Avoid 2292623SN/ABaseBus::Layer<SrcType,DstType>::failedTiming(SrcType* src_port, 2302623SN/A Tick busy_time) 2312623SN/A{ 2322623SN/A // ensure no one got in between and tried to send something to 2332623SN/A // this port 2342623SN/A assert(waitingForPeer == NULL); 2352623SN/A 2362623SN/A // if the source port is the current retrying one or not, we have 2372623SN/A // failed in forwarding and should track that we are now waiting 2382623SN/A // for the peer to send a retry 2392623SN/A waitingForPeer = src_port; 2402623SN/A 2412623SN/A // we should have gone from idle or retry to busy in the tryTiming 2422623SN/A // test 2432623SN/A assert(state == BUSY); 2442623SN/A 2452623SN/A // occupy the bus accordingly 2462623SN/A occupyLayer(busy_time); 2472623SN/A} 2482623SN/A 2492623SN/Atemplate <typename SrcType, typename DstType> 2502623SN/Avoid 2512623SN/ABaseBus::Layer<SrcType,DstType>::releaseLayer() 2522623SN/A{ 2532623SN/A // releasing the bus means we should now be idle 2542623SN/A assert(state == BUSY); 2552623SN/A assert(!releaseEvent.scheduled()); 2562623SN/A 2572623SN/A // update the state 2582623SN/A state = IDLE; 2592623SN/A 2602623SN/A // bus layer is now idle, so if someone is waiting we can retry 2612623SN/A if (!waitingForLayer.empty()) { 2622623SN/A retryWaiting(); 2632623SN/A } else if (waitingForPeer == NULL && drainManager) { 2642623SN/A DPRINTF(Drain, "Bus done draining, signaling drain manager\n"); 2652623SN/A //If we weren't able to drain before, do it now. 2662623SN/A drainManager->signalDrainDone(); 2672623SN/A // Clear the drain event once we're done with it. 2682623SN/A drainManager = NULL; 2692623SN/A } 2702623SN/A} 2712623SN/A 2722623SN/Atemplate <typename SrcType, typename DstType> 2732623SN/Avoid 2742623SN/ABaseBus::Layer<SrcType,DstType>::retryWaiting() 2752623SN/A{ 2762623SN/A // this should never be called with no one waiting 2772623SN/A assert(!waitingForLayer.empty()); 2782623SN/A 2792623SN/A // we always go to retrying from idle 2802623SN/A assert(state == IDLE); 2812623SN/A 2822623SN/A // update the state 2832623SN/A state = RETRY; 2842623SN/A 2852623SN/A // set the retrying port to the front of the retry list and pop it 2862623SN/A // off the list 2872623SN/A assert(retryingPort == NULL); 2882623SN/A retryingPort = waitingForLayer.front(); 2892663Sstever@eecs.umich.edu waitingForLayer.pop_front(); 2902663Sstever@eecs.umich.edu 2912835Srdreslin@umich.edu // tell the port to retry, which in some cases ends up calling the 2922683Sktlim@umich.edu // bus 2932623SN/A retryingPort->sendRetry(); 2942623SN/A 2952683Sktlim@umich.edu // If the bus is still in the retry state, sendTiming wasn't 2962623SN/A // called in zero time (e.g. the cache does this), burn a cycle 2972623SN/A if (state == RETRY) { 2982641Sstever@eecs.umich.edu // update the state to busy and reset the retrying port, we 2992641Sstever@eecs.umich.edu // have done our bit and sent the retry 3002623SN/A state = BUSY; 3012623SN/A retryingPort = NULL; 3022623SN/A 3032630SN/A // occupy the bus layer until the next cycle ends 3042623SN/A occupyLayer(bus.clockEdge(Cycles(1))); 3052623SN/A } 3062623SN/A} 3072623SN/A 3082623SN/Atemplate <typename SrcType, typename DstType> 3092623SN/Avoid 3102623SN/ABaseBus::Layer<SrcType,DstType>::recvRetry() 3112623SN/A{ 3122623SN/A // we should never get a retry without having failed to forward 3132623SN/A // something to this port 3142623SN/A assert(waitingForPeer != NULL); 3152623SN/A 3162623SN/A // add the port where the failed packet originated to the front of 3172623SN/A // the waiting ports for the layer, this allows us to call retry 3182623SN/A // on the port immediately if the bus layer is idle 3192623SN/A waitingForLayer.push_front(waitingForPeer); 3202623SN/A 3212623SN/A // we are no longer waiting for the peer 3222623SN/A waitingForPeer = NULL; 3232623SN/A 3242623SN/A // if the bus layer is idle, retry this port straight away, if we 3252623SN/A // are busy, then simply let the port wait for its turn 3262623SN/A if (state == IDLE) { 3272623SN/A retryWaiting(); 3282623SN/A } else { 3292623SN/A assert(state == BUSY); 3302623SN/A } 3312623SN/A} 3322623SN/A 3332623SN/APortID 3342623SN/ABaseBus::findPort(Addr addr) 3352623SN/A{ 3362623SN/A // we should never see any address lookups before we've got the 3372623SN/A // ranges of all connected slave modules 3382623SN/A assert(gotAllAddrRanges); 3392623SN/A 3402623SN/A // Check the cache 3412623SN/A PortID dest_id = checkPortCache(addr); 3422623SN/A if (dest_id != InvalidPortID) 3432623SN/A return dest_id; 3442623SN/A 3452623SN/A // Check the address map interval tree 3462623SN/A PortMapConstIter i = portMap.find(addr); 3472623SN/A if (i != portMap.end()) { 3482623SN/A dest_id = i->second; 3492623SN/A updatePortCache(dest_id, i->first); 3502623SN/A return dest_id; 3512623SN/A } 3522623SN/A 3532623SN/A // Check if this matches the default range 3542623SN/A if (useDefaultRange) { 3552623SN/A if (defaultRange.contains(addr)) { 3562623SN/A DPRINTF(BusAddrRanges, " found addr %#llx on default\n", 3572623SN/A addr); 3582623SN/A return defaultPortID; 3592623SN/A } 3602623SN/A } else if (defaultPortID != InvalidPortID) { 3612623SN/A DPRINTF(BusAddrRanges, "Unable to find destination for addr %#llx, " 3622623SN/A "will use default port\n", addr); 3632623SN/A return defaultPortID; 3642623SN/A } 3652623SN/A 3662623SN/A // we should use the range for the default port and it did not 3672623SN/A // match, or the default port is not set 3682623SN/A fatal("Unable to find destination for addr %#llx on bus %s\n", addr, 3692623SN/A name()); 3702623SN/A} 3712631SN/A 3722631SN/A/** Function called by the port when the bus is receiving a range change.*/ 3732663Sstever@eecs.umich.eduvoid 3742663Sstever@eecs.umich.eduBaseBus::recvRangeChange(PortID master_port_id) 3752835Srdreslin@umich.edu{ 3762662Sstever@eecs.umich.edu DPRINTF(BusAddrRanges, "Received range change from slave port %s\n", 3772623SN/A masterPorts[master_port_id]->getSlavePort().name()); 3782641Sstever@eecs.umich.edu 3792623SN/A // remember that we got a range from this master port and thus the 3802623SN/A // connected slave module 3812623SN/A gotAddrRanges[master_port_id] = true; 3822630SN/A 3832623SN/A // update the global flag 3842623SN/A if (!gotAllAddrRanges) { 3852623SN/A // take a logical AND of all the ports and see if we got 3862623SN/A // ranges from everyone 3872623SN/A gotAllAddrRanges = true; 3882623SN/A std::vector<bool>::const_iterator r = gotAddrRanges.begin(); 3892623SN/A while (gotAllAddrRanges && r != gotAddrRanges.end()) { 3902623SN/A gotAllAddrRanges &= *r++; 3912623SN/A } 3922644Sstever@eecs.umich.edu if (gotAllAddrRanges) 3932644Sstever@eecs.umich.edu DPRINTF(BusAddrRanges, "Got address ranges from all slaves\n"); 3942623SN/A } 3952623SN/A 3962623SN/A // note that we could get the range from the default port at any 3972623SN/A // point in time, and we cannot assume that the default range is 3982623SN/A // set before the other ones are, so we do additional checks once 3992644Sstever@eecs.umich.edu // all ranges are provided 4002623SN/A if (master_port_id == defaultPortID) { 4012623SN/A // only update if we are indeed checking ranges for the 4022623SN/A // default port since the port might not have a valid range 4032631SN/A // otherwise 4042631SN/A if (useDefaultRange) { 4052631SN/A AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges(); 4062631SN/A 4072631SN/A if (ranges.size() != 1) 4082631SN/A fatal("Bus %s may only have a single default range", 4092623SN/A name()); 4102623SN/A 4112623SN/A defaultRange = ranges.front(); 4122623SN/A } 4132644Sstever@eecs.umich.edu } else { 4142623SN/A // the ports are allowed to update their address ranges 4152623SN/A // dynamically, so remove any existing entries 4162623SN/A if (gotAddrRanges[master_port_id]) { 4172644Sstever@eecs.umich.edu for (PortMapIter p = portMap.begin(); p != portMap.end(); ) { 4182623SN/A if (p->second == master_port_id) 4192798Sktlim@umich.edu // erasing invalidates the iterator, so advance it 4202623SN/A // before the deletion takes place 4212644Sstever@eecs.umich.edu portMap.erase(p++); 4222644Sstever@eecs.umich.edu else 4232644Sstever@eecs.umich.edu p++; 4242644Sstever@eecs.umich.edu } 4252839Sktlim@umich.edu } 4262839Sktlim@umich.edu 4272798Sktlim@umich.edu AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges(); 4282798Sktlim@umich.edu 4292798Sktlim@umich.edu for (AddrRangeConstIter r = ranges.begin(); r != ranges.end(); ++r) { 4302623SN/A DPRINTF(BusAddrRanges, "Adding range %s for id %d\n", 4312644Sstever@eecs.umich.edu r->to_string(), master_port_id); 4322623SN/A if (portMap.insert(*r, master_port_id) == portMap.end()) { 4332623SN/A PortID conflict_id = portMap.find(*r)->second; 4342644Sstever@eecs.umich.edu fatal("%s has two ports with same range:\n\t%s\n\t%s\n", 4352644Sstever@eecs.umich.edu name(), 4362644Sstever@eecs.umich.edu masterPorts[master_port_id]->getSlavePort().name(), 4372644Sstever@eecs.umich.edu masterPorts[conflict_id]->getSlavePort().name()); 4382644Sstever@eecs.umich.edu } 4392644Sstever@eecs.umich.edu } 4402644Sstever@eecs.umich.edu } 4412644Sstever@eecs.umich.edu 4422644Sstever@eecs.umich.edu // if we have received ranges from all our neighbouring slave 4432623SN/A // modules, go ahead and tell our connected master modules in 4442623SN/A // turn, this effectively assumes a tree structure of the system 4452623SN/A if (gotAllAddrRanges) { 4462644Sstever@eecs.umich.edu DPRINTF(BusAddrRanges, "Aggregating bus ranges\n"); 4472644Sstever@eecs.umich.edu busRanges.clear(); 4482623SN/A 4492623SN/A // start out with the default range 4502623SN/A if (useDefaultRange) { 4512623SN/A if (!gotAddrRanges[defaultPortID]) 4522623SN/A fatal("Bus %s uses default range, but none provided", 4532630SN/A name()); 4542623SN/A 4552855Srdreslin@umich.edu busRanges.push_back(defaultRange); 4562855Srdreslin@umich.edu DPRINTF(BusAddrRanges, "-- Adding default %s\n", 4572855Srdreslin@umich.edu defaultRange.to_string()); 4582855Srdreslin@umich.edu } 4592855Srdreslin@umich.edu 4602855Srdreslin@umich.edu // merge all interleaved ranges and add any range that is not 4612623SN/A // a subset of the default range 4622623SN/A std::vector<AddrRange> intlv_ranges; 4632623SN/A for (AddrRangeMap<PortID>::const_iterator r = portMap.begin(); 4642657Ssaidi@eecs.umich.edu r != portMap.end(); ++r) { 4652623SN/A // if the range is interleaved then save it for now 4662623SN/A if (r->first.interleaved()) { 4672623SN/A // if we already got interleaved ranges that are not 4682623SN/A // part of the same range, then first do a merge 4692623SN/A // before we add the new one 4702623SN/A if (!intlv_ranges.empty() && 4712623SN/A !intlv_ranges.back().mergesWith(r->first)) { 4722657Ssaidi@eecs.umich.edu DPRINTF(BusAddrRanges, "-- Merging range from %d ranges\n", 4732657Ssaidi@eecs.umich.edu intlv_ranges.size()); 4742657Ssaidi@eecs.umich.edu AddrRange merged_range(intlv_ranges); 4752657Ssaidi@eecs.umich.edu // next decide if we keep the merged range or not 4762623SN/A if (!(useDefaultRange && 4772623SN/A merged_range.isSubset(defaultRange))) { 4782623SN/A busRanges.push_back(merged_range); 4792623SN/A DPRINTF(BusAddrRanges, "-- Adding merged range %s\n", 4802623SN/A merged_range.to_string()); 4812623SN/A } 4822623SN/A intlv_ranges.clear(); 4832641Sstever@eecs.umich.edu } 4842623SN/A intlv_ranges.push_back(r->first); 4852623SN/A } else { 4862623SN/A // keep the current range if not a subset of the default 4872839Sktlim@umich.edu if (!(useDefaultRange && 4882839Sktlim@umich.edu r->first.isSubset(defaultRange))) { 4892798Sktlim@umich.edu busRanges.push_back(r->first); 4902798Sktlim@umich.edu DPRINTF(BusAddrRanges, "-- Adding range %s\n", 4912798Sktlim@umich.edu r->first.to_string()); 4922798Sktlim@umich.edu } 4932798Sktlim@umich.edu } 4942798Sktlim@umich.edu } 4952798Sktlim@umich.edu 4962623SN/A // if there is still interleaved ranges waiting to be merged, 4972623SN/A // go ahead and do it 4982644Sstever@eecs.umich.edu if (!intlv_ranges.empty()) { 4992644Sstever@eecs.umich.edu DPRINTF(BusAddrRanges, "-- Merging range from %d ranges\n", 5002644Sstever@eecs.umich.edu intlv_ranges.size()); 5012644Sstever@eecs.umich.edu AddrRange merged_range(intlv_ranges); 5022644Sstever@eecs.umich.edu if (!(useDefaultRange && merged_range.isSubset(defaultRange))) { 5032623SN/A busRanges.push_back(merged_range); 5042623SN/A DPRINTF(BusAddrRanges, "-- Adding merged range %s\n", 5052623SN/A merged_range.to_string()); 5062798Sktlim@umich.edu } 5072839Sktlim@umich.edu } 5082798Sktlim@umich.edu 5092839Sktlim@umich.edu // also check that no range partially overlaps with the 5102839Sktlim@umich.edu // default range, this has to be done after all ranges are set 5112839Sktlim@umich.edu // as there are no guarantees for when the default range is 5122798Sktlim@umich.edu // update with respect to the other ones 5132623SN/A if (useDefaultRange) { 5142623SN/A for (AddrRangeConstIter r = busRanges.begin(); 5152630SN/A r != busRanges.end(); ++r) { 5162623SN/A // see if the new range is partially 5172630SN/A // overlapping the default range 5182623SN/A if (r->intersects(defaultRange) && 5192623SN/A !r->isSubset(defaultRange)) 5202623SN/A fatal("Range %s intersects the " \ 5212657Ssaidi@eecs.umich.edu "default range of %s but is not a " \ 5222623SN/A "subset\n", r->to_string(), name()); 5232623SN/A } 5242623SN/A } 5252623SN/A 5262623SN/A // tell all our neighbouring master ports that our address 5272623SN/A // ranges have changed 5282623SN/A for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end(); 5292657Ssaidi@eecs.umich.edu ++s) 5302657Ssaidi@eecs.umich.edu (*s)->sendRangeChange(); 5312657Ssaidi@eecs.umich.edu } 5322657Ssaidi@eecs.umich.edu 5332623SN/A clearPortCache(); 5342623SN/A} 5352623SN/A 5362623SN/AAddrRangeList 5372623SN/ABaseBus::getAddrRanges() const 5382623SN/A{ 5392623SN/A // we should never be asked without first having sent a range 5402623SN/A // change, and the latter is only done once we have all the ranges 5412623SN/A // of the connected devices 5422623SN/A assert(gotAllAddrRanges); 5432623SN/A 5442623SN/A // at the moment, this never happens, as there are no cycles in 5452623SN/A // the range queries and no devices on the master side of a bus 5462623SN/A // (CPU, cache, bridge etc) actually care about the ranges of the 5472623SN/A // ports they are connected to 5482623SN/A 5492623SN/A DPRINTF(BusAddrRanges, "Received address range request\n"); 5502623SN/A 5512623SN/A return busRanges; 5522623SN/A} 5532623SN/A 5542623SN/Aunsigned 5552623SN/ABaseBus::deviceBlockSize() const 5562623SN/A{ 5572623SN/A return blockSize; 5582623SN/A} 5592623SN/A 5602623SN/Avoid 5612623SN/ABaseBus::regStats() 5622623SN/A{ 5632623SN/A using namespace Stats; 5642623SN/A 5652623SN/A transDist 5662623SN/A .init(MemCmd::NUM_MEM_CMDS) 5672623SN/A .name(name() + ".trans_dist") 5682623SN/A .desc("Transaction distribution") 5692623SN/A .flags(nozero); 5702623SN/A 5712623SN/A // get the string representation of the commands 5722623SN/A for (int i = 0; i < MemCmd::NUM_MEM_CMDS; i++) { 5732623SN/A MemCmd cmd(i); 5742623SN/A const std::string &cstr = cmd.toString(); 5752623SN/A transDist.subname(i, cstr); 5762623SN/A } 5772623SN/A 5782623SN/A pktCount 5792623SN/A .init(slavePorts.size(), masterPorts.size()) 5802623SN/A .name(name() + ".pkt_count") 5812623SN/A .desc("Packet count per connected master and slave (bytes)") 5822623SN/A .flags(total | nozero | nonan); 5832623SN/A 5842623SN/A totPktSize 5852623SN/A .init(slavePorts.size(), masterPorts.size()) 5862623SN/A .name(name() + ".tot_pkt_size") 5872623SN/A .desc("Cumulative packet size per connected master and slave (bytes)") 5882623SN/A .flags(total | nozero | nonan); 5892623SN/A 5902623SN/A // both the packet count and total size are two-dimensional 5912623SN/A // vectors, indexed by slave port id and master port id, thus the 5922623SN/A // neighbouring master and slave, they do not differentiate what 5932623SN/A // came from the master and was forwarded to the slave (requests 5942623SN/A // and snoop responses) and what came from the slave and was 5952623SN/A // forwarded to the master (responses and snoop requests) 5962623SN/A for (int i = 0; i < slavePorts.size(); i++) { 5972623SN/A pktCount.subname(i, slavePorts[i]->getMasterPort().name()); 5982623SN/A totPktSize.subname(i, slavePorts[i]->getMasterPort().name()); 5992623SN/A for (int j = 0; j < masterPorts.size(); j++) { 6002623SN/A pktCount.ysubname(j, masterPorts[j]->getSlavePort().name()); 6012623SN/A totPktSize.ysubname(j, masterPorts[j]->getSlavePort().name()); 6022623SN/A } 6032623SN/A } 6042623SN/A} 6052623SN/A 6062623SN/Atemplate <typename SrcType, typename DstType> 6072623SN/Aunsigned int 6082623SN/ABaseBus::Layer<SrcType,DstType>::drain(DrainManager *dm) 6092623SN/A{ 6102623SN/A //We should check that we're not "doing" anything, and that noone is 6112623SN/A //waiting. We might be idle but have someone waiting if the device we 6122623SN/A //contacted for a retry didn't actually retry. 6132623SN/A if (state != IDLE) { 6142623SN/A DPRINTF(Drain, "Bus not drained\n"); 6152623SN/A drainManager = dm; 6162623SN/A return 1; 6172623SN/A } 6182623SN/A return 0; 6192623SN/A} 6202623SN/A 6212623SN/Atemplate <typename SrcType, typename DstType> 6222623SN/Avoid 6232623SN/ABaseBus::Layer<SrcType,DstType>::regStats() 6242623SN/A{ 6252623SN/A using namespace Stats; 6262623SN/A 6272623SN/A occupancy 6282623SN/A .name(name() + ".occupancy") 6292623SN/A .desc("Layer occupancy (ticks)") 6302623SN/A .flags(nozero); 631 632 utilization 633 .name(name() + ".utilization") 634 .desc("Layer utilization (%)") 635 .precision(1) 636 .flags(nozero); 637 638 utilization = 100 * occupancy / simTicks; 639} 640 641/** 642 * Bus layer template instantiations. Could be removed with _impl.hh 643 * file, but since there are only two given options (MasterPort and 644 * SlavePort) it seems a bit excessive at this point. 645 */ 646template class BaseBus::Layer<SlavePort,MasterPort>; 647template class BaseBus::Layer<MasterPort,SlavePort>; 648