coherent_xbar.hh revision 10402
14826Ssaidi@eecs.umich.edu/* 24826Ssaidi@eecs.umich.edu * Copyright (c) 2011-2013 ARM Limited 34826Ssaidi@eecs.umich.edu * All rights reserved 44826Ssaidi@eecs.umich.edu * 54826Ssaidi@eecs.umich.edu * The license below extends only to copyright in the software and shall 64826Ssaidi@eecs.umich.edu * not be construed as granting a license to any other intellectual 74826Ssaidi@eecs.umich.edu * property including but not limited to intellectual property relating 84826Ssaidi@eecs.umich.edu * to a hardware implementation of the functionality of the software 94826Ssaidi@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 104826Ssaidi@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 114826Ssaidi@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 124826Ssaidi@eecs.umich.edu * modified or unmodified, in source code or in binary form. 134826Ssaidi@eecs.umich.edu * 144826Ssaidi@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 154826Ssaidi@eecs.umich.edu * All rights reserved. 164826Ssaidi@eecs.umich.edu * 174826Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 184826Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 194826Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 204826Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 214826Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 224826Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 234826Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 244826Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 254826Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 264826Ssaidi@eecs.umich.edu * this software without specific prior written permission. 274826Ssaidi@eecs.umich.edu * 284826Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 294826Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 304826Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 314826Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 324826Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 334826Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 344826Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 354826Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 364826Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 374826Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 384826Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 394826Ssaidi@eecs.umich.edu * 404826Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 414826Ssaidi@eecs.umich.edu * Ali Saidi 424826Ssaidi@eecs.umich.edu * Andreas Hansson 434826Ssaidi@eecs.umich.edu * William Wang 444826Ssaidi@eecs.umich.edu */ 454826Ssaidi@eecs.umich.edu 464826Ssaidi@eecs.umich.edu/** 474826Ssaidi@eecs.umich.edu * @file 484826Ssaidi@eecs.umich.edu * Declaration of a coherent bus. 494826Ssaidi@eecs.umich.edu */ 504826Ssaidi@eecs.umich.edu 514826Ssaidi@eecs.umich.edu#ifndef __MEM_COHERENT_BUS_HH__ 524826Ssaidi@eecs.umich.edu#define __MEM_COHERENT_BUS_HH__ 534826Ssaidi@eecs.umich.edu 544826Ssaidi@eecs.umich.edu#include "base/hashmap.hh" 554826Ssaidi@eecs.umich.edu#include "mem/bus.hh" 564826Ssaidi@eecs.umich.edu#include "mem/snoop_filter.hh" 574826Ssaidi@eecs.umich.edu#include "params/CoherentBus.hh" 584826Ssaidi@eecs.umich.edu 594826Ssaidi@eecs.umich.edu/** 604826Ssaidi@eecs.umich.edu * A coherent bus connects a number of (potentially) snooping masters 614826Ssaidi@eecs.umich.edu * and slaves, and routes the request and response packets based on 624826Ssaidi@eecs.umich.edu * the address, and also forwards all requests to the snoopers and 634826Ssaidi@eecs.umich.edu * deals with the snoop responses. 644826Ssaidi@eecs.umich.edu * 65 * The coherent bus can be used as a template for modelling QPI, 66* HyperTransport, ACE and coherent OCP buses, and is typically used 67 * for the L1-to-L2 buses and as the main system interconnect. 68 * @sa \ref gem5MemorySystem "gem5 Memory System" 69 */ 70class CoherentBus : public BaseBus 71{ 72 73 protected: 74 75 /** 76 * Declare the layers of this bus, one vector for requests, one 77 * for responses, and one for snoop responses 78 */ 79 typedef Layer<SlavePort,MasterPort> ReqLayer; 80 typedef Layer<MasterPort,SlavePort> RespLayer; 81 typedef Layer<SlavePort,MasterPort> SnoopLayer; 82 std::vector<ReqLayer*> reqLayers; 83 std::vector<RespLayer*> respLayers; 84 std::vector<SnoopLayer*> snoopLayers; 85 86 /** 87 * Declaration of the coherent bus slave port type, one will be 88 * instantiated for each of the master ports connecting to the 89 * bus. 90 */ 91 class CoherentBusSlavePort : public SlavePort 92 { 93 94 private: 95 96 /** A reference to the bus to which this port belongs. */ 97 CoherentBus &bus; 98 99 public: 100 101 CoherentBusSlavePort(const std::string &_name, 102 CoherentBus &_bus, PortID _id) 103 : SlavePort(_name, &_bus, _id), bus(_bus) 104 { } 105 106 protected: 107 108 /** 109 * When receiving a timing request, pass it to the bus. 110 */ 111 virtual bool recvTimingReq(PacketPtr pkt) 112 { return bus.recvTimingReq(pkt, id); } 113 114 /** 115 * When receiving a timing snoop response, pass it to the bus. 116 */ 117 virtual bool recvTimingSnoopResp(PacketPtr pkt) 118 { return bus.recvTimingSnoopResp(pkt, id); } 119 120 /** 121 * When receiving an atomic request, pass it to the bus. 122 */ 123 virtual Tick recvAtomic(PacketPtr pkt) 124 { return bus.recvAtomic(pkt, id); } 125 126 /** 127 * When receiving a functional request, pass it to the bus. 128 */ 129 virtual void recvFunctional(PacketPtr pkt) 130 { bus.recvFunctional(pkt, id); } 131 132 /** 133 * When receiving a retry, pass it to the bus. 134 */ 135 virtual void recvRetry() 136 { panic("Bus slave ports always succeed and should never retry.\n"); } 137 138 /** 139 * Return the union of all adress ranges seen by this bus. 140 */ 141 virtual AddrRangeList getAddrRanges() const 142 { return bus.getAddrRanges(); } 143 144 }; 145 146 /** 147 * Declaration of the coherent bus master port type, one will be 148 * instantiated for each of the slave interfaces connecting to the 149 * bus. 150 */ 151 class CoherentBusMasterPort : public MasterPort 152 { 153 private: 154 /** A reference to the bus to which this port belongs. */ 155 CoherentBus &bus; 156 157 public: 158 159 CoherentBusMasterPort(const std::string &_name, 160 CoherentBus &_bus, PortID _id) 161 : MasterPort(_name, &_bus, _id), bus(_bus) 162 { } 163 164 protected: 165 166 /** 167 * Determine if this port should be considered a snooper. For 168 * a coherent bus master port this is always true. 169 * 170 * @return a boolean that is true if this port is snooping 171 */ 172 virtual bool isSnooping() const 173 { return true; } 174 175 /** 176 * When receiving a timing response, pass it to the bus. 177 */ 178 virtual bool recvTimingResp(PacketPtr pkt) 179 { return bus.recvTimingResp(pkt, id); } 180 181 /** 182 * When receiving a timing snoop request, pass it to the bus. 183 */ 184 virtual void recvTimingSnoopReq(PacketPtr pkt) 185 { return bus.recvTimingSnoopReq(pkt, id); } 186 187 /** 188 * When receiving an atomic snoop request, pass it to the bus. 189 */ 190 virtual Tick recvAtomicSnoop(PacketPtr pkt) 191 { return bus.recvAtomicSnoop(pkt, id); } 192 193 /** 194 * When receiving a functional snoop request, pass it to the bus. 195 */ 196 virtual void recvFunctionalSnoop(PacketPtr pkt) 197 { bus.recvFunctionalSnoop(pkt, id); } 198 199 /** When reciving a range change from the peer port (at id), 200 pass it to the bus. */ 201 virtual void recvRangeChange() 202 { bus.recvRangeChange(id); } 203 204 /** When reciving a retry from the peer port (at id), 205 pass it to the bus. */ 206 virtual void recvRetry() 207 { bus.recvRetry(id); } 208 209 }; 210 211 /** 212 * Internal class to bridge between an incoming snoop response 213 * from a slave port and forwarding it through an outgoing slave 214 * port. It is effectively a dangling master port. 215 */ 216 class SnoopRespPort : public MasterPort 217 { 218 219 private: 220 221 /** The port which we mirror internally. */ 222 SlavePort& slavePort; 223 224 public: 225 226 /** 227 * Create a snoop response port that mirrors a given slave port. 228 */ 229 SnoopRespPort(SlavePort& slave_port, CoherentBus& _bus) : 230 MasterPort(slave_port.name() + ".snoopRespPort", &_bus), 231 slavePort(slave_port) { } 232 233 /** 234 * Override the sending of retries and pass them on through 235 * the mirrored slave port. 236 */ 237 void sendRetry() { 238 slavePort.sendRetry(); 239 } 240 241 /** 242 * Provided as necessary. 243 */ 244 void recvRetry() { panic("SnoopRespPort should never see retry\n"); } 245 246 /** 247 * Provided as necessary. 248 */ 249 bool recvTimingResp(PacketPtr pkt) 250 { 251 panic("SnoopRespPort should never see timing response\n"); 252 return false; 253 } 254 255 }; 256 257 std::vector<SnoopRespPort*> snoopRespPorts; 258 259 std::vector<SlavePort*> snoopPorts; 260 261 /** 262 * Store the outstanding requests so we can determine which ones 263 * we generated and which ones were merely forwarded. This is used 264 * in the coherent bus when coherency responses come back. 265 */ 266 m5::hash_set<RequestPtr> outstandingReq; 267 268 /** 269 * Keep a pointer to the system to be allow to querying memory system 270 * properties. 271 */ 272 System *system; 273 274 /** A snoop filter that tracks cache line residency and can restrict the 275 * broadcast needed for probes. NULL denotes an absent filter. */ 276 SnoopFilter *snoopFilter; 277 278 /** Function called by the port when the bus is recieving a Timing 279 request packet.*/ 280 bool recvTimingReq(PacketPtr pkt, PortID slave_port_id); 281 282 /** Function called by the port when the bus is recieving a Timing 283 response packet.*/ 284 bool recvTimingResp(PacketPtr pkt, PortID master_port_id); 285 286 /** Function called by the port when the bus is recieving a timing 287 snoop request.*/ 288 void recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id); 289 290 /** Function called by the port when the bus is recieving a timing 291 snoop response.*/ 292 bool recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id); 293 294 /** Timing function called by port when it is once again able to process 295 * requests. */ 296 void recvRetry(PortID master_port_id); 297 298 /** 299 * Forward a timing packet to our snoopers, potentially excluding 300 * one of the connected coherent masters to avoid sending a packet 301 * back to where it came from. 302 * 303 * @param pkt Packet to forward 304 * @param exclude_slave_port_id Id of slave port to exclude 305 */ 306 void forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id) { 307 forwardTiming(pkt, exclude_slave_port_id, snoopPorts); 308 } 309 310 /** 311 * Forward a timing packet to a selected list of snoopers, potentially 312 * excluding one of the connected coherent masters to avoid sending a packet 313 * back to where it came from. 314 * 315 * @param pkt Packet to forward 316 * @param exclude_slave_port_id Id of slave port to exclude 317 * @param dests Vector of destination ports for the forwarded pkt 318 */ 319 void forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id, 320 const std::vector<SlavePort*>& dests); 321 322 /** Function called by the port when the bus is recieving a Atomic 323 transaction.*/ 324 Tick recvAtomic(PacketPtr pkt, PortID slave_port_id); 325 326 /** Function called by the port when the bus is recieving an 327 atomic snoop transaction.*/ 328 Tick recvAtomicSnoop(PacketPtr pkt, PortID master_port_id); 329 330 /** 331 * Forward an atomic packet to our snoopers, potentially excluding 332 * one of the connected coherent masters to avoid sending a packet 333 * back to where it came from. 334 * 335 * @param pkt Packet to forward 336 * @param exclude_slave_port_id Id of slave port to exclude 337 * 338 * @return a pair containing the snoop response and snoop latency 339 */ 340 std::pair<MemCmd, Tick> forwardAtomic(PacketPtr pkt, 341 PortID exclude_slave_port_id) 342 { 343 return forwardAtomic(pkt, exclude_slave_port_id, InvalidPortID, snoopPorts); 344 } 345 346 /** 347 * Forward an atomic packet to a selected list of snoopers, potentially 348 * excluding one of the connected coherent masters to avoid sending a packet 349 * back to where it came from. 350 * 351 * @param pkt Packet to forward 352 * @param exclude_slave_port_id Id of slave port to exclude 353 * @param source_master_port_id Id of the master port for snoops from below 354 * @param dests Vector of destination ports for the forwarded pkt 355 * 356 * @return a pair containing the snoop response and snoop latency 357 */ 358 std::pair<MemCmd, Tick> forwardAtomic(PacketPtr pkt, 359 PortID exclude_slave_port_id, 360 PortID source_master_port_id, 361 const std::vector<SlavePort*>& dests); 362 363 /** Function called by the port when the bus is recieving a Functional 364 transaction.*/ 365 void recvFunctional(PacketPtr pkt, PortID slave_port_id); 366 367 /** Function called by the port when the bus is recieving a functional 368 snoop transaction.*/ 369 void recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id); 370 371 /** 372 * Forward a functional packet to our snoopers, potentially 373 * excluding one of the connected coherent masters to avoid 374 * sending a packet back to where it came from. 375 * 376 * @param pkt Packet to forward 377 * @param exclude_slave_port_id Id of slave port to exclude 378 */ 379 void forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id); 380 381 Stats::Scalar dataThroughBus; 382 Stats::Scalar snoopDataThroughBus; 383 Stats::Scalar snoopsThroughBus; 384 Stats::Distribution snoopFanout; 385 386 public: 387 388 virtual void init(); 389 390 CoherentBus(const CoherentBusParams *p); 391 392 virtual ~CoherentBus(); 393 394 unsigned int drain(DrainManager *dm); 395 396 virtual void regStats(); 397}; 398 399#endif //__MEM_COHERENT_BUS_HH__ 400