xbar.cc revision 10414:3dabe649f1df
12292SN/A/*
22329SN/A * Copyright (c) 2011-2014 ARM Limited
32292SN/A * All rights reserved
42292SN/A *
52292SN/A * The license below extends only to copyright in the software and shall
62292SN/A * not be construed as granting a license to any other intellectual
72292SN/A * property including but not limited to intellectual property relating
82292SN/A * to a hardware implementation of the functionality of the software
92292SN/A * licensed hereunder.  You may use the software subject to the license
102292SN/A * terms below provided that you ensure that this notice is replicated
112292SN/A * unmodified and in its entirety in all distributions of the software,
122292SN/A * modified or unmodified, in source code or in binary form.
132292SN/A *
142292SN/A * Copyright (c) 2006 The Regents of The University of Michigan
152292SN/A * All rights reserved.
162292SN/A *
172292SN/A * Redistribution and use in source and binary forms, with or without
182292SN/A * modification, are permitted provided that the following conditions are
192292SN/A * met: redistributions of source code must retain the above copyright
202292SN/A * notice, this list of conditions and the following disclaimer;
212292SN/A * redistributions in binary form must reproduce the above copyright
222292SN/A * notice, this list of conditions and the following disclaimer in the
232292SN/A * documentation and/or other materials provided with the distribution;
242292SN/A * neither the name of the copyright holders nor the names of its
252292SN/A * contributors may be used to endorse or promote products derived from
262292SN/A * this software without specific prior written permission.
272689Sktlim@umich.edu *
282689Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292689Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302292SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312292SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352329SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372292SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392329SN/A *
403326Sktlim@umich.edu * Authors: Ali Saidi
412292SN/A *          Andreas Hansson
422292SN/A *          William Wang
432292SN/A */
443348Sbinkertn@umich.edu
452669Sktlim@umich.edu/**
462292SN/A * @file
472292SN/A * Definition of a crossbar object.
482329SN/A */
492329SN/A
502329SN/A#include "base/misc.hh"
512329SN/A#include "base/trace.hh"
522329SN/A#include "debug/AddrRanges.hh"
532329SN/A#include "debug/Drain.hh"
542329SN/A#include "debug/XBar.hh"
552329SN/A#include "mem/xbar.hh"
562329SN/A
572329SN/ABaseXBar::BaseXBar(const BaseXBarParams *p)
582292SN/A    : MemObject(p),
592292SN/A      headerCycles(p->header_cycles), width(p->width),
602292SN/A      gotAddrRanges(p->port_default_connection_count +
612292SN/A                          p->port_master_connection_count, false),
622292SN/A      gotAllAddrRanges(false), defaultPortID(InvalidPortID),
632292SN/A      useDefaultRange(p->use_default_range)
642292SN/A{}
652733Sktlim@umich.edu
662292SN/ABaseXBar::~BaseXBar()
672292SN/A{
682907Sktlim@umich.edu    for (auto m: masterPorts)
692292SN/A        delete m;
702292SN/A
712292SN/A    for (auto s: slavePorts)
722292SN/A        delete s;
732292SN/A}
742292SN/A
752292SN/Avoid
762907Sktlim@umich.eduBaseXBar::init()
772292SN/A{
782292SN/A}
792292SN/A
802292SN/ABaseMasterPort &
812292SN/ABaseXBar::getMasterPort(const std::string &if_name, PortID idx)
822727Sktlim@umich.edu{
832727Sktlim@umich.edu    if (if_name == "master" && idx < masterPorts.size()) {
842727Sktlim@umich.edu        // the master port index translates directly to the vector position
852292SN/A        return *masterPorts[idx];
862733Sktlim@umich.edu    } else  if (if_name == "default") {
872292SN/A        return *masterPorts[defaultPortID];
882292SN/A    } else {
892292SN/A        return MemObject::getMasterPort(if_name, idx);
902292SN/A    }
912292SN/A}
922907Sktlim@umich.edu
932907Sktlim@umich.eduBaseSlavePort &
942907Sktlim@umich.eduBaseXBar::getSlavePort(const std::string &if_name, PortID idx)
952907Sktlim@umich.edu{
962348SN/A    if (if_name == "slave" && idx < slavePorts.size()) {
972307SN/A        // the slave port index translates directly to the vector position
982307SN/A        return *slavePorts[idx];
992348SN/A    } else {
1002307SN/A        return MemObject::getSlavePort(if_name, idx);
1012307SN/A    }
1022348SN/A}
1032307SN/A
1042307SN/Avoid
1052292SN/ABaseXBar::calcPacketTiming(PacketPtr pkt)
1062292SN/A{
1072292SN/A    // the crossbar will be called at a time that is not necessarily
1082292SN/A    // coinciding with its own clock, so start by determining how long
1092292SN/A    // until the next clock edge (could be zero)
1102292SN/A    Tick offset = clockEdge() - curTick();
1112292SN/A
1122292SN/A    // determine how many cycles are needed to send the data
1132292SN/A    unsigned dataCycles = pkt->hasData() ? divCeil(pkt->getSize(), width) : 0;
1142292SN/A
1152292SN/A    // before setting the bus delay fields of the packet, ensure that
1162292SN/A    // the delay from any previous crossbar has been accounted for
1172292SN/A    if (pkt->firstWordDelay != 0 || pkt->lastWordDelay != 0)
1182292SN/A        panic("Packet %s already has delay (%d, %d) that should be "
1192292SN/A              "accounted for.\n", pkt->cmdString(), pkt->firstWordDelay,
1202292SN/A              pkt->lastWordDelay);
1212292SN/A
1222329SN/A    // The first word will be delivered on the cycle after the header.
1232292SN/A    pkt->firstWordDelay = (headerCycles + 1) * clockPeriod() + offset;
1242292SN/A
1252292SN/A    // Note that currently lastWordDelay can be smaller than
1262292SN/A    // firstWordDelay if the packet has no data
1272292SN/A    pkt->lastWordDelay = (headerCycles + dataCycles) * clockPeriod() +
1282292SN/A        offset;
1292292SN/A}
1302292SN/A
1312292SN/Atemplate <typename SrcType, typename DstType>
1322292SN/ABaseXBar::Layer<SrcType,DstType>::Layer(DstType& _port, BaseXBar& _xbar,
1332292SN/A                                       const std::string& _name) :
1342292SN/A    port(_port), xbar(_xbar), _name(_name), state(IDLE), drainManager(NULL),
1352292SN/A    waitingForPeer(NULL), releaseEvent(this)
1362292SN/A{
1372790Sktlim@umich.edu}
1382790Sktlim@umich.edu
1392669Sktlim@umich.edutemplate <typename SrcType, typename DstType>
1402669Sktlim@umich.eduvoid BaseXBar::Layer<SrcType,DstType>::occupyLayer(Tick until)
1412292SN/A{
1422292SN/A    // ensure the state is busy at this point, as the layer should
1432292SN/A    // transition from idle as soon as it has decided to forward the
1442292SN/A    // packet to prevent any follow-on calls to sendTiming seeing an
1452292SN/A    // unoccupied layer
1462292SN/A    assert(state == BUSY);
1472292SN/A
1482292SN/A    // until should never be 0 as express snoops never occupy the layer
1492292SN/A    assert(until != 0);
1502292SN/A    xbar.schedule(releaseEvent, until);
1512292SN/A
1522292SN/A    // account for the occupied ticks
1532292SN/A    occupancy += until - curTick();
1542292SN/A
1552292SN/A    DPRINTF(BaseXBar, "The crossbar layer is now busy from tick %d to %d\n",
1562292SN/A            curTick(), until);
1572292SN/A}
1582292SN/A
1592292SN/Atemplate <typename SrcType, typename DstType>
1602292SN/Abool
1612292SN/ABaseXBar::Layer<SrcType,DstType>::tryTiming(SrcType* src_port)
1622292SN/A{
1632292SN/A    // if we are in the retry state, we will not see anything but the
1642329SN/A    // retrying port (or in the case of the snoop ports the snoop
1652292SN/A    // response port that mirrors the actual slave port) as we leave
1662292SN/A    // this state again in zero time if the peer does not immediately
1672292SN/A    // call the layer when receiving the retry
1682348SN/A
1692292SN/A    // first we see if the layer is busy, next we check if the
1702292SN/A    // destination port is already engaged in a transaction waiting
1712292SN/A    // for a retry from the peer
1722348SN/A    if (state == BUSY || waitingForPeer != NULL) {
1732292SN/A        // the port should not be waiting already
1742292SN/A        assert(std::find(waitingForLayer.begin(), waitingForLayer.end(),
1752292SN/A                         src_port) == waitingForLayer.end());
1762348SN/A
1772292SN/A        // put the port at the end of the retry list waiting for the
1782292SN/A        // layer to be freed up (and in the case of a busy peer, for
1792292SN/A        // that transaction to go through, and then the layer to free
1802292SN/A        // up)
1812292SN/A        waitingForLayer.push_back(src_port);
1822292SN/A        return false;
1832292SN/A    }
1842292SN/A
1852292SN/A    state = BUSY;
1862292SN/A
1872292SN/A    return true;
1882292SN/A}
1892292SN/A
1902292SN/Atemplate <typename SrcType, typename DstType>
1912292SN/Avoid
1922292SN/ABaseXBar::Layer<SrcType,DstType>::succeededTiming(Tick busy_time)
1932292SN/A{
1942292SN/A    // we should have gone from idle or retry to busy in the tryTiming
1952292SN/A    // test
1962292SN/A    assert(state == BUSY);
1972292SN/A
1982292SN/A    // occupy the layer accordingly
1992292SN/A    occupyLayer(busy_time);
2002292SN/A}
2012292SN/A
2022292SN/Atemplate <typename SrcType, typename DstType>
2032292SN/Avoid
2042292SN/ABaseXBar::Layer<SrcType,DstType>::failedTiming(SrcType* src_port,
2052292SN/A                                              Tick busy_time)
2062292SN/A{
2072292SN/A    // ensure no one got in between and tried to send something to
2082292SN/A    // this port
2092292SN/A    assert(waitingForPeer == NULL);
2102292SN/A
2112292SN/A    // if the source port is the current retrying one or not, we have
2122678Sktlim@umich.edu    // failed in forwarding and should track that we are now waiting
2132678Sktlim@umich.edu    // for the peer to send a retry
2142292SN/A    waitingForPeer = src_port;
2152907Sktlim@umich.edu
2162907Sktlim@umich.edu    // we should have gone from idle or retry to busy in the tryTiming
2172907Sktlim@umich.edu    // test
2182292SN/A    assert(state == BUSY);
2192698Sktlim@umich.edu
2202678Sktlim@umich.edu    // occupy the bus accordingly
2212678Sktlim@umich.edu    occupyLayer(busy_time);
2222698Sktlim@umich.edu}
2233349Sbinkertn@umich.edu
2242693Sktlim@umich.edutemplate <typename SrcType, typename DstType>
2252292SN/Avoid
2262292SN/ABaseXBar::Layer<SrcType,DstType>::releaseLayer()
2272292SN/A{
2282292SN/A    // releasing the bus means we should now be idle
2292292SN/A    assert(state == BUSY);
2302292SN/A    assert(!releaseEvent.scheduled());
2312292SN/A
2322292SN/A    // update the state
2332292SN/A    state = IDLE;
2342292SN/A
2352292SN/A    // bus layer is now idle, so if someone is waiting we can retry
2362292SN/A    if (!waitingForLayer.empty()) {
2372329SN/A        // there is no point in sending a retry if someone is still
2382329SN/A        // waiting for the peer
2392329SN/A        if (waitingForPeer == NULL)
2402329SN/A            retryWaiting();
2412292SN/A    } else if (waitingForPeer == NULL && drainManager) {
2422292SN/A        DPRINTF(Drain, "Crossbar done draining, signaling drain manager\n");
2432733Sktlim@umich.edu        //If we weren't able to drain before, do it now.
2442292SN/A        drainManager->signalDrainDone();
2452292SN/A        // Clear the drain event once we're done with it.
2462292SN/A        drainManager = NULL;
2472292SN/A    }
2482907Sktlim@umich.edu}
2492907Sktlim@umich.edu
2502669Sktlim@umich.edutemplate <typename SrcType, typename DstType>
2512907Sktlim@umich.eduvoid
2522907Sktlim@umich.eduBaseXBar::Layer<SrcType,DstType>::retryWaiting()
2532292SN/A{
2542698Sktlim@umich.edu    // this should never be called with no one waiting
2552678Sktlim@umich.edu    assert(!waitingForLayer.empty());
2562678Sktlim@umich.edu
2572678Sktlim@umich.edu    // we always go to retrying from idle
2582698Sktlim@umich.edu    assert(state == IDLE);
2592678Sktlim@umich.edu
2602678Sktlim@umich.edu    // update the state
2612678Sktlim@umich.edu    state = RETRY;
2622678Sktlim@umich.edu
2632698Sktlim@umich.edu    // set the retrying port to the front of the retry list and pop it
2642678Sktlim@umich.edu    // off the list
2652698Sktlim@umich.edu    SrcType* retryingPort = waitingForLayer.front();
2662678Sktlim@umich.edu    waitingForLayer.pop_front();
2672698Sktlim@umich.edu
2682678Sktlim@umich.edu    // tell the port to retry, which in some cases ends up calling the
2692698Sktlim@umich.edu    // layer again
2702678Sktlim@umich.edu    retryingPort->sendRetry();
2712678Sktlim@umich.edu
2722678Sktlim@umich.edu    // If the layer is still in the retry state, sendTiming wasn't
2732698Sktlim@umich.edu    // called in zero time (e.g. the cache does this), burn a cycle
2742678Sktlim@umich.edu    if (state == RETRY) {
2752678Sktlim@umich.edu        // update the state to busy and reset the retrying port, we
2762678Sktlim@umich.edu        // have done our bit and sent the retry
2772678Sktlim@umich.edu        state = BUSY;
2782678Sktlim@umich.edu
2792678Sktlim@umich.edu        // occupy the crossbar layer until the next cycle ends
2802678Sktlim@umich.edu        occupyLayer(xbar.clockEdge(Cycles(1)));
2812678Sktlim@umich.edu    }
2822678Sktlim@umich.edu}
2832678Sktlim@umich.edu
2842678Sktlim@umich.edutemplate <typename SrcType, typename DstType>
2852678Sktlim@umich.eduvoid
2862698Sktlim@umich.eduBaseXBar::Layer<SrcType,DstType>::recvRetry()
2872678Sktlim@umich.edu{
2882678Sktlim@umich.edu    // we should never get a retry without having failed to forward
2892698Sktlim@umich.edu    // something to this port
2902678Sktlim@umich.edu    assert(waitingForPeer != NULL);
2912678Sktlim@umich.edu
2922678Sktlim@umich.edu    // add the port where the failed packet originated to the front of
2932678Sktlim@umich.edu    // the waiting ports for the layer, this allows us to call retry
2942678Sktlim@umich.edu    // on the port immediately if the crossbar layer is idle
2952678Sktlim@umich.edu    waitingForLayer.push_front(waitingForPeer);
2962292SN/A
2972292SN/A    // we are no longer waiting for the peer
2982292SN/A    waitingForPeer = NULL;
2992292SN/A
3002292SN/A    // if the layer is idle, retry this port straight away, if we
3012292SN/A    // are busy, then simply let the port wait for its turn
3022292SN/A    if (state == IDLE) {
3032292SN/A        retryWaiting();
3042292SN/A    } else {
3052292SN/A        assert(state == BUSY);
3062292SN/A    }
3072292SN/A}
3082292SN/A
3092292SN/APortID
3102292SN/ABaseXBar::findPort(Addr addr)
3112292SN/A{
3122669Sktlim@umich.edu    // we should never see any address lookups before we've got the
3132669Sktlim@umich.edu    // ranges of all connected slave modules
3142292SN/A    assert(gotAllAddrRanges);
3152292SN/A
3162292SN/A    // Check the cache
3172292SN/A    PortID dest_id = checkPortCache(addr);
3182292SN/A    if (dest_id != InvalidPortID)
3192292SN/A        return dest_id;
3202292SN/A
3212292SN/A    // Check the address map interval tree
3222292SN/A    auto i = portMap.find(addr);
3232292SN/A    if (i != portMap.end()) {
3242292SN/A        dest_id = i->second;
3252329SN/A        updatePortCache(dest_id, i->first);
3262292SN/A        return dest_id;
3272292SN/A    }
3282292SN/A
3292292SN/A    // Check if this matches the default range
3302292SN/A    if (useDefaultRange) {
3312292SN/A        if (defaultRange.contains(addr)) {
3322292SN/A            DPRINTF(AddrRanges, "  found addr %#llx on default\n",
3332292SN/A                    addr);
3342292SN/A            return defaultPortID;
3352292SN/A        }
3362329SN/A    } else if (defaultPortID != InvalidPortID) {
3372329SN/A        DPRINTF(AddrRanges, "Unable to find destination for addr %#llx, "
3382329SN/A                "will use default port\n", addr);
3392292SN/A        return defaultPortID;
3402329SN/A    }
3412329SN/A
3422329SN/A    // we should use the range for the default port and it did not
3432292SN/A    // match, or the default port is not set
3442292SN/A    fatal("Unable to find destination for addr %#llx on %s\n", addr,
3452292SN/A          name());
3462292SN/A}
3472329SN/A
3482292SN/A/** Function called by the port when the crossbar is receiving a range change.*/
3492292SN/Avoid
3502292SN/ABaseXBar::recvRangeChange(PortID master_port_id)
3512292SN/A{
3522292SN/A    DPRINTF(AddrRanges, "Received range change from slave port %s\n",
3532292SN/A            masterPorts[master_port_id]->getSlavePort().name());
3542292SN/A
3552292SN/A    // remember that we got a range from this master port and thus the
3562292SN/A    // connected slave module
3572292SN/A    gotAddrRanges[master_port_id] = true;
3582292SN/A
3592329SN/A    // update the global flag
3602329SN/A    if (!gotAllAddrRanges) {
3612292SN/A        // take a logical AND of all the ports and see if we got
3622292SN/A        // ranges from everyone
3632292SN/A        gotAllAddrRanges = true;
3642292SN/A        std::vector<bool>::const_iterator r = gotAddrRanges.begin();
3652292SN/A        while (gotAllAddrRanges &&  r != gotAddrRanges.end()) {
3662292SN/A            gotAllAddrRanges &= *r++;
3672292SN/A        }
3682292SN/A        if (gotAllAddrRanges)
3692292SN/A            DPRINTF(AddrRanges, "Got address ranges from all slaves\n");
3702292SN/A    }
3712292SN/A
3722292SN/A    // note that we could get the range from the default port at any
3732348SN/A    // point in time, and we cannot assume that the default range is
3742307SN/A    // set before the other ones are, so we do additional checks once
3752307SN/A    // all ranges are provided
3762292SN/A    if (master_port_id == defaultPortID) {
3772292SN/A        // only update if we are indeed checking ranges for the
3782292SN/A        // default port since the port might not have a valid range
3792292SN/A        // otherwise
3802292SN/A        if (useDefaultRange) {
3812292SN/A            AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges();
3822292SN/A
3832292SN/A            if (ranges.size() != 1)
3842292SN/A                fatal("Crossbar %s may only have a single default range",
3852292SN/A                      name());
3862292SN/A
3872292SN/A            defaultRange = ranges.front();
3882292SN/A        }
3892292SN/A    } else {
3902698Sktlim@umich.edu        // the ports are allowed to update their address ranges
3912698Sktlim@umich.edu        // dynamically, so remove any existing entries
3922693Sktlim@umich.edu        if (gotAddrRanges[master_port_id]) {
3932698Sktlim@umich.edu            for (auto p = portMap.begin(); p != portMap.end(); ) {
3942678Sktlim@umich.edu                if (p->second == master_port_id)
3952678Sktlim@umich.edu                    // erasing invalidates the iterator, so advance it
3962329SN/A                    // before the deletion takes place
3972292SN/A                    portMap.erase(p++);
3982292SN/A                else
3992348SN/A                    p++;
4002292SN/A            }
4012292SN/A        }
4022348SN/A
4032292SN/A        AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges();
4042292SN/A
4052292SN/A        for (const auto& r: ranges) {
4062292SN/A            DPRINTF(AddrRanges, "Adding range %s for id %d\n",
4072292SN/A                    r.to_string(), master_port_id);
4082292SN/A            if (portMap.insert(r, master_port_id) == portMap.end()) {
4092292SN/A                PortID conflict_id = portMap.find(r)->second;
4102292SN/A                fatal("%s has two ports responding within range %s:\n\t%s\n\t%s\n",
4112727Sktlim@umich.edu                      name(),
4122727Sktlim@umich.edu                      r.to_string(),
4132307SN/A                      masterPorts[master_port_id]->getSlavePort().name(),
4143126Sktlim@umich.edu                      masterPorts[conflict_id]->getSlavePort().name());
4153126Sktlim@umich.edu            }
4163126Sktlim@umich.edu        }
4173126Sktlim@umich.edu    }
4183126Sktlim@umich.edu
4193126Sktlim@umich.edu    // if we have received ranges from all our neighbouring slave
4203126Sktlim@umich.edu    // modules, go ahead and tell our connected master modules in
4213126Sktlim@umich.edu    // turn, this effectively assumes a tree structure of the system
4223126Sktlim@umich.edu    if (gotAllAddrRanges) {
4233126Sktlim@umich.edu        DPRINTF(AddrRanges, "Aggregating address ranges\n");
4243126Sktlim@umich.edu        xbarRanges.clear();
4253126Sktlim@umich.edu
4263126Sktlim@umich.edu        // start out with the default range
4272727Sktlim@umich.edu        if (useDefaultRange) {
4282727Sktlim@umich.edu            if (!gotAddrRanges[defaultPortID])
4292727Sktlim@umich.edu                fatal("Crossbar %s uses default range, but none provided",
4302727Sktlim@umich.edu                      name());
4312727Sktlim@umich.edu
4322727Sktlim@umich.edu            xbarRanges.push_back(defaultRange);
4332727Sktlim@umich.edu            DPRINTF(AddrRanges, "-- Adding default %s\n",
4342727Sktlim@umich.edu                    defaultRange.to_string());
4352727Sktlim@umich.edu        }
4362727Sktlim@umich.edu
4372727Sktlim@umich.edu        // merge all interleaved ranges and add any range that is not
4382727Sktlim@umich.edu        // a subset of the default range
4392727Sktlim@umich.edu        std::vector<AddrRange> intlv_ranges;
4402727Sktlim@umich.edu        for (const auto& r: portMap) {
4412727Sktlim@umich.edu            // if the range is interleaved then save it for now
4422292SN/A            if (r.first.interleaved()) {
4432292SN/A                // if we already got interleaved ranges that are not
4442292SN/A                // part of the same range, then first do a merge
4452669Sktlim@umich.edu                // before we add the new one
4462292SN/A                if (!intlv_ranges.empty() &&
4472292SN/A                    !intlv_ranges.back().mergesWith(r.first)) {
4482292SN/A                    DPRINTF(AddrRanges, "-- Merging range from %d ranges\n",
4492669Sktlim@umich.edu                            intlv_ranges.size());
4502292SN/A                    AddrRange merged_range(intlv_ranges);
4512292SN/A                    // next decide if we keep the merged range or not
4522292SN/A                    if (!(useDefaultRange &&
4532292SN/A                          merged_range.isSubset(defaultRange))) {
4542292SN/A                        xbarRanges.push_back(merged_range);
4552292SN/A                        DPRINTF(AddrRanges, "-- Adding merged range %s\n",
4562292SN/A                                merged_range.to_string());
4572292SN/A                    }
4582292SN/A                    intlv_ranges.clear();
4592292SN/A                }
4602292SN/A                intlv_ranges.push_back(r.first);
4612292SN/A            } else {
4622292SN/A                // keep the current range if not a subset of the default
4632292SN/A                if (!(useDefaultRange &&
4642292SN/A                      r.first.isSubset(defaultRange))) {
4652292SN/A                    xbarRanges.push_back(r.first);
4662292SN/A                    DPRINTF(AddrRanges, "-- Adding range %s\n",
4672292SN/A                            r.first.to_string());
4682292SN/A                }
4692292SN/A            }
4702292SN/A        }
4712292SN/A
4722292SN/A        // if there is still interleaved ranges waiting to be merged,
4732292SN/A        // go ahead and do it
4742292SN/A        if (!intlv_ranges.empty()) {
4752292SN/A            DPRINTF(AddrRanges, "-- Merging range from %d ranges\n",
4762292SN/A                    intlv_ranges.size());
4772292SN/A            AddrRange merged_range(intlv_ranges);
4782292SN/A            if (!(useDefaultRange && merged_range.isSubset(defaultRange))) {
4792292SN/A                xbarRanges.push_back(merged_range);
4802292SN/A                DPRINTF(AddrRanges, "-- Adding merged range %s\n",
4812292SN/A                        merged_range.to_string());
4822292SN/A            }
4832292SN/A        }
4842669Sktlim@umich.edu
4852292SN/A        // also check that no range partially overlaps with the
4862669Sktlim@umich.edu        // default range, this has to be done after all ranges are set
4872292SN/A        // as there are no guarantees for when the default range is
4882669Sktlim@umich.edu        // update with respect to the other ones
4892669Sktlim@umich.edu        if (useDefaultRange) {
4902669Sktlim@umich.edu            for (const auto& r: xbarRanges) {
4912292SN/A                // see if the new range is partially
4922292SN/A                // overlapping the default range
4932292SN/A                if (r.intersects(defaultRange) &&
4942292SN/A                    !r.isSubset(defaultRange))
4952292SN/A                    fatal("Range %s intersects the "                    \
4963172Sstever@eecs.umich.edu                          "default range of %s but is not a "           \
4972731Sktlim@umich.edu                          "subset\n", r.to_string(), name());
4982669Sktlim@umich.edu            }
4992727Sktlim@umich.edu        }
5004032Sktlim@umich.edu
5014032Sktlim@umich.edu        // tell all our neighbouring master ports that our address
5024032Sktlim@umich.edu        // ranges have changed
5034032Sktlim@umich.edu        for (const auto& s: slavePorts)
5044032Sktlim@umich.edu            s->sendRangeChange();
5052292SN/A    }
5062292SN/A
5072292SN/A    clearPortCache();
5082292SN/A}
5092669Sktlim@umich.edu
5102292SN/AAddrRangeList
5112292SN/ABaseXBar::getAddrRanges() const
5122292SN/A{
5132292SN/A    // we should never be asked without first having sent a range
5142292SN/A    // change, and the latter is only done once we have all the ranges
5152669Sktlim@umich.edu    // of the connected devices
5162292SN/A    assert(gotAllAddrRanges);
5173172Sstever@eecs.umich.edu
5183326Sktlim@umich.edu    // at the moment, this never happens, as there are no cycles in
5193326Sktlim@umich.edu    // the range queries and no devices on the master side of a crossbar
5203326Sktlim@umich.edu    // (CPU, cache, bridge etc) actually care about the ranges of the
5213326Sktlim@umich.edu    // ports they are connected to
5223326Sktlim@umich.edu
5233326Sktlim@umich.edu    DPRINTF(AddrRanges, "Received address range request\n");
5242292SN/A
5252292SN/A    return xbarRanges;
5262292SN/A}
5272292SN/A
5282292SN/Avoid
5292292SN/ABaseXBar::regStats()
5302292SN/A{
5312292SN/A    using namespace Stats;
5322292SN/A
5332292SN/A    transDist
5342292SN/A        .init(MemCmd::NUM_MEM_CMDS)
5352292SN/A        .name(name() + ".trans_dist")
5362292SN/A        .desc("Transaction distribution")
5372292SN/A        .flags(nozero);
5382292SN/A
5392292SN/A    // get the string representation of the commands
5402292SN/A    for (int i = 0; i < MemCmd::NUM_MEM_CMDS; i++) {
5412292SN/A        MemCmd cmd(i);
5424032Sktlim@umich.edu        const std::string &cstr = cmd.toString();
5434032Sktlim@umich.edu        transDist.subname(i, cstr);
5444032Sktlim@umich.edu    }
5454032Sktlim@umich.edu
5462292SN/A    pktCount
5472292SN/A        .init(slavePorts.size(), masterPorts.size())
5482292SN/A        .name(name() + ".pkt_count")
5492292SN/A        .desc("Packet count per connected master and slave (bytes)")
5502669Sktlim@umich.edu        .flags(total | nozero | nonan);
5512292SN/A
5522669Sktlim@umich.edu    pktSize
5532669Sktlim@umich.edu        .init(slavePorts.size(), masterPorts.size())
5542292SN/A        .name(name() + ".pkt_size")
5552669Sktlim@umich.edu        .desc("Cumulative packet size per connected master and slave (bytes)")
5562292SN/A        .flags(total | nozero | nonan);
5572292SN/A
5582669Sktlim@umich.edu    // both the packet count and total size are two-dimensional
5592669Sktlim@umich.edu    // vectors, indexed by slave port id and master port id, thus the
5602292SN/A    // neighbouring master and slave, they do not differentiate what
5612292SN/A    // came from the master and was forwarded to the slave (requests
5624032Sktlim@umich.edu    // and snoop responses) and what came from the slave and was
5632329SN/A    // forwarded to the master (responses and snoop requests)
5642669Sktlim@umich.edu    for (int i = 0; i < slavePorts.size(); i++) {
5652329SN/A        pktCount.subname(i, slavePorts[i]->getMasterPort().name());
5662292SN/A        pktSize.subname(i, slavePorts[i]->getMasterPort().name());
5672292SN/A        for (int j = 0; j < masterPorts.size(); j++) {
5682292SN/A            pktCount.ysubname(j, masterPorts[j]->getSlavePort().name());
5692292SN/A            pktSize.ysubname(j, masterPorts[j]->getSlavePort().name());
5702292SN/A        }
5713803Sgblack@eecs.umich.edu    }
5723803Sgblack@eecs.umich.edu}
5733803Sgblack@eecs.umich.edu
5743803Sgblack@eecs.umich.edutemplate <typename SrcType, typename DstType>
5753803Sgblack@eecs.umich.eduunsigned int
5763803Sgblack@eecs.umich.eduBaseXBar::Layer<SrcType,DstType>::drain(DrainManager *dm)
5772669Sktlim@umich.edu{
5782669Sktlim@umich.edu    //We should check that we're not "doing" anything, and that noone is
5792292SN/A    //waiting. We might be idle but have someone waiting if the device we
5802669Sktlim@umich.edu    //contacted for a retry didn't actually retry.
5812292SN/A    if (state != IDLE) {
5822292SN/A        DPRINTF(Drain, "Crossbar not drained\n");
5832292SN/A        drainManager = dm;
5842693Sktlim@umich.edu        return 1;
5852678Sktlim@umich.edu    }
5862678Sktlim@umich.edu    return 0;
5872678Sktlim@umich.edu}
5882678Sktlim@umich.edu
5892678Sktlim@umich.edutemplate <typename SrcType, typename DstType>
5902292SN/Avoid
5912292SN/ABaseXBar::Layer<SrcType,DstType>::regStats()
5922292SN/A{
5932292SN/A    using namespace Stats;
5942292SN/A
5952678Sktlim@umich.edu    occupancy
5962727Sktlim@umich.edu        .name(name() + ".occupancy")
5972292SN/A        .desc("Layer occupancy (ticks)")
5982292SN/A        .flags(nozero);
5992292SN/A
6002292SN/A    utilization
6012292SN/A        .name(name() + ".utilization")
6022292SN/A        .desc("Layer utilization (%)")
6032292SN/A        .precision(1)
6042292SN/A        .flags(nozero);
6052292SN/A
6062292SN/A    utilization = 100 * occupancy / simTicks;
6074032Sktlim@umich.edu}
6082292SN/A
6092292SN/A/**
6102292SN/A * Crossbar layer template instantiations. Could be removed with _impl.hh
6112292SN/A * file, but since there are only two given options (MasterPort and
6122292SN/A * SlavePort) it seems a bit excessive at this point.
6132292SN/A */
6142292SN/Atemplate class BaseXBar::Layer<SlavePort,MasterPort>;
6152669Sktlim@umich.edutemplate class BaseXBar::Layer<MasterPort,SlavePort>;
6162292SN/A