noncoherent_xbar.cc revision 12334:e0ab29a34764
110447Snilay@cs.wisc.edu/*
210447Snilay@cs.wisc.edu * Copyright (c) 2011-2015 ARM Limited
310447Snilay@cs.wisc.edu * All rights reserved
410447Snilay@cs.wisc.edu *
510447Snilay@cs.wisc.edu * The license below extends only to copyright in the software and shall
610447Snilay@cs.wisc.edu * not be construed as granting a license to any other intellectual
710447Snilay@cs.wisc.edu * property including but not limited to intellectual property relating
810447Snilay@cs.wisc.edu * to a hardware implementation of the functionality of the software
910447Snilay@cs.wisc.edu * licensed hereunder.  You may use the software subject to the license
1010447Snilay@cs.wisc.edu * terms below provided that you ensure that this notice is replicated
1110447Snilay@cs.wisc.edu * unmodified and in its entirety in all distributions of the software,
1210447Snilay@cs.wisc.edu * modified or unmodified, in source code or in binary form.
1310447Snilay@cs.wisc.edu *
1410447Snilay@cs.wisc.edu * Copyright (c) 2006 The Regents of The University of Michigan
1510447Snilay@cs.wisc.edu * All rights reserved.
1610447Snilay@cs.wisc.edu *
1710447Snilay@cs.wisc.edu * Redistribution and use in source and binary forms, with or without
1810447Snilay@cs.wisc.edu * modification, are permitted provided that the following conditions are
1910447Snilay@cs.wisc.edu * met: redistributions of source code must retain the above copyright
2010447Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer;
2110447Snilay@cs.wisc.edu * redistributions in binary form must reproduce the above copyright
2210447Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer in the
2310447Snilay@cs.wisc.edu * documentation and/or other materials provided with the distribution;
2410447Snilay@cs.wisc.edu * neither the name of the copyright holders nor the names of its
2510447Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from
2610447Snilay@cs.wisc.edu * this software without specific prior written permission.
2710447Snilay@cs.wisc.edu *
2810447Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2910447Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3010447Snilay@cs.wisc.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3110447Snilay@cs.wisc.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3210447Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3310447Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3410447Snilay@cs.wisc.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3510447Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3610447Snilay@cs.wisc.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3710447Snilay@cs.wisc.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3810447Snilay@cs.wisc.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3910447Snilay@cs.wisc.edu *
4010447Snilay@cs.wisc.edu * Authors: Ali Saidi
4110447Snilay@cs.wisc.edu *          Andreas Hansson
4210447Snilay@cs.wisc.edu *          William Wang
4310447Snilay@cs.wisc.edu */
4410447Snilay@cs.wisc.edu
4510447Snilay@cs.wisc.edu/**
4610447Snilay@cs.wisc.edu * @file
4710447Snilay@cs.wisc.edu * Definition of a non-coherent crossbar object.
4810447Snilay@cs.wisc.edu */
4910447Snilay@cs.wisc.edu
5010447Snilay@cs.wisc.edu#include "mem/noncoherent_xbar.hh"
5110447Snilay@cs.wisc.edu
5210447Snilay@cs.wisc.edu#include "base/logging.hh"
5310447Snilay@cs.wisc.edu#include "base/trace.hh"
5410447Snilay@cs.wisc.edu#include "debug/NoncoherentXBar.hh"
5510447Snilay@cs.wisc.edu#include "debug/XBar.hh"
5610447Snilay@cs.wisc.edu
5710447Snilay@cs.wisc.eduNoncoherentXBar::NoncoherentXBar(const NoncoherentXBarParams *p)
5810447Snilay@cs.wisc.edu    : BaseXBar(p)
5910447Snilay@cs.wisc.edu{
6010447Snilay@cs.wisc.edu    // create the ports based on the size of the master and slave
6110447Snilay@cs.wisc.edu    // vector ports, and the presence of the default port, the ports
6210447Snilay@cs.wisc.edu    // are enumerated starting from zero
6310447Snilay@cs.wisc.edu    for (int i = 0; i < p->port_master_connection_count; ++i) {
6410447Snilay@cs.wisc.edu        std::string portName = csprintf("%s.master[%d]", name(), i);
6510447Snilay@cs.wisc.edu        MasterPort* bp = new NoncoherentXBarMasterPort(portName, *this, i);
6610447Snilay@cs.wisc.edu        masterPorts.push_back(bp);
6710447Snilay@cs.wisc.edu        reqLayers.push_back(new ReqLayer(*bp, *this,
6810447Snilay@cs.wisc.edu                                         csprintf(".reqLayer%d", i)));
6910447Snilay@cs.wisc.edu    }
7010447Snilay@cs.wisc.edu
7110447Snilay@cs.wisc.edu    // see if we have a default slave device connected and if so add
7210447Snilay@cs.wisc.edu    // our corresponding master port
7310447Snilay@cs.wisc.edu    if (p->port_default_connection_count) {
7410447Snilay@cs.wisc.edu        defaultPortID = masterPorts.size();
7510447Snilay@cs.wisc.edu        std::string portName = name() + ".default";
7610447Snilay@cs.wisc.edu        MasterPort* bp = new NoncoherentXBarMasterPort(portName, *this,
7710447Snilay@cs.wisc.edu                                                      defaultPortID);
7810447Snilay@cs.wisc.edu        masterPorts.push_back(bp);
7910447Snilay@cs.wisc.edu        reqLayers.push_back(new ReqLayer(*bp, *this, csprintf(".reqLayer%d",
8010447Snilay@cs.wisc.edu                                                              defaultPortID)));
8110447Snilay@cs.wisc.edu    }
8210447Snilay@cs.wisc.edu
8310447Snilay@cs.wisc.edu    // create the slave ports, once again starting at zero
8410447Snilay@cs.wisc.edu    for (int i = 0; i < p->port_slave_connection_count; ++i) {
8510447Snilay@cs.wisc.edu        std::string portName = csprintf("%s.slave[%d]", name(), i);
8610447Snilay@cs.wisc.edu        QueuedSlavePort* bp = new NoncoherentXBarSlavePort(portName, *this, i);
8710447Snilay@cs.wisc.edu        slavePorts.push_back(bp);
8810447Snilay@cs.wisc.edu        respLayers.push_back(new RespLayer(*bp, *this,
8910447Snilay@cs.wisc.edu                                           csprintf(".respLayer%d", i)));
9010447Snilay@cs.wisc.edu    }
9110447Snilay@cs.wisc.edu
9210447Snilay@cs.wisc.edu    clearPortCache();
9310447Snilay@cs.wisc.edu}
9410447Snilay@cs.wisc.edu
9510447Snilay@cs.wisc.eduNoncoherentXBar::~NoncoherentXBar()
9610447Snilay@cs.wisc.edu{
9710447Snilay@cs.wisc.edu    for (auto l: reqLayers)
9810447Snilay@cs.wisc.edu        delete l;
9910447Snilay@cs.wisc.edu    for (auto l: respLayers)
10010447Snilay@cs.wisc.edu        delete l;
10110447Snilay@cs.wisc.edu}
10210447Snilay@cs.wisc.edu
10310447Snilay@cs.wisc.edubool
10410447Snilay@cs.wisc.eduNoncoherentXBar::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
10510447Snilay@cs.wisc.edu{
10610447Snilay@cs.wisc.edu    // determine the source port based on the id
10710447Snilay@cs.wisc.edu    SlavePort *src_port = slavePorts[slave_port_id];
10810447Snilay@cs.wisc.edu
10910447Snilay@cs.wisc.edu    // we should never see express snoops on a non-coherent crossbar
11010447Snilay@cs.wisc.edu    assert(!pkt->isExpressSnoop());
11110447Snilay@cs.wisc.edu
11210447Snilay@cs.wisc.edu    // determine the destination based on the address
11310447Snilay@cs.wisc.edu    PortID master_port_id = findPort(pkt->getAddr());
11410447Snilay@cs.wisc.edu
11510447Snilay@cs.wisc.edu    // test if the layer should be considered occupied for the current
11610447Snilay@cs.wisc.edu    // port
11710447Snilay@cs.wisc.edu    if (!reqLayers[master_port_id]->tryTiming(src_port)) {
11810447Snilay@cs.wisc.edu        DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x BUSY\n",
11910447Snilay@cs.wisc.edu                src_port->name(), pkt->cmdString(), pkt->getAddr());
12010447Snilay@cs.wisc.edu        return false;
12110447Snilay@cs.wisc.edu    }
12210447Snilay@cs.wisc.edu
12310447Snilay@cs.wisc.edu    DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x\n",
12410447Snilay@cs.wisc.edu            src_port->name(), pkt->cmdString(), pkt->getAddr());
12510447Snilay@cs.wisc.edu
12610447Snilay@cs.wisc.edu    // store size and command as they might be modified when
12710447Snilay@cs.wisc.edu    // forwarding the packet
12810447Snilay@cs.wisc.edu    unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
12910447Snilay@cs.wisc.edu    unsigned int pkt_cmd = pkt->cmdToIndex();
13010447Snilay@cs.wisc.edu
13110447Snilay@cs.wisc.edu    // store the old header delay so we can restore it if needed
13210447Snilay@cs.wisc.edu    Tick old_header_delay = pkt->headerDelay;
13310447Snilay@cs.wisc.edu
13410447Snilay@cs.wisc.edu    // a request sees the frontend and forward latency
13510447Snilay@cs.wisc.edu    Tick xbar_delay = (frontendLatency + forwardLatency) * clockPeriod();
13610447Snilay@cs.wisc.edu
13710447Snilay@cs.wisc.edu    // set the packet header and payload delay
13810447Snilay@cs.wisc.edu    calcPacketTiming(pkt, xbar_delay);
13910447Snilay@cs.wisc.edu
14010447Snilay@cs.wisc.edu    // determine how long to be crossbar layer is busy
14110447Snilay@cs.wisc.edu    Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
14210447Snilay@cs.wisc.edu
14310447Snilay@cs.wisc.edu    // before forwarding the packet (and possibly altering it),
14410447Snilay@cs.wisc.edu    // remember if we are expecting a response
14510447Snilay@cs.wisc.edu    const bool expect_response = pkt->needsResponse() &&
14610447Snilay@cs.wisc.edu        !pkt->cacheResponding();
14710447Snilay@cs.wisc.edu
14810447Snilay@cs.wisc.edu    // since it is a normal request, attempt to send the packet
14910447Snilay@cs.wisc.edu    bool success = masterPorts[master_port_id]->sendTimingReq(pkt);
15010447Snilay@cs.wisc.edu
15110447Snilay@cs.wisc.edu    if (!success)  {
15210447Snilay@cs.wisc.edu        DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x RETRY\n",
15310447Snilay@cs.wisc.edu                src_port->name(), pkt->cmdString(), pkt->getAddr());
15410447Snilay@cs.wisc.edu
15510447Snilay@cs.wisc.edu        // restore the header delay as it is additive
15610447Snilay@cs.wisc.edu        pkt->headerDelay = old_header_delay;
15710447Snilay@cs.wisc.edu
15810447Snilay@cs.wisc.edu        // occupy until the header is sent
15910447Snilay@cs.wisc.edu        reqLayers[master_port_id]->failedTiming(src_port,
16010447Snilay@cs.wisc.edu                                                clockEdge(Cycles(1)));
16110447Snilay@cs.wisc.edu
16210447Snilay@cs.wisc.edu        return false;
16310447Snilay@cs.wisc.edu    }
16410447Snilay@cs.wisc.edu
16510447Snilay@cs.wisc.edu    // remember where to route the response to
16610447Snilay@cs.wisc.edu    if (expect_response) {
16710447Snilay@cs.wisc.edu        assert(routeTo.find(pkt->req) == routeTo.end());
16810447Snilay@cs.wisc.edu        routeTo[pkt->req] = slave_port_id;
16910447Snilay@cs.wisc.edu    }
17010447Snilay@cs.wisc.edu
17110447Snilay@cs.wisc.edu    reqLayers[master_port_id]->succeededTiming(packetFinishTime);
17210447Snilay@cs.wisc.edu
17310447Snilay@cs.wisc.edu    // stats updates
17410447Snilay@cs.wisc.edu    pktCount[slave_port_id][master_port_id]++;
17510447Snilay@cs.wisc.edu    pktSize[slave_port_id][master_port_id] += pkt_size;
17610447Snilay@cs.wisc.edu    transDist[pkt_cmd]++;
17710447Snilay@cs.wisc.edu
17810447Snilay@cs.wisc.edu    return true;
17910447Snilay@cs.wisc.edu}
18010447Snilay@cs.wisc.edu
18110447Snilay@cs.wisc.edubool
18210447Snilay@cs.wisc.eduNoncoherentXBar::recvTimingResp(PacketPtr pkt, PortID master_port_id)
18310447Snilay@cs.wisc.edu{
18410447Snilay@cs.wisc.edu    // determine the source port based on the id
18510447Snilay@cs.wisc.edu    MasterPort *src_port = masterPorts[master_port_id];
18610447Snilay@cs.wisc.edu
18710447Snilay@cs.wisc.edu    // determine the destination
18810447Snilay@cs.wisc.edu    const auto route_lookup = routeTo.find(pkt->req);
18910447Snilay@cs.wisc.edu    assert(route_lookup != routeTo.end());
19010447Snilay@cs.wisc.edu    const PortID slave_port_id = route_lookup->second;
19110447Snilay@cs.wisc.edu    assert(slave_port_id != InvalidPortID);
19210447Snilay@cs.wisc.edu    assert(slave_port_id < respLayers.size());
19310447Snilay@cs.wisc.edu
19410447Snilay@cs.wisc.edu    // test if the layer should be considered occupied for the current
19510447Snilay@cs.wisc.edu    // port
19610447Snilay@cs.wisc.edu    if (!respLayers[slave_port_id]->tryTiming(src_port)) {
19710447Snilay@cs.wisc.edu        DPRINTF(NoncoherentXBar, "recvTimingResp: src %s %s 0x%x BUSY\n",
19810447Snilay@cs.wisc.edu                src_port->name(), pkt->cmdString(), pkt->getAddr());
19910447Snilay@cs.wisc.edu        return false;
20010447Snilay@cs.wisc.edu    }
20110447Snilay@cs.wisc.edu
20210447Snilay@cs.wisc.edu    DPRINTF(NoncoherentXBar, "recvTimingResp: src %s %s 0x%x\n",
20310447Snilay@cs.wisc.edu            src_port->name(), pkt->cmdString(), pkt->getAddr());
20410447Snilay@cs.wisc.edu
20510447Snilay@cs.wisc.edu    // store size and command as they might be modified when
20610447Snilay@cs.wisc.edu    // forwarding the packet
20710447Snilay@cs.wisc.edu    unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
20810447Snilay@cs.wisc.edu    unsigned int pkt_cmd = pkt->cmdToIndex();
20910447Snilay@cs.wisc.edu
21010447Snilay@cs.wisc.edu    // a response sees the response latency
21110447Snilay@cs.wisc.edu    Tick xbar_delay = responseLatency * clockPeriod();
21210447Snilay@cs.wisc.edu
21310447Snilay@cs.wisc.edu    // set the packet header and payload delay
21410447Snilay@cs.wisc.edu    calcPacketTiming(pkt, xbar_delay);
21510447Snilay@cs.wisc.edu
21610447Snilay@cs.wisc.edu    // determine how long to be crossbar layer is busy
21710447Snilay@cs.wisc.edu    Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
21810447Snilay@cs.wisc.edu
21910447Snilay@cs.wisc.edu    // send the packet through the destination slave port, and pay for
22010447Snilay@cs.wisc.edu    // any outstanding latency
22110447Snilay@cs.wisc.edu    Tick latency = pkt->headerDelay;
22210447Snilay@cs.wisc.edu    pkt->headerDelay = 0;
22310447Snilay@cs.wisc.edu    slavePorts[slave_port_id]->schedTimingResp(pkt, curTick() + latency);
22410447Snilay@cs.wisc.edu
22510447Snilay@cs.wisc.edu    // remove the request from the routing table
22610447Snilay@cs.wisc.edu    routeTo.erase(route_lookup);
22710447Snilay@cs.wisc.edu
22810447Snilay@cs.wisc.edu    respLayers[slave_port_id]->succeededTiming(packetFinishTime);
22910447Snilay@cs.wisc.edu
23010447Snilay@cs.wisc.edu    // stats updates
23110447Snilay@cs.wisc.edu    pktCount[slave_port_id][master_port_id]++;
23210447Snilay@cs.wisc.edu    pktSize[slave_port_id][master_port_id] += pkt_size;
23310447Snilay@cs.wisc.edu    transDist[pkt_cmd]++;
23410447Snilay@cs.wisc.edu
23510447Snilay@cs.wisc.edu    return true;
23610447Snilay@cs.wisc.edu}
23710447Snilay@cs.wisc.edu
23810447Snilay@cs.wisc.eduvoid
23910447Snilay@cs.wisc.eduNoncoherentXBar::recvReqRetry(PortID master_port_id)
24010447Snilay@cs.wisc.edu{
24110447Snilay@cs.wisc.edu    // responses never block on forwarding them, so the retry will
24210447Snilay@cs.wisc.edu    // always be coming from a port to which we tried to forward a
24310447Snilay@cs.wisc.edu    // request
24410447Snilay@cs.wisc.edu    reqLayers[master_port_id]->recvRetry();
24510447Snilay@cs.wisc.edu}
24610447Snilay@cs.wisc.edu
24710447Snilay@cs.wisc.eduTick
24810447Snilay@cs.wisc.eduNoncoherentXBar::recvAtomic(PacketPtr pkt, PortID slave_port_id)
24910447Snilay@cs.wisc.edu{
25010447Snilay@cs.wisc.edu    DPRINTF(NoncoherentXBar, "recvAtomic: packet src %s addr 0x%x cmd %s\n",
25110447Snilay@cs.wisc.edu            slavePorts[slave_port_id]->name(), pkt->getAddr(),
25210447Snilay@cs.wisc.edu            pkt->cmdString());
25310447Snilay@cs.wisc.edu
25410447Snilay@cs.wisc.edu    unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
25510447Snilay@cs.wisc.edu    unsigned int pkt_cmd = pkt->cmdToIndex();
25610447Snilay@cs.wisc.edu
25710447Snilay@cs.wisc.edu    // determine the destination port
25810447Snilay@cs.wisc.edu    PortID master_port_id = findPort(pkt->getAddr());
25910447Snilay@cs.wisc.edu
26010447Snilay@cs.wisc.edu    // stats updates for the request
26110447Snilay@cs.wisc.edu    pktCount[slave_port_id][master_port_id]++;
26210447Snilay@cs.wisc.edu    pktSize[slave_port_id][master_port_id] += pkt_size;
26310447Snilay@cs.wisc.edu    transDist[pkt_cmd]++;
26410447Snilay@cs.wisc.edu
26510447Snilay@cs.wisc.edu    // forward the request to the appropriate destination
26610447Snilay@cs.wisc.edu    Tick response_latency = masterPorts[master_port_id]->sendAtomic(pkt);
26710447Snilay@cs.wisc.edu
26810447Snilay@cs.wisc.edu    // add the response data
26910447Snilay@cs.wisc.edu    if (pkt->isResponse()) {
27010447Snilay@cs.wisc.edu        pkt_size = pkt->hasData() ? pkt->getSize() : 0;
27110447Snilay@cs.wisc.edu        pkt_cmd = pkt->cmdToIndex();
27210447Snilay@cs.wisc.edu
27310447Snilay@cs.wisc.edu        // stats updates
27410447Snilay@cs.wisc.edu        pktCount[slave_port_id][master_port_id]++;
27510447Snilay@cs.wisc.edu        pktSize[slave_port_id][master_port_id] += pkt_size;
27610447Snilay@cs.wisc.edu        transDist[pkt_cmd]++;
27710447Snilay@cs.wisc.edu    }
27810447Snilay@cs.wisc.edu
27910447Snilay@cs.wisc.edu    // @todo: Not setting first-word time
28010447Snilay@cs.wisc.edu    pkt->payloadDelay = response_latency;
28110447Snilay@cs.wisc.edu    return response_latency;
28210447Snilay@cs.wisc.edu}
28310447Snilay@cs.wisc.edu
28410447Snilay@cs.wisc.eduvoid
28510447Snilay@cs.wisc.eduNoncoherentXBar::recvFunctional(PacketPtr pkt, PortID slave_port_id)
28610447Snilay@cs.wisc.edu{
28710447Snilay@cs.wisc.edu    if (!pkt->isPrint()) {
28810447Snilay@cs.wisc.edu        // don't do DPRINTFs on PrintReq as it clutters up the output
28910447Snilay@cs.wisc.edu        DPRINTF(NoncoherentXBar,
29010447Snilay@cs.wisc.edu                "recvFunctional: packet src %s addr 0x%x cmd %s\n",
29110447Snilay@cs.wisc.edu                slavePorts[slave_port_id]->name(), pkt->getAddr(),
29210447Snilay@cs.wisc.edu                pkt->cmdString());
29310447Snilay@cs.wisc.edu    }
29410447Snilay@cs.wisc.edu
29510447Snilay@cs.wisc.edu    // since our slave ports are queued ports we need to check them as well
29610447Snilay@cs.wisc.edu    for (const auto& p : slavePorts) {
29710447Snilay@cs.wisc.edu        // if we find a response that has the data, then the
29810447Snilay@cs.wisc.edu        // downstream caches/memories may be out of date, so simply stop
29910447Snilay@cs.wisc.edu        // here
30010447Snilay@cs.wisc.edu        if (p->checkFunctional(pkt)) {
30110447Snilay@cs.wisc.edu            if (pkt->needsResponse())
30210447Snilay@cs.wisc.edu                pkt->makeResponse();
30310447Snilay@cs.wisc.edu            return;
30410447Snilay@cs.wisc.edu        }
30510447Snilay@cs.wisc.edu    }
30610447Snilay@cs.wisc.edu
30710447Snilay@cs.wisc.edu    // determine the destination port
30810447Snilay@cs.wisc.edu    PortID dest_id = findPort(pkt->getAddr());
30910447Snilay@cs.wisc.edu
31010447Snilay@cs.wisc.edu    // forward the request to the appropriate destination
31110447Snilay@cs.wisc.edu    masterPorts[dest_id]->sendFunctional(pkt);
31210447Snilay@cs.wisc.edu}
31310447Snilay@cs.wisc.edu
31410447Snilay@cs.wisc.eduNoncoherentXBar*
31510447Snilay@cs.wisc.eduNoncoherentXBarParams::create()
31610447Snilay@cs.wisc.edu{
31710447Snilay@cs.wisc.edu    return new NoncoherentXBar(this);
31810447Snilay@cs.wisc.edu}
31910447Snilay@cs.wisc.edu
32010447Snilay@cs.wisc.eduvoid
32110447Snilay@cs.wisc.eduNoncoherentXBar::regStats()
32210447Snilay@cs.wisc.edu{
32310447Snilay@cs.wisc.edu    // register the stats of the base class and our layers
32410447Snilay@cs.wisc.edu    BaseXBar::regStats();
32510447Snilay@cs.wisc.edu    for (auto l: reqLayers)
32610447Snilay@cs.wisc.edu        l->regStats();
32710447Snilay@cs.wisc.edu    for (auto l: respLayers)
32810447Snilay@cs.wisc.edu        l->regStats();
32910447Snilay@cs.wisc.edu}
33010447Snilay@cs.wisc.edu