coherent_xbar.cc revision 9095
112027Sjungma@eit.uni-kl.de/*
212027Sjungma@eit.uni-kl.de * Copyright (c) 2011-2012 ARM Limited
312027Sjungma@eit.uni-kl.de * All rights reserved
412027Sjungma@eit.uni-kl.de *
512027Sjungma@eit.uni-kl.de * The license below extends only to copyright in the software and shall
612027Sjungma@eit.uni-kl.de * not be construed as granting a license to any other intellectual
712027Sjungma@eit.uni-kl.de * property including but not limited to intellectual property relating
812027Sjungma@eit.uni-kl.de * to a hardware implementation of the functionality of the software
912027Sjungma@eit.uni-kl.de * licensed hereunder.  You may use the software subject to the license
1012027Sjungma@eit.uni-kl.de * terms below provided that you ensure that this notice is replicated
1112027Sjungma@eit.uni-kl.de * unmodified and in its entirety in all distributions of the software,
1212027Sjungma@eit.uni-kl.de * modified or unmodified, in source code or in binary form.
1312027Sjungma@eit.uni-kl.de *
1412027Sjungma@eit.uni-kl.de * Copyright (c) 2006 The Regents of The University of Michigan
1512027Sjungma@eit.uni-kl.de * All rights reserved.
1612027Sjungma@eit.uni-kl.de *
1712027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without
1812027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions are
1912027Sjungma@eit.uni-kl.de * met: redistributions of source code must retain the above copyright
2012027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer;
2112027Sjungma@eit.uni-kl.de * redistributions in binary form must reproduce the above copyright
2212027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer in the
2312027Sjungma@eit.uni-kl.de * documentation and/or other materials provided with the distribution;
2412027Sjungma@eit.uni-kl.de * neither the name of the copyright holders nor the names of its
2512027Sjungma@eit.uni-kl.de * contributors may be used to endorse or promote products derived from
2612027Sjungma@eit.uni-kl.de * this software without specific prior written permission.
2712027Sjungma@eit.uni-kl.de *
2812027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2912027Sjungma@eit.uni-kl.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3012027Sjungma@eit.uni-kl.de * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3112027Sjungma@eit.uni-kl.de * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3212027Sjungma@eit.uni-kl.de * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3312027Sjungma@eit.uni-kl.de * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3412027Sjungma@eit.uni-kl.de * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3512027Sjungma@eit.uni-kl.de * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3612027Sjungma@eit.uni-kl.de * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3712027Sjungma@eit.uni-kl.de * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3812027Sjungma@eit.uni-kl.de * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3912027Sjungma@eit.uni-kl.de *
4012027Sjungma@eit.uni-kl.de * Authors: Ali Saidi
4112027Sjungma@eit.uni-kl.de *          Andreas Hansson
4212027Sjungma@eit.uni-kl.de *          William Wang
4312027Sjungma@eit.uni-kl.de */
4412027Sjungma@eit.uni-kl.de
4512027Sjungma@eit.uni-kl.de/**
4612027Sjungma@eit.uni-kl.de * @file
4712027Sjungma@eit.uni-kl.de * Definition of a bus object.
4812027Sjungma@eit.uni-kl.de */
4912027Sjungma@eit.uni-kl.de
5012027Sjungma@eit.uni-kl.de#include "base/misc.hh"
5112027Sjungma@eit.uni-kl.de#include "base/trace.hh"
5212027Sjungma@eit.uni-kl.de#include "debug/BusAddrRanges.hh"
5312027Sjungma@eit.uni-kl.de#include "debug/CoherentBus.hh"
5412027Sjungma@eit.uni-kl.de#include "mem/coherent_bus.hh"
5512027Sjungma@eit.uni-kl.de
5612027Sjungma@eit.uni-kl.deCoherentBus::CoherentBus(const CoherentBusParams *p)
5712027Sjungma@eit.uni-kl.de    : BaseBus(p), reqLayer(*this, ".reqLayer", p->clock),
5812027Sjungma@eit.uni-kl.de      respLayer(*this, ".respLayer", p->clock),
5912027Sjungma@eit.uni-kl.de      snoopRespLayer(*this, ".snoopRespLayer", p->clock)
6012027Sjungma@eit.uni-kl.de{
6112027Sjungma@eit.uni-kl.de    // create the ports based on the size of the master and slave
6212027Sjungma@eit.uni-kl.de    // vector ports, and the presence of the default port, the ports
6312027Sjungma@eit.uni-kl.de    // are enumerated starting from zero
6412027Sjungma@eit.uni-kl.de    for (int i = 0; i < p->port_master_connection_count; ++i) {
6512027Sjungma@eit.uni-kl.de        std::string portName = csprintf("%s.master[%d]", name(), i);
6612027Sjungma@eit.uni-kl.de        MasterPort* bp = new CoherentBusMasterPort(portName, *this, i);
6712027Sjungma@eit.uni-kl.de        masterPorts.push_back(bp);
6812027Sjungma@eit.uni-kl.de    }
6912027Sjungma@eit.uni-kl.de
7012027Sjungma@eit.uni-kl.de    // see if we have a default slave device connected and if so add
7112027Sjungma@eit.uni-kl.de    // our corresponding master port
7212027Sjungma@eit.uni-kl.de    if (p->port_default_connection_count) {
7312027Sjungma@eit.uni-kl.de        defaultPortID = masterPorts.size();
7412027Sjungma@eit.uni-kl.de        std::string portName = name() + ".default";
7512027Sjungma@eit.uni-kl.de        MasterPort* bp = new CoherentBusMasterPort(portName, *this,
7612027Sjungma@eit.uni-kl.de                                                   defaultPortID);
7712027Sjungma@eit.uni-kl.de        masterPorts.push_back(bp);
7812027Sjungma@eit.uni-kl.de    }
7912027Sjungma@eit.uni-kl.de
8012027Sjungma@eit.uni-kl.de    // create the slave ports, once again starting at zero
8112027Sjungma@eit.uni-kl.de    for (int i = 0; i < p->port_slave_connection_count; ++i) {
8212027Sjungma@eit.uni-kl.de        std::string portName = csprintf("%s.slave[%d]", name(), i);
8312027Sjungma@eit.uni-kl.de        SlavePort* bp = new CoherentBusSlavePort(portName, *this, i);
8412027Sjungma@eit.uni-kl.de        slavePorts.push_back(bp);
8512027Sjungma@eit.uni-kl.de    }
8612027Sjungma@eit.uni-kl.de
8712027Sjungma@eit.uni-kl.de    clearPortCache();
8812027Sjungma@eit.uni-kl.de}
8912027Sjungma@eit.uni-kl.de
9012027Sjungma@eit.uni-kl.devoid
9112027Sjungma@eit.uni-kl.deCoherentBus::init()
9212027Sjungma@eit.uni-kl.de{
9312027Sjungma@eit.uni-kl.de    // iterate over our slave ports and determine which of our
9412027Sjungma@eit.uni-kl.de    // neighbouring master ports are snooping and add them as snoopers
9512027Sjungma@eit.uni-kl.de    for (SlavePortConstIter p = slavePorts.begin(); p != slavePorts.end();
9612027Sjungma@eit.uni-kl.de         ++p) {
9712027Sjungma@eit.uni-kl.de        // check if the connected master port is snooping
9812027Sjungma@eit.uni-kl.de        if ((*p)->isSnooping()) {
9912027Sjungma@eit.uni-kl.de            DPRINTF(BusAddrRanges, "Adding snooping master %s\n",
10012027Sjungma@eit.uni-kl.de                    (*p)->getMasterPort().name());
10112027Sjungma@eit.uni-kl.de            snoopPorts.push_back(*p);
10212027Sjungma@eit.uni-kl.de        }
10312027Sjungma@eit.uni-kl.de    }
10412027Sjungma@eit.uni-kl.de
10512027Sjungma@eit.uni-kl.de    if (snoopPorts.empty())
10612027Sjungma@eit.uni-kl.de        warn("CoherentBus %s has no snooping ports attached!\n", name());
10712027Sjungma@eit.uni-kl.de}
10812027Sjungma@eit.uni-kl.de
10912027Sjungma@eit.uni-kl.debool
11012027Sjungma@eit.uni-kl.deCoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
11112027Sjungma@eit.uni-kl.de{
11212027Sjungma@eit.uni-kl.de    // determine the source port based on the id
11312027Sjungma@eit.uni-kl.de    SlavePort *src_port = slavePorts[slave_port_id];
11412027Sjungma@eit.uni-kl.de
11512027Sjungma@eit.uni-kl.de    // remember if the packet is an express snoop
11612027Sjungma@eit.uni-kl.de    bool is_express_snoop = pkt->isExpressSnoop();
11712027Sjungma@eit.uni-kl.de
11812027Sjungma@eit.uni-kl.de    // test if the bus should be considered occupied for the current
11912027Sjungma@eit.uni-kl.de    // port, and exclude express snoops from the check
12012027Sjungma@eit.uni-kl.de    if (!is_express_snoop && !reqLayer.tryTiming(src_port)) {
12112027Sjungma@eit.uni-kl.de        DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x BUSY\n",
12212027Sjungma@eit.uni-kl.de                src_port->name(), pkt->cmdString(), pkt->getAddr());
12312027Sjungma@eit.uni-kl.de        return false;
12412027Sjungma@eit.uni-kl.de    }
12512027Sjungma@eit.uni-kl.de
12612027Sjungma@eit.uni-kl.de    DPRINTF(CoherentBus, "recvTimingReq: src %s %s expr %d 0x%x\n",
12712027Sjungma@eit.uni-kl.de            src_port->name(), pkt->cmdString(), is_express_snoop,
12812027Sjungma@eit.uni-kl.de            pkt->getAddr());
12912027Sjungma@eit.uni-kl.de
13012027Sjungma@eit.uni-kl.de    // set the source port for routing of the response
13112027Sjungma@eit.uni-kl.de    pkt->setSrc(slave_port_id);
13212027Sjungma@eit.uni-kl.de
13312027Sjungma@eit.uni-kl.de    Tick headerFinishTime = is_express_snoop ? 0 : calcPacketTiming(pkt);
13412027Sjungma@eit.uni-kl.de    Tick packetFinishTime = is_express_snoop ? 0 : pkt->finishTime;
13512027Sjungma@eit.uni-kl.de
13612027Sjungma@eit.uni-kl.de    // uncacheable requests need never be snooped
13712027Sjungma@eit.uni-kl.de    if (!pkt->req->isUncacheable()) {
13812027Sjungma@eit.uni-kl.de        // the packet is a memory-mapped request and should be
13912027Sjungma@eit.uni-kl.de        // broadcasted to our snoopers but the source
14012027Sjungma@eit.uni-kl.de        forwardTiming(pkt, slave_port_id);
14112027Sjungma@eit.uni-kl.de    }
14212027Sjungma@eit.uni-kl.de
14312027Sjungma@eit.uni-kl.de    // remember if we add an outstanding req so we can undo it if
14412027Sjungma@eit.uni-kl.de    // necessary, if the packet needs a response, we should add it
14512027Sjungma@eit.uni-kl.de    // as outstanding and express snoops never fail so there is
14612027Sjungma@eit.uni-kl.de    // not need to worry about them
14712027Sjungma@eit.uni-kl.de    bool add_outstanding = !is_express_snoop && pkt->needsResponse();
14812027Sjungma@eit.uni-kl.de
14912027Sjungma@eit.uni-kl.de    // keep track that we have an outstanding request packet
15012027Sjungma@eit.uni-kl.de    // matching this request, this is used by the coherency
15112027Sjungma@eit.uni-kl.de    // mechanism in determining what to do with snoop responses
15212027Sjungma@eit.uni-kl.de    // (in recvTimingSnoop)
15312027Sjungma@eit.uni-kl.de    if (add_outstanding) {
15412027Sjungma@eit.uni-kl.de        // we should never have an exsiting request outstanding
15512027Sjungma@eit.uni-kl.de        assert(outstandingReq.find(pkt->req) == outstandingReq.end());
15612027Sjungma@eit.uni-kl.de        outstandingReq.insert(pkt->req);
15712027Sjungma@eit.uni-kl.de    }
15812027Sjungma@eit.uni-kl.de
15912027Sjungma@eit.uni-kl.de    // since it is a normal request, determine the destination
16012027Sjungma@eit.uni-kl.de    // based on the address and attempt to send the packet
16112027Sjungma@eit.uni-kl.de    bool success = masterPorts[findPort(pkt->getAddr())]->sendTimingReq(pkt);
16212027Sjungma@eit.uni-kl.de
16312027Sjungma@eit.uni-kl.de    // if this is an express snoop, we are done at this point
16412027Sjungma@eit.uni-kl.de    if (is_express_snoop) {
16512027Sjungma@eit.uni-kl.de        assert(success);
16612027Sjungma@eit.uni-kl.de    } else {
16712027Sjungma@eit.uni-kl.de        // for normal requests, check if successful
16812027Sjungma@eit.uni-kl.de        if (!success)  {
16912027Sjungma@eit.uni-kl.de            // inhibited packets should never be forced to retry
17012027Sjungma@eit.uni-kl.de            assert(!pkt->memInhibitAsserted());
17112027Sjungma@eit.uni-kl.de
17212027Sjungma@eit.uni-kl.de            // if it was added as outstanding and the send failed, then
17312027Sjungma@eit.uni-kl.de            // erase it again
17412027Sjungma@eit.uni-kl.de            if (add_outstanding)
17512027Sjungma@eit.uni-kl.de                outstandingReq.erase(pkt->req);
17612027Sjungma@eit.uni-kl.de
17712027Sjungma@eit.uni-kl.de            DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x RETRY\n",
17812027Sjungma@eit.uni-kl.de                    src_port->name(), pkt->cmdString(), pkt->getAddr());
17912027Sjungma@eit.uni-kl.de
18012027Sjungma@eit.uni-kl.de            // update the bus state and schedule an idle event
18112027Sjungma@eit.uni-kl.de            reqLayer.failedTiming(src_port, headerFinishTime);
18212027Sjungma@eit.uni-kl.de        } else {
18312027Sjungma@eit.uni-kl.de            // update the bus state and schedule an idle event
18412027Sjungma@eit.uni-kl.de            reqLayer.succeededTiming(packetFinishTime);
18512027Sjungma@eit.uni-kl.de        }
18612027Sjungma@eit.uni-kl.de    }
18712027Sjungma@eit.uni-kl.de
18812027Sjungma@eit.uni-kl.de    return success;
18912027Sjungma@eit.uni-kl.de}
19012027Sjungma@eit.uni-kl.de
19112027Sjungma@eit.uni-kl.debool
19212027Sjungma@eit.uni-kl.deCoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
19312027Sjungma@eit.uni-kl.de{
19412027Sjungma@eit.uni-kl.de    // determine the source port based on the id
19512027Sjungma@eit.uni-kl.de    MasterPort *src_port = masterPorts[master_port_id];
19612027Sjungma@eit.uni-kl.de
19712027Sjungma@eit.uni-kl.de    // test if the bus should be considered occupied for the current
19812027Sjungma@eit.uni-kl.de    // port
19912027Sjungma@eit.uni-kl.de    if (!respLayer.tryTiming(src_port)) {
20012027Sjungma@eit.uni-kl.de        DPRINTF(CoherentBus, "recvTimingResp: src %s %s 0x%x BUSY\n",
20112027Sjungma@eit.uni-kl.de                src_port->name(), pkt->cmdString(), pkt->getAddr());
20212027Sjungma@eit.uni-kl.de        return false;
20312027Sjungma@eit.uni-kl.de    }
20412027Sjungma@eit.uni-kl.de
20512027Sjungma@eit.uni-kl.de    DPRINTF(CoherentBus, "recvTimingResp: src %s %s 0x%x\n",
20612027Sjungma@eit.uni-kl.de            src_port->name(), pkt->cmdString(), pkt->getAddr());
20712027Sjungma@eit.uni-kl.de
20812027Sjungma@eit.uni-kl.de    calcPacketTiming(pkt);
20912027Sjungma@eit.uni-kl.de    Tick packetFinishTime = pkt->finishTime;
21012027Sjungma@eit.uni-kl.de
21112027Sjungma@eit.uni-kl.de    // the packet is a normal response to a request that we should
21212027Sjungma@eit.uni-kl.de    // have seen passing through the bus
21312027Sjungma@eit.uni-kl.de    assert(outstandingReq.find(pkt->req) != outstandingReq.end());
21412027Sjungma@eit.uni-kl.de
21512027Sjungma@eit.uni-kl.de    // remove it as outstanding
21612027Sjungma@eit.uni-kl.de    outstandingReq.erase(pkt->req);
21712027Sjungma@eit.uni-kl.de
21812027Sjungma@eit.uni-kl.de    // send the packet to the destination through one of our slave
21912027Sjungma@eit.uni-kl.de    // ports, as determined by the destination field
22012027Sjungma@eit.uni-kl.de    bool success M5_VAR_USED = slavePorts[pkt->getDest()]->sendTimingResp(pkt);
22112027Sjungma@eit.uni-kl.de
22212027Sjungma@eit.uni-kl.de    // currently it is illegal to block responses... can lead to
22312027Sjungma@eit.uni-kl.de    // deadlock
22412027Sjungma@eit.uni-kl.de    assert(success);
22512027Sjungma@eit.uni-kl.de
22612027Sjungma@eit.uni-kl.de    respLayer.succeededTiming(packetFinishTime);
22712027Sjungma@eit.uni-kl.de
22812027Sjungma@eit.uni-kl.de    return true;
22912027Sjungma@eit.uni-kl.de}
23012027Sjungma@eit.uni-kl.de
23112027Sjungma@eit.uni-kl.devoid
23212027Sjungma@eit.uni-kl.deCoherentBus::recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
23312027Sjungma@eit.uni-kl.de{
23412027Sjungma@eit.uni-kl.de    DPRINTF(CoherentBus, "recvTimingSnoopReq: src %s %s 0x%x\n",
23512027Sjungma@eit.uni-kl.de            masterPorts[master_port_id]->name(), pkt->cmdString(),
23612027Sjungma@eit.uni-kl.de            pkt->getAddr());
23712027Sjungma@eit.uni-kl.de
23812027Sjungma@eit.uni-kl.de    // we should only see express snoops from caches
23912027Sjungma@eit.uni-kl.de    assert(pkt->isExpressSnoop());
24012027Sjungma@eit.uni-kl.de
24112027Sjungma@eit.uni-kl.de    // set the source port for routing of the response
24212027Sjungma@eit.uni-kl.de    pkt->setSrc(master_port_id);
24312027Sjungma@eit.uni-kl.de
24412027Sjungma@eit.uni-kl.de    // forward to all snoopers
24512027Sjungma@eit.uni-kl.de    forwardTiming(pkt, InvalidPortID);
24612027Sjungma@eit.uni-kl.de
24712027Sjungma@eit.uni-kl.de    // a snoop request came from a connected slave device (one of
24812027Sjungma@eit.uni-kl.de    // our master ports), and if it is not coming from the slave
24912027Sjungma@eit.uni-kl.de    // device responsible for the address range something is
25012027Sjungma@eit.uni-kl.de    // wrong, hence there is nothing further to do as the packet
25112027Sjungma@eit.uni-kl.de    // would be going back to where it came from
25212027Sjungma@eit.uni-kl.de    assert(master_port_id == findPort(pkt->getAddr()));
25312027Sjungma@eit.uni-kl.de}
25412027Sjungma@eit.uni-kl.de
25512027Sjungma@eit.uni-kl.debool
25612027Sjungma@eit.uni-kl.deCoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
25712027Sjungma@eit.uni-kl.de{
25812027Sjungma@eit.uni-kl.de    // determine the source port based on the id
25912027Sjungma@eit.uni-kl.de    SlavePort* src_port = slavePorts[slave_port_id];
26012027Sjungma@eit.uni-kl.de
26112027Sjungma@eit.uni-kl.de    // test if the bus should be considered occupied for the current
26212027Sjungma@eit.uni-kl.de    // port
26312027Sjungma@eit.uni-kl.de    if (!snoopRespLayer.tryTiming(src_port)) {
26412027Sjungma@eit.uni-kl.de        DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n",
26512027Sjungma@eit.uni-kl.de                src_port->name(), pkt->cmdString(), pkt->getAddr());
26612027Sjungma@eit.uni-kl.de        return false;
26712027Sjungma@eit.uni-kl.de    }
26812027Sjungma@eit.uni-kl.de
26912027Sjungma@eit.uni-kl.de    DPRINTF(CoherentBus, "recvTimingSnoop: src %s %s 0x%x\n",
27012027Sjungma@eit.uni-kl.de            src_port->name(), pkt->cmdString(), pkt->getAddr());
27112027Sjungma@eit.uni-kl.de
27212027Sjungma@eit.uni-kl.de    // get the destination from the packet
27312027Sjungma@eit.uni-kl.de    PortID dest = pkt->getDest();
27412027Sjungma@eit.uni-kl.de
27512027Sjungma@eit.uni-kl.de    // responses are never express snoops
27612027Sjungma@eit.uni-kl.de    assert(!pkt->isExpressSnoop());
27712027Sjungma@eit.uni-kl.de
27812027Sjungma@eit.uni-kl.de    calcPacketTiming(pkt);
27912027Sjungma@eit.uni-kl.de    Tick packetFinishTime = pkt->finishTime;
28012027Sjungma@eit.uni-kl.de
28112027Sjungma@eit.uni-kl.de    // determine if the response is from a snoop request we
28212027Sjungma@eit.uni-kl.de    // created as the result of a normal request (in which case it
28312027Sjungma@eit.uni-kl.de    // should be in the outstandingReq), or if we merely forwarded
28412027Sjungma@eit.uni-kl.de    // someone else's snoop request
28512027Sjungma@eit.uni-kl.de    if (outstandingReq.find(pkt->req) == outstandingReq.end()) {
28612027Sjungma@eit.uni-kl.de        // this is a snoop response to a snoop request we
28712027Sjungma@eit.uni-kl.de        // forwarded, e.g. coming from the L1 and going to the L2
28812027Sjungma@eit.uni-kl.de        // this should be forwarded as a snoop response
28912027Sjungma@eit.uni-kl.de        bool success M5_VAR_USED = masterPorts[dest]->sendTimingSnoopResp(pkt);
29012027Sjungma@eit.uni-kl.de        assert(success);
29112027Sjungma@eit.uni-kl.de    } else {
29212027Sjungma@eit.uni-kl.de        // we got a snoop response on one of our slave ports,
29312027Sjungma@eit.uni-kl.de        // i.e. from a coherent master connected to the bus, and
29412027Sjungma@eit.uni-kl.de        // since we created the snoop request as part of
29512027Sjungma@eit.uni-kl.de        // recvTiming, this should now be a normal response again
29612027Sjungma@eit.uni-kl.de        outstandingReq.erase(pkt->req);
29712027Sjungma@eit.uni-kl.de
29812027Sjungma@eit.uni-kl.de        // this is a snoop response from a coherent master, with a
29912027Sjungma@eit.uni-kl.de        // destination field set on its way through the bus as
30012027Sjungma@eit.uni-kl.de        // request, hence it should never go back to where the
30112027Sjungma@eit.uni-kl.de        // snoop response came from, but instead to where the
30212027Sjungma@eit.uni-kl.de        // original request came from
30312027Sjungma@eit.uni-kl.de        assert(slave_port_id != dest);
30412027Sjungma@eit.uni-kl.de
30512027Sjungma@eit.uni-kl.de        // as a normal response, it should go back to a master
30612027Sjungma@eit.uni-kl.de        // through one of our slave ports
30712027Sjungma@eit.uni-kl.de        bool success M5_VAR_USED = slavePorts[dest]->sendTimingResp(pkt);
30812027Sjungma@eit.uni-kl.de
30912027Sjungma@eit.uni-kl.de        // currently it is illegal to block responses... can lead
31012027Sjungma@eit.uni-kl.de        // to deadlock
31112027Sjungma@eit.uni-kl.de        assert(success);
31212027Sjungma@eit.uni-kl.de    }
31312027Sjungma@eit.uni-kl.de
31412027Sjungma@eit.uni-kl.de    snoopRespLayer.succeededTiming(packetFinishTime);
31512027Sjungma@eit.uni-kl.de
31612027Sjungma@eit.uni-kl.de    return true;
31712027Sjungma@eit.uni-kl.de}
31812027Sjungma@eit.uni-kl.de
31912027Sjungma@eit.uni-kl.de
32012027Sjungma@eit.uni-kl.devoid
32112027Sjungma@eit.uni-kl.deCoherentBus::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id)
32212027Sjungma@eit.uni-kl.de{
32312027Sjungma@eit.uni-kl.de    for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
32412027Sjungma@eit.uni-kl.de        SlavePort *p = *s;
32512027Sjungma@eit.uni-kl.de        // we could have gotten this request from a snooping master
32612027Sjungma@eit.uni-kl.de        // (corresponding to our own slave port that is also in
32712027Sjungma@eit.uni-kl.de        // snoopPorts) and should not send it back to where it came
32812027Sjungma@eit.uni-kl.de        // from
32912027Sjungma@eit.uni-kl.de        if (exclude_slave_port_id == InvalidPortID ||
33012027Sjungma@eit.uni-kl.de            p->getId() != exclude_slave_port_id) {
33112027Sjungma@eit.uni-kl.de            // cache is not allowed to refuse snoop
33212027Sjungma@eit.uni-kl.de            p->sendTimingSnoopReq(pkt);
33312027Sjungma@eit.uni-kl.de        }
33412027Sjungma@eit.uni-kl.de    }
33512027Sjungma@eit.uni-kl.de}
33612027Sjungma@eit.uni-kl.de
33712027Sjungma@eit.uni-kl.devoid
33812027Sjungma@eit.uni-kl.deCoherentBus::recvRetry()
33912027Sjungma@eit.uni-kl.de{
34012027Sjungma@eit.uni-kl.de    // responses and snoop responses never block on forwarding them,
34112027Sjungma@eit.uni-kl.de    // so the retry will always be coming from a port to which we
34212027Sjungma@eit.uni-kl.de    // tried to forward a request
34312027Sjungma@eit.uni-kl.de    reqLayer.recvRetry();
34412027Sjungma@eit.uni-kl.de}
34512027Sjungma@eit.uni-kl.de
34612027Sjungma@eit.uni-kl.deTick
34712027Sjungma@eit.uni-kl.deCoherentBus::recvAtomic(PacketPtr pkt, PortID slave_port_id)
34812027Sjungma@eit.uni-kl.de{
34912027Sjungma@eit.uni-kl.de    DPRINTF(CoherentBus, "recvAtomic: packet src %s addr 0x%x cmd %s\n",
35012027Sjungma@eit.uni-kl.de            slavePorts[slave_port_id]->name(), pkt->getAddr(),
35112027Sjungma@eit.uni-kl.de            pkt->cmdString());
35212027Sjungma@eit.uni-kl.de
35312027Sjungma@eit.uni-kl.de    MemCmd snoop_response_cmd = MemCmd::InvalidCmd;
35412027Sjungma@eit.uni-kl.de    Tick snoop_response_latency = 0;
35512027Sjungma@eit.uni-kl.de
35612027Sjungma@eit.uni-kl.de    // uncacheable requests need never be snooped
35712027Sjungma@eit.uni-kl.de    if (!pkt->req->isUncacheable()) {
35812027Sjungma@eit.uni-kl.de        // forward to all snoopers but the source
35912027Sjungma@eit.uni-kl.de        std::pair<MemCmd, Tick> snoop_result =
36012027Sjungma@eit.uni-kl.de            forwardAtomic(pkt, slave_port_id);
36112027Sjungma@eit.uni-kl.de        snoop_response_cmd = snoop_result.first;
36212027Sjungma@eit.uni-kl.de        snoop_response_latency = snoop_result.second;
36312027Sjungma@eit.uni-kl.de    }
36412027Sjungma@eit.uni-kl.de
36512027Sjungma@eit.uni-kl.de    // even if we had a snoop response, we must continue and also
36612027Sjungma@eit.uni-kl.de    // perform the actual request at the destination
36712027Sjungma@eit.uni-kl.de    PortID dest_id = findPort(pkt->getAddr());
36812027Sjungma@eit.uni-kl.de
36912027Sjungma@eit.uni-kl.de    // forward the request to the appropriate destination
37012027Sjungma@eit.uni-kl.de    Tick response_latency = masterPorts[dest_id]->sendAtomic(pkt);
37112027Sjungma@eit.uni-kl.de
37212027Sjungma@eit.uni-kl.de    // if we got a response from a snooper, restore it here
37312027Sjungma@eit.uni-kl.de    if (snoop_response_cmd != MemCmd::InvalidCmd) {
37412027Sjungma@eit.uni-kl.de        // no one else should have responded
37512027Sjungma@eit.uni-kl.de        assert(!pkt->isResponse());
37612027Sjungma@eit.uni-kl.de        pkt->cmd = snoop_response_cmd;
37712027Sjungma@eit.uni-kl.de        response_latency = snoop_response_latency;
37812027Sjungma@eit.uni-kl.de    }
37912027Sjungma@eit.uni-kl.de
38012027Sjungma@eit.uni-kl.de    pkt->finishTime = curTick() + response_latency;
38112027Sjungma@eit.uni-kl.de    return response_latency;
38212027Sjungma@eit.uni-kl.de}
38312027Sjungma@eit.uni-kl.de
38412027Sjungma@eit.uni-kl.deTick
38512027Sjungma@eit.uni-kl.deCoherentBus::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
38612027Sjungma@eit.uni-kl.de{
38712027Sjungma@eit.uni-kl.de    DPRINTF(CoherentBus, "recvAtomicSnoop: packet src %s addr 0x%x cmd %s\n",
38812027Sjungma@eit.uni-kl.de            masterPorts[master_port_id]->name(), pkt->getAddr(),
38912027Sjungma@eit.uni-kl.de            pkt->cmdString());
39012027Sjungma@eit.uni-kl.de
39112027Sjungma@eit.uni-kl.de    // forward to all snoopers
39212027Sjungma@eit.uni-kl.de    std::pair<MemCmd, Tick> snoop_result =
39312027Sjungma@eit.uni-kl.de        forwardAtomic(pkt, InvalidPortID);
39412027Sjungma@eit.uni-kl.de    MemCmd snoop_response_cmd = snoop_result.first;
39512027Sjungma@eit.uni-kl.de    Tick snoop_response_latency = snoop_result.second;
39612027Sjungma@eit.uni-kl.de
39712027Sjungma@eit.uni-kl.de    if (snoop_response_cmd != MemCmd::InvalidCmd)
39812027Sjungma@eit.uni-kl.de        pkt->cmd = snoop_response_cmd;
39912027Sjungma@eit.uni-kl.de
40012027Sjungma@eit.uni-kl.de    pkt->finishTime = curTick() + snoop_response_latency;
40112027Sjungma@eit.uni-kl.de    return snoop_response_latency;
40212027Sjungma@eit.uni-kl.de}
40312027Sjungma@eit.uni-kl.de
40412027Sjungma@eit.uni-kl.destd::pair<MemCmd, Tick>
40512027Sjungma@eit.uni-kl.deCoherentBus::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id)
40612027Sjungma@eit.uni-kl.de{
40712027Sjungma@eit.uni-kl.de    // the packet may be changed on snoops, record the original
40812027Sjungma@eit.uni-kl.de    // command to enable us to restore it between snoops so that
40912027Sjungma@eit.uni-kl.de    // additional snoops can take place properly
41012027Sjungma@eit.uni-kl.de    MemCmd orig_cmd = pkt->cmd;
41112027Sjungma@eit.uni-kl.de    MemCmd snoop_response_cmd = MemCmd::InvalidCmd;
41212027Sjungma@eit.uni-kl.de    Tick snoop_response_latency = 0;
41312027Sjungma@eit.uni-kl.de
41412027Sjungma@eit.uni-kl.de    for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
41512027Sjungma@eit.uni-kl.de        SlavePort *p = *s;
41612027Sjungma@eit.uni-kl.de        // we could have gotten this request from a snooping master
41712027Sjungma@eit.uni-kl.de        // (corresponding to our own slave port that is also in
41812027Sjungma@eit.uni-kl.de        // snoopPorts) and should not send it back to where it came
41912027Sjungma@eit.uni-kl.de        // from
42012027Sjungma@eit.uni-kl.de        if (exclude_slave_port_id == InvalidPortID ||
42112027Sjungma@eit.uni-kl.de            p->getId() != exclude_slave_port_id) {
42212027Sjungma@eit.uni-kl.de            Tick latency = p->sendAtomicSnoop(pkt);
42312027Sjungma@eit.uni-kl.de            // in contrast to a functional access, we have to keep on
42412027Sjungma@eit.uni-kl.de            // going as all snoopers must be updated even if we get a
42512027Sjungma@eit.uni-kl.de            // response
42612027Sjungma@eit.uni-kl.de            if (pkt->isResponse()) {
42712027Sjungma@eit.uni-kl.de                // response from snoop agent
42812027Sjungma@eit.uni-kl.de                assert(pkt->cmd != orig_cmd);
42912027Sjungma@eit.uni-kl.de                assert(pkt->memInhibitAsserted());
43012027Sjungma@eit.uni-kl.de                // should only happen once
43112027Sjungma@eit.uni-kl.de                assert(snoop_response_cmd == MemCmd::InvalidCmd);
43212027Sjungma@eit.uni-kl.de                // save response state
43312027Sjungma@eit.uni-kl.de                snoop_response_cmd = pkt->cmd;
43412027Sjungma@eit.uni-kl.de                snoop_response_latency = latency;
43512027Sjungma@eit.uni-kl.de                // restore original packet state for remaining snoopers
43612027Sjungma@eit.uni-kl.de                pkt->cmd = orig_cmd;
43712027Sjungma@eit.uni-kl.de            }
43812027Sjungma@eit.uni-kl.de        }
43912027Sjungma@eit.uni-kl.de    }
44012027Sjungma@eit.uni-kl.de
44112027Sjungma@eit.uni-kl.de    // the packet is restored as part of the loop and any potential
44212027Sjungma@eit.uni-kl.de    // snoop response is part of the returned pair
44312027Sjungma@eit.uni-kl.de    return std::make_pair(snoop_response_cmd, snoop_response_latency);
44412027Sjungma@eit.uni-kl.de}
44512027Sjungma@eit.uni-kl.de
44612027Sjungma@eit.uni-kl.devoid
44712027Sjungma@eit.uni-kl.deCoherentBus::recvFunctional(PacketPtr pkt, PortID slave_port_id)
44812027Sjungma@eit.uni-kl.de{
44912027Sjungma@eit.uni-kl.de    if (!pkt->isPrint()) {
45012027Sjungma@eit.uni-kl.de        // don't do DPRINTFs on PrintReq as it clutters up the output
45112027Sjungma@eit.uni-kl.de        DPRINTF(CoherentBus,
45212027Sjungma@eit.uni-kl.de                "recvFunctional: packet src %s addr 0x%x cmd %s\n",
45312027Sjungma@eit.uni-kl.de                slavePorts[slave_port_id]->name(), pkt->getAddr(),
45412027Sjungma@eit.uni-kl.de                pkt->cmdString());
45512027Sjungma@eit.uni-kl.de    }
45612027Sjungma@eit.uni-kl.de
45712027Sjungma@eit.uni-kl.de    // uncacheable requests need never be snooped
45812027Sjungma@eit.uni-kl.de    if (!pkt->req->isUncacheable()) {
45912027Sjungma@eit.uni-kl.de        // forward to all snoopers but the source
46012027Sjungma@eit.uni-kl.de        forwardFunctional(pkt, slave_port_id);
46112027Sjungma@eit.uni-kl.de    }
46212027Sjungma@eit.uni-kl.de
46312027Sjungma@eit.uni-kl.de    // there is no need to continue if the snooping has found what we
46412027Sjungma@eit.uni-kl.de    // were looking for and the packet is already a response
46512027Sjungma@eit.uni-kl.de    if (!pkt->isResponse()) {
46612027Sjungma@eit.uni-kl.de        PortID dest_id = findPort(pkt->getAddr());
46712027Sjungma@eit.uni-kl.de
46812027Sjungma@eit.uni-kl.de        masterPorts[dest_id]->sendFunctional(pkt);
46912027Sjungma@eit.uni-kl.de    }
47012027Sjungma@eit.uni-kl.de}
47112027Sjungma@eit.uni-kl.de
47212027Sjungma@eit.uni-kl.devoid
47312027Sjungma@eit.uni-kl.deCoherentBus::recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id)
47412027Sjungma@eit.uni-kl.de{
47512027Sjungma@eit.uni-kl.de    if (!pkt->isPrint()) {
47612027Sjungma@eit.uni-kl.de        // don't do DPRINTFs on PrintReq as it clutters up the output
47712027Sjungma@eit.uni-kl.de        DPRINTF(CoherentBus,
47812027Sjungma@eit.uni-kl.de                "recvFunctionalSnoop: packet src %s addr 0x%x cmd %s\n",
47912027Sjungma@eit.uni-kl.de                masterPorts[master_port_id]->name(), pkt->getAddr(),
48012027Sjungma@eit.uni-kl.de                pkt->cmdString());
48112027Sjungma@eit.uni-kl.de    }
48212027Sjungma@eit.uni-kl.de
48312027Sjungma@eit.uni-kl.de    // forward to all snoopers
48412027Sjungma@eit.uni-kl.de    forwardFunctional(pkt, InvalidPortID);
48512027Sjungma@eit.uni-kl.de}
48612027Sjungma@eit.uni-kl.de
48712027Sjungma@eit.uni-kl.devoid
48812027Sjungma@eit.uni-kl.deCoherentBus::forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id)
48912027Sjungma@eit.uni-kl.de{
49012027Sjungma@eit.uni-kl.de    for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
49112027Sjungma@eit.uni-kl.de        SlavePort *p = *s;
49212027Sjungma@eit.uni-kl.de        // we could have gotten this request from a snooping master
49312027Sjungma@eit.uni-kl.de        // (corresponding to our own slave port that is also in
49412027Sjungma@eit.uni-kl.de        // snoopPorts) and should not send it back to where it came
49512027Sjungma@eit.uni-kl.de        // from
49612027Sjungma@eit.uni-kl.de        if (exclude_slave_port_id == InvalidPortID ||
49712027Sjungma@eit.uni-kl.de            p->getId() != exclude_slave_port_id)
49812027Sjungma@eit.uni-kl.de            p->sendFunctionalSnoop(pkt);
49912027Sjungma@eit.uni-kl.de
50012027Sjungma@eit.uni-kl.de        // if we get a response we are done
50112027Sjungma@eit.uni-kl.de        if (pkt->isResponse()) {
50212027Sjungma@eit.uni-kl.de            break;
50312027Sjungma@eit.uni-kl.de        }
50412027Sjungma@eit.uni-kl.de    }
50512027Sjungma@eit.uni-kl.de}
50612027Sjungma@eit.uni-kl.de
50712027Sjungma@eit.uni-kl.deunsigned int
50812027Sjungma@eit.uni-kl.deCoherentBus::drain(Event *de)
50912027Sjungma@eit.uni-kl.de{
51012027Sjungma@eit.uni-kl.de    // sum up the individual layers
51112027Sjungma@eit.uni-kl.de    return reqLayer.drain(de) + respLayer.drain(de) + snoopRespLayer.drain(de);
51212027Sjungma@eit.uni-kl.de}
51312027Sjungma@eit.uni-kl.de
51412027Sjungma@eit.uni-kl.deCoherentBus *
51512027Sjungma@eit.uni-kl.deCoherentBusParams::create()
51612027Sjungma@eit.uni-kl.de{
51712027Sjungma@eit.uni-kl.de    return new CoherentBus(this);
51812027Sjungma@eit.uni-kl.de}
51912027Sjungma@eit.uni-kl.de