coherent_xbar.hh revision 8922
1545SN/A/* 22512SN/A * Copyright (c) 2011 ARM Limited 3545SN/A * All rights reserved 4545SN/A * 5545SN/A * The license below extends only to copyright in the software and shall 6545SN/A * not be construed as granting a license to any other intellectual 7545SN/A * property including but not limited to intellectual property relating 8545SN/A * to a hardware implementation of the functionality of the software 9545SN/A * licensed hereunder. You may use the software subject to the license 10545SN/A * terms below provided that you ensure that this notice is replicated 11545SN/A * unmodified and in its entirety in all distributions of the software, 12545SN/A * modified or unmodified, in source code or in binary form. 13545SN/A * 14545SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 15545SN/A * All rights reserved. 16545SN/A * 17545SN/A * Redistribution and use in source and binary forms, with or without 18545SN/A * modification, are permitted provided that the following conditions are 19545SN/A * met: redistributions of source code must retain the above copyright 20545SN/A * notice, this list of conditions and the following disclaimer; 21545SN/A * redistributions in binary form must reproduce the above copyright 22545SN/A * notice, this list of conditions and the following disclaimer in the 23545SN/A * documentation and/or other materials provided with the distribution; 24545SN/A * neither the name of the copyright holders nor the names of its 25545SN/A * contributors may be used to endorse or promote products derived from 26545SN/A * this software without specific prior written permission. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292665Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30545SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31545SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323090Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332657Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34545SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35679SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362901Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37545SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382489SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392901Ssaidi@eecs.umich.edu * 403091Sstever@eecs.umich.edu * Authors: Ron Dreslinski 412489SN/A * Ali Saidi 422489SN/A * Andreas Hansson 432489SN/A * William Wang 442489SN/A */ 453349Sbinkertn@umich.edu 462489SN/A/** 473091Sstever@eecs.umich.edu * @file 482489SN/A * Declaration of a bus object. 492489SN/A */ 502489SN/A 512521SN/A#ifndef __MEM_BUS_HH__ 522489SN/A#define __MEM_BUS_HH__ 532521SN/A 542521SN/A#include <list> 552489SN/A#include <set> 562489SN/A#include <string> 572489SN/A 58545SN/A#include "base/range.hh" 59545SN/A#include "base/range_map.hh" 602384SN/A#include "base/types.hh" 612489SN/A#include "mem/mem_object.hh" 62545SN/A#include "mem/packet.hh" 63545SN/A#include "mem/port.hh" 642542SN/A#include "params/Bus.hh" 652541SN/A#include "sim/eventq.hh" 662541SN/A 672541SN/Aclass Bus : public MemObject 682541SN/A{ 692541SN/A /** 702541SN/A * Declaration of the bus slave port type, one will be 712541SN/A * instantiated for each of the master interfaces connecting to 722901Ssaidi@eecs.umich.edu * the bus. 732901Ssaidi@eecs.umich.edu */ 742901Ssaidi@eecs.umich.edu class BusSlavePort : public SlavePort 752901Ssaidi@eecs.umich.edu { 762901Ssaidi@eecs.umich.edu private: 772901Ssaidi@eecs.umich.edu /** A pointer to the bus to which this port belongs. */ 782901Ssaidi@eecs.umich.edu Bus *bus; 792901Ssaidi@eecs.umich.edu 802901Ssaidi@eecs.umich.edu /** A id to keep track of the interface ID of this port. */ 812901Ssaidi@eecs.umich.edu int id; 822901Ssaidi@eecs.umich.edu 832901Ssaidi@eecs.umich.edu public: 842901Ssaidi@eecs.umich.edu 852539SN/A /** Constructor for the BusSlavePort.*/ 862539SN/A BusSlavePort(const std::string &_name, Bus *_bus, int _id) 872539SN/A : SlavePort(_name, _bus), bus(_bus), id(_id) 882539SN/A { } 892539SN/A 902539SN/A int getId() const { return id; } 912539SN/A 922539SN/A protected: 932489SN/A 942901Ssaidi@eecs.umich.edu /** When reciving a timing request from the peer port (at id), 952901Ssaidi@eecs.umich.edu pass it to the bus. */ 962901Ssaidi@eecs.umich.edu virtual bool recvTiming(PacketPtr pkt) 972489SN/A { pkt->setSrc(id); return bus->recvTiming(pkt); } 982489SN/A 992489SN/A /** When reciving a Atomic requestfrom the peer port (at id), 1003349Sbinkertn@umich.edu pass it to the bus. */ 1012384SN/A virtual Tick recvAtomic(PacketPtr pkt) 1022685Ssaidi@eecs.umich.edu { pkt->setSrc(id); return bus->recvAtomic(pkt); } 1032685Ssaidi@eecs.umich.edu 1042685Ssaidi@eecs.umich.edu /** When reciving a Functional requestfrom the peer port (at id), 1052685Ssaidi@eecs.umich.edu pass it to the bus. */ 1062685Ssaidi@eecs.umich.edu virtual void recvFunctional(PacketPtr pkt) 1072685Ssaidi@eecs.umich.edu { pkt->setSrc(id); bus->recvFunctional(pkt); } 1082685Ssaidi@eecs.umich.edu 1092685Ssaidi@eecs.umich.edu /** When reciving a retry from the peer port (at id), 1102565SN/A pass it to the bus. */ 1112685Ssaidi@eecs.umich.edu virtual void recvRetry() 1122685Ssaidi@eecs.umich.edu { bus->recvRetry(id); } 1132641Sstever@eecs.umich.edu 1142685Ssaidi@eecs.umich.edu // This should return all the 'owned' addresses that are 1152685Ssaidi@eecs.umich.edu // downstream from this bus, yes? That is, the union of all 1162685Ssaidi@eecs.umich.edu // the 'owned' address ranges of all the other interfaces on 1172657Ssaidi@eecs.umich.edu // this bus... 1182685Ssaidi@eecs.umich.edu virtual AddrRangeList getAddrRanges() 1192685Ssaidi@eecs.umich.edu { return bus->getAddrRanges(id); } 1202685Ssaidi@eecs.umich.edu 1212685Ssaidi@eecs.umich.edu // Ask the bus to ask everyone on the bus what their block size is and 1222685Ssaidi@eecs.umich.edu // take the max of it. This might need to be changed a bit if we ever 1232685Ssaidi@eecs.umich.edu // support multiple block sizes. 1242630SN/A virtual unsigned deviceBlockSize() const 1252630SN/A { return bus->findBlockSize(id); } 1262901Ssaidi@eecs.umich.edu 1272901Ssaidi@eecs.umich.edu }; 1282901Ssaidi@eecs.umich.edu 1292901Ssaidi@eecs.umich.edu /** 1302901Ssaidi@eecs.umich.edu * Declaration of the bus master port type, one will be 1312569SN/A * instantiated for each of the slave interfaces connecting to the 1322685Ssaidi@eecs.umich.edu * bus. 1332565SN/A */ 1342569SN/A class BusMasterPort : public MasterPort 1352657Ssaidi@eecs.umich.edu { 1362384SN/A private: 137679SN/A /** A pointer to the bus to which this port belongs. */ 1382521SN/A Bus *bus; 1392565SN/A 1402565SN/A /** A id to keep track of the interface ID of this port. */ 1412384SN/A int id; 1422901Ssaidi@eecs.umich.edu 1432901Ssaidi@eecs.umich.edu public: 1442901Ssaidi@eecs.umich.edu 1452901Ssaidi@eecs.umich.edu /** Constructor for the BusMasterPort.*/ 1462901Ssaidi@eecs.umich.edu BusMasterPort(const std::string &_name, Bus *_bus, int _id) 1472901Ssaidi@eecs.umich.edu : MasterPort(_name, _bus), bus(_bus), id(_id) 1482901Ssaidi@eecs.umich.edu { } 1492901Ssaidi@eecs.umich.edu 1502901Ssaidi@eecs.umich.edu int getId() const { return id; } 1512901Ssaidi@eecs.umich.edu 1522901Ssaidi@eecs.umich.edu /** 1532901Ssaidi@eecs.umich.edu * Determine if this port should be considered a snooper. This 1542901Ssaidi@eecs.umich.edu * is determined by the bus. 1552901Ssaidi@eecs.umich.edu * 1562901Ssaidi@eecs.umich.edu * @return a boolean that is true if this port is snooping 1572901Ssaidi@eecs.umich.edu */ 1582901Ssaidi@eecs.umich.edu virtual bool isSnooping() const 1592901Ssaidi@eecs.umich.edu { return bus->isSnooping(id); } 1602901Ssaidi@eecs.umich.edu 1612901Ssaidi@eecs.umich.edu protected: 1622901Ssaidi@eecs.umich.edu 1632901Ssaidi@eecs.umich.edu /** When reciving a timing request from the peer port (at id), 1642901Ssaidi@eecs.umich.edu pass it to the bus. */ 1652384SN/A virtual bool recvTiming(PacketPtr pkt) 1662489SN/A { pkt->setSrc(id); return bus->recvTiming(pkt); } 1672489SN/A 1683349Sbinkertn@umich.edu /** When reciving a Atomic requestfrom the peer port (at id), 1692659Ssaidi@eecs.umich.edu pass it to the bus. */ 1702659Ssaidi@eecs.umich.edu virtual Tick recvAtomic(PacketPtr pkt) 1712659Ssaidi@eecs.umich.edu { pkt->setSrc(id); return bus->recvAtomic(pkt); } 1722659Ssaidi@eecs.umich.edu 1732659Ssaidi@eecs.umich.edu /** When reciving a Functional requestfrom the peer port (at id), 1742659Ssaidi@eecs.umich.edu pass it to the bus. */ 1752659Ssaidi@eecs.umich.edu virtual void recvFunctional(PacketPtr pkt) 1762659Ssaidi@eecs.umich.edu { pkt->setSrc(id); bus->recvFunctional(pkt); } 1772659Ssaidi@eecs.umich.edu 1782659Ssaidi@eecs.umich.edu /** When reciving a range change from the peer port (at id), 1792659Ssaidi@eecs.umich.edu pass it to the bus. */ 1802657Ssaidi@eecs.umich.edu virtual void recvRangeChange() 1812489SN/A { bus->recvRangeChange(id); } 1822641Sstever@eecs.umich.edu 1832641Sstever@eecs.umich.edu /** When reciving a retry from the peer port (at id), 1842489SN/A pass it to the bus. */ 1852641Sstever@eecs.umich.edu virtual void recvRetry() 1862641Sstever@eecs.umich.edu { bus->recvRetry(id); } 1872384SN/A 1882384SN/A // Ask the bus to ask everyone on the bus what their block size is and 1892384SN/A // take the max of it. This might need to be changed a bit if we ever 1902901Ssaidi@eecs.umich.edu // support multiple block sizes. 1912901Ssaidi@eecs.umich.edu virtual unsigned deviceBlockSize() const 1922685Ssaidi@eecs.umich.edu { return bus->findBlockSize(id); } 1932384SN/A 1942406SN/A }; 1952406SN/A 1962663Sstever@eecs.umich.edu /** the clock speed for the bus */ 1973349Sbinkertn@umich.edu int clock; 1982641Sstever@eecs.umich.edu /** cycles of overhead per transaction */ 1992384SN/A int headerCycles; 2002566SN/A /** the width of the bus in bytes */ 2012685Ssaidi@eecs.umich.edu int width; 2022641Sstever@eecs.umich.edu /** the next tick at which the bus will be idle */ 2032685Ssaidi@eecs.umich.edu Tick tickNextIdle; 2042641Sstever@eecs.umich.edu 2052565SN/A Event * drainEvent; 2062565SN/A 2072566SN/A typedef range_map<Addr,int>::iterator PortIter; 2082384SN/A range_map<Addr, int> portMap; 2092901Ssaidi@eecs.umich.edu 2102384SN/A AddrRangeList defaultRange; 2112384SN/A 2122384SN/A typedef std::vector<BusSlavePort*>::iterator SnoopIter; 2132384SN/A std::vector<BusSlavePort*> snoopPorts; 2143349Sbinkertn@umich.edu 2152384SN/A /** Function called by the port when the bus is recieving a Timing 2162901Ssaidi@eecs.umich.edu transaction.*/ 2172901Ssaidi@eecs.umich.edu bool recvTiming(PacketPtr pkt); 2182901Ssaidi@eecs.umich.edu 2192902Ssaidi@eecs.umich.edu /** Function called by the port when the bus is recieving a Atomic 2202901Ssaidi@eecs.umich.edu transaction.*/ 2212901Ssaidi@eecs.umich.edu Tick recvAtomic(PacketPtr pkt); 2222901Ssaidi@eecs.umich.edu 2232901Ssaidi@eecs.umich.edu /** Function called by the port when the bus is recieving a Functional 2242901Ssaidi@eecs.umich.edu transaction.*/ 2252901Ssaidi@eecs.umich.edu void recvFunctional(PacketPtr pkt); 2262901Ssaidi@eecs.umich.edu 2272901Ssaidi@eecs.umich.edu /** Timing function called by port when it is once again able to process 2282901Ssaidi@eecs.umich.edu * requests. */ 2292901Ssaidi@eecs.umich.edu void recvRetry(int id); 2302901Ssaidi@eecs.umich.edu 2312901Ssaidi@eecs.umich.edu /** Function called by the port when the bus is recieving a range change.*/ 2322901Ssaidi@eecs.umich.edu void recvRangeChange(int id); 2332901Ssaidi@eecs.umich.edu 2342902Ssaidi@eecs.umich.edu /** Find which port connected to this bus (if any) should be given a packet 2352902Ssaidi@eecs.umich.edu * with this address. 2362901Ssaidi@eecs.umich.edu * @param addr Address to find port for. 2372901Ssaidi@eecs.umich.edu * @return id of port that the packet should be sent out of. 2382901Ssaidi@eecs.umich.edu */ 2392384SN/A int findPort(Addr addr); 2402901Ssaidi@eecs.umich.edu 2412901Ssaidi@eecs.umich.edu // Cache for the findPort function storing recently used ports from portMap 2422902Ssaidi@eecs.umich.edu struct PortCache { 2432901Ssaidi@eecs.umich.edu bool valid; 2442901Ssaidi@eecs.umich.edu int id; 2452901Ssaidi@eecs.umich.edu Addr start; 2462901Ssaidi@eecs.umich.edu Addr end; 2472901Ssaidi@eecs.umich.edu }; 2482901Ssaidi@eecs.umich.edu 2492566SN/A PortCache portCache[3]; 2502901Ssaidi@eecs.umich.edu 2512901Ssaidi@eecs.umich.edu // Checks the cache and returns the id of the port that has the requested 2522901Ssaidi@eecs.umich.edu // address within its range 2532901Ssaidi@eecs.umich.edu inline int checkPortCache(Addr addr) { 2542901Ssaidi@eecs.umich.edu if (portCache[0].valid && addr >= portCache[0].start && 2552384SN/A addr < portCache[0].end) { 2562384SN/A return portCache[0].id; 2572384SN/A } 258545SN/A if (portCache[1].valid && addr >= portCache[1].start && 259545SN/A addr < portCache[1].end) { 260545SN/A return portCache[1].id; 2612489SN/A } 2622489SN/A if (portCache[2].valid && addr >= portCache[2].start && 263545SN/A addr < portCache[2].end) { 264545SN/A return portCache[2].id; 265679SN/A } 266 267 return INVALID_PORT_ID; 268 } 269 270 // Clears the earliest entry of the cache and inserts a new port entry 271 inline void updatePortCache(short id, Addr start, Addr end) { 272 portCache[2].valid = portCache[1].valid; 273 portCache[2].id = portCache[1].id; 274 portCache[2].start = portCache[1].start; 275 portCache[2].end = portCache[1].end; 276 277 portCache[1].valid = portCache[0].valid; 278 portCache[1].id = portCache[0].id; 279 portCache[1].start = portCache[0].start; 280 portCache[1].end = portCache[0].end; 281 282 portCache[0].valid = true; 283 portCache[0].id = id; 284 portCache[0].start = start; 285 portCache[0].end = end; 286 } 287 288 // Clears the cache. Needs to be called in constructor. 289 inline void clearPortCache() { 290 portCache[2].valid = false; 291 portCache[1].valid = false; 292 portCache[0].valid = false; 293 } 294 295 /** 296 * Return the address ranges this port is responsible for. 297 * 298 * @param id id of the bus port that made the request 299 * 300 * @return a list of non-overlapping address ranges 301 */ 302 AddrRangeList getAddrRanges(int id); 303 304 /** 305 * Determine if the bus port is snooping or not. 306 * 307 * @param id id of the bus port that made the request 308 * 309 * @return a boolean indicating if this port is snooping or not 310 */ 311 bool isSnooping(int id) const; 312 313 /** Calculate the timing parameters for the packet. Updates the 314 * firstWordTime and finishTime fields of the packet object. 315 * Returns the tick at which the packet header is completed (which 316 * will be all that is sent if the target rejects the packet). 317 */ 318 Tick calcPacketTiming(PacketPtr pkt); 319 320 /** Occupy the bus until until */ 321 void occupyBus(Tick until); 322 323 /** 324 * Release the bus after being occupied and return to an idle 325 * state where we proceed to send a retry to any potential waiting 326 * port, or drain if asked to do so. 327 */ 328 void releaseBus(); 329 330 /** 331 * Send a retry to the port at the head of the retryList. The 332 * caller must ensure that the list is not empty. 333 */ 334 void retryWaiting(); 335 336 /** Ask everyone on the bus what their size is 337 * @param id id of the busport that made the request 338 * @return the max of all the sizes 339 */ 340 unsigned findBlockSize(int id); 341 342 // event used to schedule a release of the bus 343 EventWrapper<Bus, &Bus::releaseBus> busIdleEvent; 344 345 bool inRetry; 346 std::set<int> inRecvRangeChange; 347 348 // keep track of the number of master ports (not counting the 349 // default master) since we need this as an offset into the 350 // interfaces vector 351 unsigned int nbrMasterPorts; 352 353 /** The master and slave ports of the bus */ 354 std::vector<BusSlavePort*> slavePorts; 355 std::vector<BusMasterPort*> masterPorts; 356 357 /** An array of pointers to ports that retry should be called on because the 358 * original send failed for whatever reason.*/ 359 std::list<Port*> retryList; 360 361 void addToRetryList(Port* port) 362 { 363 if (!inRetry) { 364 // The device wasn't retrying a packet, or wasn't at an 365 // appropriate time. 366 retryList.push_back(port); 367 } else { 368 if (!retryList.empty() && port == retryList.front()) { 369 // The device was retrying a packet. It didn't work, 370 // so we'll leave it at the head of the retry list. 371 inRetry = false; 372 } else { 373 // We are in retry, but not for this port, put it at 374 // the end. 375 retryList.push_back(port); 376 } 377 } 378 } 379 380 /** Port that handles requests that don't match any of the interfaces.*/ 381 short defaultPortId; 382 383 /** A symbolic name for a port id that denotes no port. */ 384 static const short INVALID_PORT_ID = -1; 385 386 /** If true, use address range provided by default device. Any 387 address not handled by another port and not in default device's 388 range will cause a fatal error. If false, just send all 389 addresses not handled by another port to default device. */ 390 bool useDefaultRange; 391 392 unsigned defaultBlockSize; 393 unsigned cachedBlockSize; 394 bool cachedBlockSizeValid; 395 396 public: 397 398 /** A function used to return the port associated with this bus object. */ 399 virtual MasterPort& getMasterPort(const std::string& if_name, int idx = -1); 400 virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1); 401 402 virtual void init(); 403 virtual void startup(); 404 405 unsigned int drain(Event *de); 406 407 Bus(const BusParams *p); 408}; 409 410#endif //__MEM_BUS_HH__ 411