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