coherent_xbar.cc revision 9036
15647Sgblack@eecs.umich.edu/* 29544Sandreas.hansson@arm.com * Copyright (c) 2011-2012 ARM Limited 38922Swilliam.wang@arm.com * All rights reserved 48922Swilliam.wang@arm.com * 58922Swilliam.wang@arm.com * The license below extends only to copyright in the software and shall 68922Swilliam.wang@arm.com * not be construed as granting a license to any other intellectual 78922Swilliam.wang@arm.com * property including but not limited to intellectual property relating 88922Swilliam.wang@arm.com * to a hardware implementation of the functionality of the software 98922Swilliam.wang@arm.com * licensed hereunder. You may use the software subject to the license 108922Swilliam.wang@arm.com * terms below provided that you ensure that this notice is replicated 118922Swilliam.wang@arm.com * unmodified and in its entirety in all distributions of the software, 128922Swilliam.wang@arm.com * modified or unmodified, in source code or in binary form. 138922Swilliam.wang@arm.com * 145647Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan 155647Sgblack@eecs.umich.edu * All rights reserved. 165647Sgblack@eecs.umich.edu * 177087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 187087Snate@binkert.org * modification, are permitted provided that the following conditions are 197087Snate@binkert.org * met: redistributions of source code must retain the above copyright 207087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 217087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 227087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 237087Snate@binkert.org * documentation and/or other materials provided with the distribution; 247087Snate@binkert.org * neither the name of the copyright holders nor the names of its 255647Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 267087Snate@binkert.org * this software without specific prior written permission. 277087Snate@binkert.org * 287087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 297087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 307087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 317087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 327087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 337087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 345647Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 357087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 365647Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 375647Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 385647Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 395647Sgblack@eecs.umich.edu * 405647Sgblack@eecs.umich.edu * Authors: Ali Saidi 415647Sgblack@eecs.umich.edu * Andreas Hansson 425647Sgblack@eecs.umich.edu * William Wang 435647Sgblack@eecs.umich.edu */ 445647Sgblack@eecs.umich.edu 455647Sgblack@eecs.umich.edu/** 465647Sgblack@eecs.umich.edu * @file 475647Sgblack@eecs.umich.edu * Definition of a bus object. 485647Sgblack@eecs.umich.edu */ 495647Sgblack@eecs.umich.edu 505647Sgblack@eecs.umich.edu#include "base/misc.hh" 515647Sgblack@eecs.umich.edu#include "base/trace.hh" 5211793Sbrandon.potter@amd.com#include "debug/BusAddrRanges.hh" 5311793Sbrandon.potter@amd.com#include "debug/CoherentBus.hh" 5410474Sandreas.hansson@arm.com#include "mem/coherent_bus.hh" 5510474Sandreas.hansson@arm.com 5611793Sbrandon.potter@amd.comCoherentBus::CoherentBus(const CoherentBusParams *p) 578229Snate@binkert.org : BaseBus(p) 585647Sgblack@eecs.umich.edu{ 598232Snate@binkert.org // create the ports based on the size of the master and slave 606137Sgblack@eecs.umich.edu // vector ports, and the presence of the default port, the ports 616137Sgblack@eecs.umich.edu // are enumerated starting from zero 626137Sgblack@eecs.umich.edu for (int i = 0; i < p->port_master_connection_count; ++i) { 635654Sgblack@eecs.umich.edu std::string portName = csprintf("%s-p%d", name(), i); 6411793Sbrandon.potter@amd.com MasterPort* bp = new CoherentBusMasterPort(portName, *this, i); 656046Sgblack@eecs.umich.edu masterPorts.push_back(bp); 665647Sgblack@eecs.umich.edu } 675648Sgblack@eecs.umich.edu 685648Sgblack@eecs.umich.edu // see if we have a default slave device connected and if so add 695647Sgblack@eecs.umich.edu // our corresponding master port 705647Sgblack@eecs.umich.edu if (p->port_default_connection_count) { 715647Sgblack@eecs.umich.edu defaultPortID = masterPorts.size(); 725647Sgblack@eecs.umich.edu std::string portName = csprintf("%s-default", name()); 735647Sgblack@eecs.umich.edu MasterPort* bp = new CoherentBusMasterPort(portName, *this, 745647Sgblack@eecs.umich.edu defaultPortID); 755647Sgblack@eecs.umich.edu masterPorts.push_back(bp); 765647Sgblack@eecs.umich.edu } 775647Sgblack@eecs.umich.edu 785648Sgblack@eecs.umich.edu // create the slave ports, once again starting at zero 795647Sgblack@eecs.umich.edu for (int i = 0; i < p->port_slave_connection_count; ++i) { 805648Sgblack@eecs.umich.edu std::string portName = csprintf("%s-p%d", name(), i); 815648Sgblack@eecs.umich.edu SlavePort* bp = new CoherentBusSlavePort(portName, *this, i); 825648Sgblack@eecs.umich.edu slavePorts.push_back(bp); 835648Sgblack@eecs.umich.edu } 845648Sgblack@eecs.umich.edu 855648Sgblack@eecs.umich.edu clearPortCache(); 865648Sgblack@eecs.umich.edu} 875648Sgblack@eecs.umich.edu 885648Sgblack@eecs.umich.eduvoid 895648Sgblack@eecs.umich.eduCoherentBus::init() 905648Sgblack@eecs.umich.edu{ 915648Sgblack@eecs.umich.edu // iterate over our slave ports and determine which of our 925648Sgblack@eecs.umich.edu // neighbouring master ports are snooping and add them as snoopers 935648Sgblack@eecs.umich.edu for (SlavePortConstIter p = slavePorts.begin(); p != slavePorts.end(); 945648Sgblack@eecs.umich.edu ++p) { 955648Sgblack@eecs.umich.edu if ((*p)->getMasterPort().isSnooping()) { 965648Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "Adding snooping master %s\n", 975648Sgblack@eecs.umich.edu (*p)->getMasterPort().name()); 985648Sgblack@eecs.umich.edu snoopPorts.push_back(*p); 995648Sgblack@eecs.umich.edu } 1005648Sgblack@eecs.umich.edu } 1015648Sgblack@eecs.umich.edu 1025648Sgblack@eecs.umich.edu if (snoopPorts.empty()) 1035648Sgblack@eecs.umich.edu warn("CoherentBus %s has no snooping ports attached!\n", name()); 1045648Sgblack@eecs.umich.edu} 1055648Sgblack@eecs.umich.edu 1065648Sgblack@eecs.umich.edubool 1075648Sgblack@eecs.umich.eduCoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id) 1085648Sgblack@eecs.umich.edu{ 1095648Sgblack@eecs.umich.edu // determine the source port based on the id 1105648Sgblack@eecs.umich.edu SlavePort *src_port = slavePorts[slave_port_id]; 1115648Sgblack@eecs.umich.edu 1125648Sgblack@eecs.umich.edu // test if the bus should be considered occupied for the current 1135648Sgblack@eecs.umich.edu // port, and exclude express snoops from the check 1145648Sgblack@eecs.umich.edu if (!pkt->isExpressSnoop() && isOccupied(src_port)) { 1155648Sgblack@eecs.umich.edu DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x BUSY\n", 1165648Sgblack@eecs.umich.edu src_port->name(), pkt->cmdString(), pkt->getAddr()); 1175648Sgblack@eecs.umich.edu return false; 1185648Sgblack@eecs.umich.edu } 1195648Sgblack@eecs.umich.edu 1205648Sgblack@eecs.umich.edu DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x\n", 1215648Sgblack@eecs.umich.edu src_port->name(), pkt->cmdString(), pkt->getAddr()); 1225648Sgblack@eecs.umich.edu 12311479Sbaz21@cam.ac.uk // set the source port for routing of the response 1245648Sgblack@eecs.umich.edu pkt->setSrc(slave_port_id); 1255648Sgblack@eecs.umich.edu 1265648Sgblack@eecs.umich.edu Tick headerFinishTime = pkt->isExpressSnoop() ? 0 : calcPacketTiming(pkt); 1275648Sgblack@eecs.umich.edu Tick packetFinishTime = pkt->isExpressSnoop() ? 0 : pkt->finishTime; 1285648Sgblack@eecs.umich.edu 1295648Sgblack@eecs.umich.edu // uncacheable requests need never be snooped 1305648Sgblack@eecs.umich.edu if (!pkt->req->isUncacheable()) { 1315648Sgblack@eecs.umich.edu // the packet is a memory-mapped request and should be 1325648Sgblack@eecs.umich.edu // broadcasted to our snoopers but the source 13311479Sbaz21@cam.ac.uk forwardTiming(pkt, slave_port_id); 1345648Sgblack@eecs.umich.edu } 1355648Sgblack@eecs.umich.edu 1365648Sgblack@eecs.umich.edu // remember if we add an outstanding req so we can undo it if 1375648Sgblack@eecs.umich.edu // necessary, if the packet needs a response, we should add it 1385648Sgblack@eecs.umich.edu // as outstanding and express snoops never fail so there is 1395648Sgblack@eecs.umich.edu // not need to worry about them 1405648Sgblack@eecs.umich.edu bool add_outstanding = !pkt->isExpressSnoop() && pkt->needsResponse(); 1415648Sgblack@eecs.umich.edu 1425648Sgblack@eecs.umich.edu // keep track that we have an outstanding request packet 14311479Sbaz21@cam.ac.uk // matching this request, this is used by the coherency 1445648Sgblack@eecs.umich.edu // mechanism in determining what to do with snoop responses 1455648Sgblack@eecs.umich.edu // (in recvTimingSnoop) 1465648Sgblack@eecs.umich.edu if (add_outstanding) { 1475648Sgblack@eecs.umich.edu // we should never have an exsiting request outstanding 1485648Sgblack@eecs.umich.edu assert(outstandingReq.find(pkt->req) == outstandingReq.end()); 1495648Sgblack@eecs.umich.edu outstandingReq.insert(pkt->req); 1505648Sgblack@eecs.umich.edu } 1515648Sgblack@eecs.umich.edu 1525648Sgblack@eecs.umich.edu // since it is a normal request, determine the destination 1535648Sgblack@eecs.umich.edu // based on the address and attempt to send the packet 1545648Sgblack@eecs.umich.edu bool success = masterPorts[findPort(pkt->getAddr())]->sendTimingReq(pkt); 1555648Sgblack@eecs.umich.edu 1565648Sgblack@eecs.umich.edu if (!success) { 1575648Sgblack@eecs.umich.edu // inhibited packets should never be forced to retry 1585648Sgblack@eecs.umich.edu assert(!pkt->memInhibitAsserted()); 1595648Sgblack@eecs.umich.edu 1605648Sgblack@eecs.umich.edu // if it was added as outstanding and the send failed, then 1615648Sgblack@eecs.umich.edu // erase it again 1625648Sgblack@eecs.umich.edu if (add_outstanding) 1635648Sgblack@eecs.umich.edu outstandingReq.erase(pkt->req); 1645648Sgblack@eecs.umich.edu 1655648Sgblack@eecs.umich.edu DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x RETRY\n", 1665648Sgblack@eecs.umich.edu src_port->name(), pkt->cmdString(), pkt->getAddr()); 1675648Sgblack@eecs.umich.edu 1685648Sgblack@eecs.umich.edu addToRetryList(src_port); 1695648Sgblack@eecs.umich.edu occupyBus(headerFinishTime); 1705648Sgblack@eecs.umich.edu 1715648Sgblack@eecs.umich.edu return false; 1725648Sgblack@eecs.umich.edu } 1735648Sgblack@eecs.umich.edu 1745648Sgblack@eecs.umich.edu succeededTiming(packetFinishTime); 1755648Sgblack@eecs.umich.edu 1765648Sgblack@eecs.umich.edu return true; 1775648Sgblack@eecs.umich.edu} 1785648Sgblack@eecs.umich.edu 1795648Sgblack@eecs.umich.edubool 1805648Sgblack@eecs.umich.eduCoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id) 1815648Sgblack@eecs.umich.edu{ 1825648Sgblack@eecs.umich.edu // determine the source port based on the id 1835648Sgblack@eecs.umich.edu MasterPort *src_port = masterPorts[master_port_id]; 1845648Sgblack@eecs.umich.edu 1855648Sgblack@eecs.umich.edu // test if the bus should be considered occupied for the current 1865648Sgblack@eecs.umich.edu // port 1875648Sgblack@eecs.umich.edu if (isOccupied(src_port)) { 1885648Sgblack@eecs.umich.edu DPRINTF(CoherentBus, "recvTimingResp: src %s %s 0x%x BUSY\n", 1895648Sgblack@eecs.umich.edu src_port->name(), pkt->cmdString(), pkt->getAddr()); 1905648Sgblack@eecs.umich.edu return false; 1915648Sgblack@eecs.umich.edu } 1925648Sgblack@eecs.umich.edu 1935648Sgblack@eecs.umich.edu DPRINTF(CoherentBus, "recvTimingResp: src %s %s 0x%x\n", 1945648Sgblack@eecs.umich.edu src_port->name(), pkt->cmdString(), pkt->getAddr()); 1955648Sgblack@eecs.umich.edu 1965648Sgblack@eecs.umich.edu calcPacketTiming(pkt); 1975648Sgblack@eecs.umich.edu Tick packetFinishTime = pkt->finishTime; 1985648Sgblack@eecs.umich.edu 1995649Sgblack@eecs.umich.edu // the packet is a normal response to a request that we should 2005649Sgblack@eecs.umich.edu // have seen passing through the bus 2015649Sgblack@eecs.umich.edu assert(outstandingReq.find(pkt->req) != outstandingReq.end()); 2025648Sgblack@eecs.umich.edu 2035898Sgblack@eecs.umich.edu // remove it as outstanding 2049805Sstever@gmail.com outstandingReq.erase(pkt->req); 2055648Sgblack@eecs.umich.edu 2065648Sgblack@eecs.umich.edu // send the packet to the destination through one of our slave 2075648Sgblack@eecs.umich.edu // ports, as determined by the destination field 2085648Sgblack@eecs.umich.edu bool success M5_VAR_USED = slavePorts[pkt->getDest()]->sendTimingResp(pkt); 2095648Sgblack@eecs.umich.edu 2105648Sgblack@eecs.umich.edu // currently it is illegal to block responses... can lead to 2115648Sgblack@eecs.umich.edu // deadlock 2125648Sgblack@eecs.umich.edu assert(success); 2135648Sgblack@eecs.umich.edu 2145648Sgblack@eecs.umich.edu succeededTiming(packetFinishTime); 2155648Sgblack@eecs.umich.edu 2165648Sgblack@eecs.umich.edu return true; 2175649Sgblack@eecs.umich.edu} 2185649Sgblack@eecs.umich.edu 2195649Sgblack@eecs.umich.eduvoid 2205648Sgblack@eecs.umich.eduCoherentBus::recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id) 2215898Sgblack@eecs.umich.edu{ 2229805Sstever@gmail.com DPRINTF(CoherentBus, "recvTimingSnoopReq: src %s %s 0x%x\n", 2235647Sgblack@eecs.umich.edu masterPorts[master_port_id]->name(), pkt->cmdString(), 2245691Sgblack@eecs.umich.edu pkt->getAddr()); 2255691Sgblack@eecs.umich.edu 2265691Sgblack@eecs.umich.edu // we should only see express snoops from caches 2275691Sgblack@eecs.umich.edu assert(pkt->isExpressSnoop()); 2285691Sgblack@eecs.umich.edu 2295691Sgblack@eecs.umich.edu // set the source port for routing of the response 2305691Sgblack@eecs.umich.edu pkt->setSrc(master_port_id); 2315691Sgblack@eecs.umich.edu 2325691Sgblack@eecs.umich.edu // forward to all snoopers 2335691Sgblack@eecs.umich.edu forwardTiming(pkt, InvalidPortID); 2345691Sgblack@eecs.umich.edu 2355691Sgblack@eecs.umich.edu // a snoop request came from a connected slave device (one of 2365691Sgblack@eecs.umich.edu // our master ports), and if it is not coming from the slave 2375691Sgblack@eecs.umich.edu // device responsible for the address range something is 2385691Sgblack@eecs.umich.edu // wrong, hence there is nothing further to do as the packet 2395691Sgblack@eecs.umich.edu // would be going back to where it came from 2405691Sgblack@eecs.umich.edu assert(master_port_id == findPort(pkt->getAddr())); 2415691Sgblack@eecs.umich.edu 2425691Sgblack@eecs.umich.edu // this is an express snoop and is never forced to retry 2435691Sgblack@eecs.umich.edu assert(!inRetry); 2445691Sgblack@eecs.umich.edu} 2455691Sgblack@eecs.umich.edu 2465691Sgblack@eecs.umich.edubool 2475691Sgblack@eecs.umich.eduCoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id) 2485691Sgblack@eecs.umich.edu{ 2495691Sgblack@eecs.umich.edu // determine the source port based on the id 2505691Sgblack@eecs.umich.edu SlavePort* src_port = slavePorts[slave_port_id]; 2515691Sgblack@eecs.umich.edu 2525691Sgblack@eecs.umich.edu // test if the bus should be considered occupied for the current 2535691Sgblack@eecs.umich.edu // port 2545691Sgblack@eecs.umich.edu if (isOccupied(src_port)) { 2555691Sgblack@eecs.umich.edu DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n", 2565691Sgblack@eecs.umich.edu src_port->name(), pkt->cmdString(), pkt->getAddr()); 2575691Sgblack@eecs.umich.edu return false; 2585691Sgblack@eecs.umich.edu } 2595691Sgblack@eecs.umich.edu 2605691Sgblack@eecs.umich.edu DPRINTF(CoherentBus, "recvTimingSnoop: src %s %s 0x%x\n", 2615691Sgblack@eecs.umich.edu src_port->name(), pkt->cmdString(), pkt->getAddr()); 2625691Sgblack@eecs.umich.edu 2636066Sgblack@eecs.umich.edu // get the destination from the packet 2646066Sgblack@eecs.umich.edu PortID dest = pkt->getDest(); 2656050Sgblack@eecs.umich.edu 2666050Sgblack@eecs.umich.edu // responses are never express snoops 2675691Sgblack@eecs.umich.edu assert(!pkt->isExpressSnoop()); 2688745Sgblack@eecs.umich.edu 2698781Sgblack@eecs.umich.edu calcPacketTiming(pkt); 27011151Smitch.hayenga@arm.com Tick packetFinishTime = pkt->finishTime; 2715691Sgblack@eecs.umich.edu 2725647Sgblack@eecs.umich.edu // determine if the response is from a snoop request we 2736041Sgblack@eecs.umich.edu // created as the result of a normal request (in which case it 2746041Sgblack@eecs.umich.edu // should be in the outstandingReq), or if we merely forwarded 2756041Sgblack@eecs.umich.edu // someone else's snoop request 2766041Sgblack@eecs.umich.edu if (outstandingReq.find(pkt->req) == outstandingReq.end()) { 2776136Sgblack@eecs.umich.edu // this is a snoop response to a snoop request we 2786136Sgblack@eecs.umich.edu // forwarded, e.g. coming from the L1 and going to the L2 2796136Sgblack@eecs.umich.edu // this should be forwarded as a snoop response 2806136Sgblack@eecs.umich.edu bool success M5_VAR_USED = masterPorts[dest]->sendTimingSnoopResp(pkt); 2816136Sgblack@eecs.umich.edu assert(success); 2826041Sgblack@eecs.umich.edu } else { 2836136Sgblack@eecs.umich.edu // we got a snoop response on one of our slave ports, 2846136Sgblack@eecs.umich.edu // i.e. from a coherent master connected to the bus, and 2859090Sandreas.hansson@arm.com // since we created the snoop request as part of 2866041Sgblack@eecs.umich.edu // recvTiming, this should now be a normal response again 2876041Sgblack@eecs.umich.edu outstandingReq.erase(pkt->req); 2886041Sgblack@eecs.umich.edu 2896137Sgblack@eecs.umich.edu // this is a snoop response from a coherent master, with a 2906137Sgblack@eecs.umich.edu // destination field set on its way through the bus as 2916137Sgblack@eecs.umich.edu // request, hence it should never go back to where the 2927913SBrad.Beckmann@amd.com // snoop response came from, but instead to where the 2939807Sstever@gmail.com // original request came from 2949807Sstever@gmail.com assert(slave_port_id != dest); 2959807Sstever@gmail.com 2969807Sstever@gmail.com // as a normal response, it should go back to a master 2977913SBrad.Beckmann@amd.com // through one of our slave ports 2986137Sgblack@eecs.umich.edu bool success M5_VAR_USED = slavePorts[dest]->sendTimingResp(pkt); 2999807Sstever@gmail.com 3008922Swilliam.wang@arm.com // currently it is illegal to block responses... can lead 3018922Swilliam.wang@arm.com // to deadlock 3028922Swilliam.wang@arm.com assert(success); 3036137Sgblack@eecs.umich.edu } 3046137Sgblack@eecs.umich.edu 3056137Sgblack@eecs.umich.edu succeededTiming(packetFinishTime); 3065651Sgblack@eecs.umich.edu 3075651Sgblack@eecs.umich.edu return true; 3085651Sgblack@eecs.umich.edu} 3096136Sgblack@eecs.umich.edu 3105651Sgblack@eecs.umich.edu 3115651Sgblack@eecs.umich.eduvoid 3125651Sgblack@eecs.umich.eduCoherentBus::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id) 3135651Sgblack@eecs.umich.edu{ 3145654Sgblack@eecs.umich.edu for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) { 31513229Sgabeblack@google.com SlavePort *p = *s; 3165654Sgblack@eecs.umich.edu // we could have gotten this request from a snooping master 3175654Sgblack@eecs.umich.edu // (corresponding to our own slave port that is also in 3185697Snate@binkert.org // snoopPorts) and should not send it back to where it came 3195655Sgblack@eecs.umich.edu // from 3205691Sgblack@eecs.umich.edu if (exclude_slave_port_id == InvalidPortID || 3215691Sgblack@eecs.umich.edu p->getId() != exclude_slave_port_id) { 3225654Sgblack@eecs.umich.edu // cache is not allowed to refuse snoop 3235651Sgblack@eecs.umich.edu p->sendTimingSnoopReq(pkt); 3245651Sgblack@eecs.umich.edu } 3255651Sgblack@eecs.umich.edu } 3265651Sgblack@eecs.umich.edu} 3275651Sgblack@eecs.umich.edu 3285651Sgblack@eecs.umich.eduTick 3296064Sgblack@eecs.umich.eduCoherentBus::recvAtomic(PacketPtr pkt, PortID slave_port_id) 3309805Sstever@gmail.com{ 3315651Sgblack@eecs.umich.edu DPRINTF(CoherentBus, "recvAtomic: packet src %s addr 0x%x cmd %s\n", 3325651Sgblack@eecs.umich.edu slavePorts[slave_port_id]->name(), pkt->getAddr(), 3335651Sgblack@eecs.umich.edu pkt->cmdString()); 3346065Sgblack@eecs.umich.edu 3356065Sgblack@eecs.umich.edu MemCmd snoop_response_cmd = MemCmd::InvalidCmd; 3366065Sgblack@eecs.umich.edu Tick snoop_response_latency = 0; 3376065Sgblack@eecs.umich.edu 3386065Sgblack@eecs.umich.edu // uncacheable requests need never be snooped 3396069Sgblack@eecs.umich.edu if (!pkt->req->isUncacheable()) { 3406069Sgblack@eecs.umich.edu // forward to all snoopers but the source 3416069Sgblack@eecs.umich.edu std::pair<MemCmd, Tick> snoop_result = 3426069Sgblack@eecs.umich.edu forwardAtomic(pkt, slave_port_id); 3436069Sgblack@eecs.umich.edu snoop_response_cmd = snoop_result.first; 3446069Sgblack@eecs.umich.edu snoop_response_latency = snoop_result.second; 3456065Sgblack@eecs.umich.edu } 3466065Sgblack@eecs.umich.edu 3476065Sgblack@eecs.umich.edu // even if we had a snoop response, we must continue and also 3486065Sgblack@eecs.umich.edu // perform the actual request at the destination 3496065Sgblack@eecs.umich.edu PortID dest_id = findPort(pkt->getAddr()); 3508711Sandreas.hansson@arm.com 3519090Sandreas.hansson@arm.com // forward the request to the appropriate destination 3526041Sgblack@eecs.umich.edu Tick response_latency = masterPorts[dest_id]->sendAtomic(pkt); 3538711Sandreas.hansson@arm.com 3548711Sandreas.hansson@arm.com // if we got a response from a snooper, restore it here 3558711Sandreas.hansson@arm.com if (snoop_response_cmd != MemCmd::InvalidCmd) { 3568711Sandreas.hansson@arm.com // no one else should have responded 3578711Sandreas.hansson@arm.com assert(!pkt->isResponse()); 3586041Sgblack@eecs.umich.edu pkt->cmd = snoop_response_cmd; 3596041Sgblack@eecs.umich.edu response_latency = snoop_response_latency; 3606041Sgblack@eecs.umich.edu } 3615647Sgblack@eecs.umich.edu 3625648Sgblack@eecs.umich.edu pkt->finishTime = curTick() + response_latency; 3635647Sgblack@eecs.umich.edu return response_latency; 3645647Sgblack@eecs.umich.edu} 3655647Sgblack@eecs.umich.edu 3665647Sgblack@eecs.umich.eduTick 3675647Sgblack@eecs.umich.eduCoherentBus::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id) 3685647Sgblack@eecs.umich.edu{ 3695647Sgblack@eecs.umich.edu DPRINTF(CoherentBus, "recvAtomicSnoop: packet src %s addr 0x%x cmd %s\n", 3705647Sgblack@eecs.umich.edu masterPorts[master_port_id]->name(), pkt->getAddr(), 3715647Sgblack@eecs.umich.edu pkt->cmdString()); 3725647Sgblack@eecs.umich.edu 3735647Sgblack@eecs.umich.edu // forward to all snoopers 3745647Sgblack@eecs.umich.edu std::pair<MemCmd, Tick> snoop_result = 3755647Sgblack@eecs.umich.edu forwardAtomic(pkt, InvalidPortID); 3765647Sgblack@eecs.umich.edu MemCmd snoop_response_cmd = snoop_result.first; 3775647Sgblack@eecs.umich.edu Tick snoop_response_latency = snoop_result.second; 3785647Sgblack@eecs.umich.edu 3795647Sgblack@eecs.umich.edu if (snoop_response_cmd != MemCmd::InvalidCmd) 3805848Sgblack@eecs.umich.edu pkt->cmd = snoop_response_cmd; 3815848Sgblack@eecs.umich.edu 3829544Sandreas.hansson@arm.com pkt->finishTime = curTick() + snoop_response_latency; 3835848Sgblack@eecs.umich.edu return snoop_response_latency; 3845848Sgblack@eecs.umich.edu} 3857823Ssteve.reinhardt@amd.com 3865848Sgblack@eecs.umich.edustd::pair<MemCmd, Tick> 3875848Sgblack@eecs.umich.eduCoherentBus::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id) 3885848Sgblack@eecs.umich.edu{ 3895848Sgblack@eecs.umich.edu // the packet may be changed on snoops, record the original 3905848Sgblack@eecs.umich.edu // command to enable us to restore it between snoops so that 3915848Sgblack@eecs.umich.edu // additional snoops can take place properly 3925647Sgblack@eecs.umich.edu MemCmd orig_cmd = pkt->cmd; 3935647Sgblack@eecs.umich.edu MemCmd snoop_response_cmd = MemCmd::InvalidCmd; 3945647Sgblack@eecs.umich.edu Tick snoop_response_latency = 0; 3955647Sgblack@eecs.umich.edu 3965648Sgblack@eecs.umich.edu for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) { 3975647Sgblack@eecs.umich.edu SlavePort *p = *s; 3985647Sgblack@eecs.umich.edu // we could have gotten this request from a snooping master 3995647Sgblack@eecs.umich.edu // (corresponding to our own slave port that is also in 4005648Sgblack@eecs.umich.edu // snoopPorts) and should not send it back to where it came 4015647Sgblack@eecs.umich.edu // from 4025647Sgblack@eecs.umich.edu if (exclude_slave_port_id == InvalidPortID || 4035647Sgblack@eecs.umich.edu p->getId() != exclude_slave_port_id) { 4045647Sgblack@eecs.umich.edu Tick latency = p->sendAtomicSnoop(pkt); 4055647Sgblack@eecs.umich.edu // in contrast to a functional access, we have to keep on 4065647Sgblack@eecs.umich.edu // going as all snoopers must be updated even if we get a 4075647Sgblack@eecs.umich.edu // response 4085647Sgblack@eecs.umich.edu if (pkt->isResponse()) { 4095647Sgblack@eecs.umich.edu // response from snoop agent 4105647Sgblack@eecs.umich.edu assert(pkt->cmd != orig_cmd); 4115647Sgblack@eecs.umich.edu assert(pkt->memInhibitAsserted()); 4125647Sgblack@eecs.umich.edu // should only happen once 4135647Sgblack@eecs.umich.edu assert(snoop_response_cmd == MemCmd::InvalidCmd); 4145647Sgblack@eecs.umich.edu // save response state 4155647Sgblack@eecs.umich.edu snoop_response_cmd = pkt->cmd; 4165647Sgblack@eecs.umich.edu snoop_response_latency = latency; 4175647Sgblack@eecs.umich.edu // restore original packet state for remaining snoopers 4185647Sgblack@eecs.umich.edu pkt->cmd = orig_cmd; 4195647Sgblack@eecs.umich.edu } 4205647Sgblack@eecs.umich.edu } 4215647Sgblack@eecs.umich.edu } 4225647Sgblack@eecs.umich.edu 4235647Sgblack@eecs.umich.edu // the packet is restored as part of the loop and any potential 4245647Sgblack@eecs.umich.edu // snoop response is part of the returned pair 4255647Sgblack@eecs.umich.edu return std::make_pair(snoop_response_cmd, snoop_response_latency); 4265647Sgblack@eecs.umich.edu} 4275647Sgblack@eecs.umich.edu 4285647Sgblack@eecs.umich.eduvoid 4295647Sgblack@eecs.umich.eduCoherentBus::recvFunctional(PacketPtr pkt, PortID slave_port_id) 4305647Sgblack@eecs.umich.edu{ 4315647Sgblack@eecs.umich.edu if (!pkt->isPrint()) { 4325647Sgblack@eecs.umich.edu // don't do DPRINTFs on PrintReq as it clutters up the output 4335690Sgblack@eecs.umich.edu DPRINTF(CoherentBus, 4345690Sgblack@eecs.umich.edu "recvFunctional: packet src %s addr 0x%x cmd %s\n", 4355690Sgblack@eecs.umich.edu slavePorts[slave_port_id]->name(), pkt->getAddr(), 4365690Sgblack@eecs.umich.edu pkt->cmdString()); 4375647Sgblack@eecs.umich.edu } 4385647Sgblack@eecs.umich.edu 4395647Sgblack@eecs.umich.edu // uncacheable requests need never be snooped 4405647Sgblack@eecs.umich.edu if (!pkt->req->isUncacheable()) { 4415647Sgblack@eecs.umich.edu // forward to all snoopers but the source 4425647Sgblack@eecs.umich.edu forwardFunctional(pkt, slave_port_id); 4435647Sgblack@eecs.umich.edu } 4445647Sgblack@eecs.umich.edu 4455647Sgblack@eecs.umich.edu // there is no need to continue if the snooping has found what we 4465647Sgblack@eecs.umich.edu // were looking for and the packet is already a response 4475647Sgblack@eecs.umich.edu if (!pkt->isResponse()) { 4485647Sgblack@eecs.umich.edu PortID dest_id = findPort(pkt->getAddr()); 4495647Sgblack@eecs.umich.edu 4505647Sgblack@eecs.umich.edu masterPorts[dest_id]->sendFunctional(pkt); 4515647Sgblack@eecs.umich.edu } 4525647Sgblack@eecs.umich.edu} 4535647Sgblack@eecs.umich.edu 4545647Sgblack@eecs.umich.eduvoid 4555647Sgblack@eecs.umich.eduCoherentBus::recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id) 4565647Sgblack@eecs.umich.edu{ 4575647Sgblack@eecs.umich.edu if (!pkt->isPrint()) { 4585647Sgblack@eecs.umich.edu // don't do DPRINTFs on PrintReq as it clutters up the output 4595647Sgblack@eecs.umich.edu DPRINTF(CoherentBus, 4605647Sgblack@eecs.umich.edu "recvFunctionalSnoop: packet src %s addr 0x%x cmd %s\n", 4615647Sgblack@eecs.umich.edu masterPorts[master_port_id]->name(), pkt->getAddr(), 4626046Sgblack@eecs.umich.edu pkt->cmdString()); 4636046Sgblack@eecs.umich.edu } 4646046Sgblack@eecs.umich.edu 4656046Sgblack@eecs.umich.edu // forward to all snoopers 4666046Sgblack@eecs.umich.edu forwardFunctional(pkt, InvalidPortID); 4676046Sgblack@eecs.umich.edu} 4686046Sgblack@eecs.umich.edu 4696046Sgblack@eecs.umich.eduvoid 4706046Sgblack@eecs.umich.eduCoherentBus::forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id) 4716712Snate@binkert.org{ 4726046Sgblack@eecs.umich.edu for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) { 4736046Sgblack@eecs.umich.edu SlavePort *p = *s; 4746046Sgblack@eecs.umich.edu // we could have gotten this request from a snooping master 4756046Sgblack@eecs.umich.edu // (corresponding to our own slave port that is also in 4766046Sgblack@eecs.umich.edu // snoopPorts) and should not send it back to where it came 4776046Sgblack@eecs.umich.edu // from 4786138Sgblack@eecs.umich.edu if (exclude_slave_port_id == InvalidPortID || 4796138Sgblack@eecs.umich.edu p->getId() != exclude_slave_port_id) 4806046Sgblack@eecs.umich.edu p->sendFunctionalSnoop(pkt); 4816046Sgblack@eecs.umich.edu 4826138Sgblack@eecs.umich.edu // if we get a response we are done 4836138Sgblack@eecs.umich.edu if (pkt->isResponse()) { 4846138Sgblack@eecs.umich.edu break; 4856138Sgblack@eecs.umich.edu } 4866138Sgblack@eecs.umich.edu } 4876138Sgblack@eecs.umich.edu} 4886138Sgblack@eecs.umich.edu 4896138Sgblack@eecs.umich.eduCoherentBus * 4906138Sgblack@eecs.umich.eduCoherentBusParams::create() 4916138Sgblack@eecs.umich.edu{ 4926138Sgblack@eecs.umich.edu return new CoherentBus(this); 4936138Sgblack@eecs.umich.edu} 4946138Sgblack@eecs.umich.edu