noncoherent_xbar.cc revision 9092
1/* 2 * Copyright (c) 2011-2012 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2006 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Ali Saidi 41 * Andreas Hansson 42 * William Wang 43 */ 44 45/** 46 * @file 47 * Definition of a bus object. 48 */ 49 50#include "base/misc.hh" 51#include "base/trace.hh" 52#include "debug/Bus.hh" 53#include "debug/BusAddrRanges.hh" 54#include "debug/NoncoherentBus.hh" 55#include "mem/noncoherent_bus.hh" 56 57NoncoherentBus::NoncoherentBus(const NoncoherentBusParams *p) 58 : BaseBus(p), layer(*this, ".layer", p->clock) 59{ 60 // create the ports based on the size of the master and slave 61 // vector ports, and the presence of the default port, the ports 62 // are enumerated starting from zero 63 for (int i = 0; i < p->port_master_connection_count; ++i) { 64 std::string portName = csprintf("%s-p%d", name(), i); 65 MasterPort* bp = new NoncoherentBusMasterPort(portName, *this, i); 66 masterPorts.push_back(bp); 67 } 68 69 // see if we have a default slave device connected and if so add 70 // our corresponding master port 71 if (p->port_default_connection_count) { 72 defaultPortID = masterPorts.size(); 73 std::string portName = csprintf("%s-default", name()); 74 MasterPort* bp = new NoncoherentBusMasterPort(portName, *this, 75 defaultPortID); 76 masterPorts.push_back(bp); 77 } 78 79 // create the slave ports, once again starting at zero 80 for (int i = 0; i < p->port_slave_connection_count; ++i) { 81 std::string portName = csprintf("%s-p%d", name(), i); 82 SlavePort* bp = new NoncoherentBusSlavePort(portName, *this, i); 83 slavePorts.push_back(bp); 84 } 85 86 clearPortCache(); 87} 88 89bool 90NoncoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id) 91{ 92 // determine the source port based on the id 93 SlavePort *src_port = slavePorts[slave_port_id]; 94 95 // we should never see express snoops on a non-coherent bus 96 assert(!pkt->isExpressSnoop()); 97 98 // test if the bus should be considered occupied for the current 99 // port 100 if (!layer.tryTiming(src_port)) { 101 DPRINTF(NoncoherentBus, "recvTimingReq: src %s %s 0x%x BUSY\n", 102 src_port->name(), pkt->cmdString(), pkt->getAddr()); 103 return false; 104 } 105 106 DPRINTF(NoncoherentBus, "recvTimingReq: src %s %s 0x%x\n", 107 src_port->name(), pkt->cmdString(), pkt->getAddr()); 108 109 // set the source port for routing of the response 110 pkt->setSrc(slave_port_id); 111 112 Tick headerFinishTime = calcPacketTiming(pkt); 113 Tick packetFinishTime = pkt->finishTime; 114 115 // since it is a normal request, determine the destination 116 // based on the address and attempt to send the packet 117 bool success = masterPorts[findPort(pkt->getAddr())]->sendTimingReq(pkt); 118 119 if (!success) { 120 // inhibited packets should never be forced to retry 121 assert(!pkt->memInhibitAsserted()); 122 123 DPRINTF(NoncoherentBus, "recvTimingReq: src %s %s 0x%x RETRY\n", 124 src_port->name(), pkt->cmdString(), pkt->getAddr()); 125 126 layer.failedTiming(src_port, headerFinishTime); 127 128 return false; 129 } 130 131 layer.succeededTiming(packetFinishTime); 132 133 return true; 134} 135 136bool 137NoncoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id) 138{ 139 // determine the source port based on the id 140 MasterPort *src_port = masterPorts[master_port_id]; 141 142 // test if the bus should be considered occupied for the current 143 // port 144 if (!layer.tryTiming(src_port)) { 145 DPRINTF(NoncoherentBus, "recvTimingResp: src %s %s 0x%x BUSY\n", 146 src_port->name(), pkt->cmdString(), pkt->getAddr()); 147 return false; 148 } 149 150 DPRINTF(NoncoherentBus, "recvTimingResp: src %s %s 0x%x\n", 151 src_port->name(), pkt->cmdString(), pkt->getAddr()); 152 153 calcPacketTiming(pkt); 154 Tick packetFinishTime = pkt->finishTime; 155 156 // send the packet to the destination through one of our slave 157 // ports, as determined by the destination field 158 bool success M5_VAR_USED = slavePorts[pkt->getDest()]->sendTimingResp(pkt); 159 160 // currently it is illegal to block responses... can lead to 161 // deadlock 162 assert(success); 163 164 layer.succeededTiming(packetFinishTime); 165 166 return true; 167} 168 169void 170NoncoherentBus::recvRetry() 171{ 172 // only one layer that can deal with it 173 layer.recvRetry(); 174} 175 176Tick 177NoncoherentBus::recvAtomic(PacketPtr pkt, PortID slave_port_id) 178{ 179 DPRINTF(NoncoherentBus, "recvAtomic: packet src %s addr 0x%x cmd %s\n", 180 slavePorts[slave_port_id]->name(), pkt->getAddr(), 181 pkt->cmdString()); 182 183 // determine the destination port 184 PortID dest_id = findPort(pkt->getAddr()); 185 186 // forward the request to the appropriate destination 187 Tick response_latency = masterPorts[dest_id]->sendAtomic(pkt); 188 189 pkt->finishTime = curTick() + response_latency; 190 return response_latency; 191} 192 193void 194NoncoherentBus::recvFunctional(PacketPtr pkt, PortID slave_port_id) 195{ 196 if (!pkt->isPrint()) { 197 // don't do DPRINTFs on PrintReq as it clutters up the output 198 DPRINTF(NoncoherentBus, 199 "recvFunctional: packet src %s addr 0x%x cmd %s\n", 200 slavePorts[slave_port_id]->name(), pkt->getAddr(), 201 pkt->cmdString()); 202 } 203 204 // determine the destination port 205 PortID dest_id = findPort(pkt->getAddr()); 206 207 // forward the request to the appropriate destination 208 masterPorts[dest_id]->sendFunctional(pkt); 209} 210 211unsigned int 212NoncoherentBus::drain(Event *de) 213{ 214 // only one layer to worry about at the moment 215 return layer.drain(de); 216} 217 218NoncoherentBus* 219NoncoherentBusParams::create() 220{ 221 return new NoncoherentBus(this); 222} 223