xbar.hh revision 8715
114039Sstacze01@arm.com/* 214039Sstacze01@arm.com * Copyright (c) 2011 ARM Limited 314039Sstacze01@arm.com * All rights reserved 414039Sstacze01@arm.com * 514039Sstacze01@arm.com * The license below extends only to copyright in the software and shall 614039Sstacze01@arm.com * not be construed as granting a license to any other intellectual 714039Sstacze01@arm.com * property including but not limited to intellectual property relating 814039Sstacze01@arm.com * to a hardware implementation of the functionality of the software 914039Sstacze01@arm.com * licensed hereunder. You may use the software subject to the license 1014039Sstacze01@arm.com * terms below provided that you ensure that this notice is replicated 1114039Sstacze01@arm.com * unmodified and in its entirety in all distributions of the software, 1214039Sstacze01@arm.com * modified or unmodified, in source code or in binary form. 1314039Sstacze01@arm.com * 1414039Sstacze01@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 1514039Sstacze01@arm.com * All rights reserved. 1614039Sstacze01@arm.com * 1714039Sstacze01@arm.com * Redistribution and use in source and binary forms, with or without 1814039Sstacze01@arm.com * modification, are permitted provided that the following conditions are 1914039Sstacze01@arm.com * met: redistributions of source code must retain the above copyright 2014039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer; 2114039Sstacze01@arm.com * redistributions in binary form must reproduce the above copyright 2214039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer in the 2314039Sstacze01@arm.com * documentation and/or other materials provided with the distribution; 2414039Sstacze01@arm.com * neither the name of the copyright holders nor the names of its 2514039Sstacze01@arm.com * contributors may be used to endorse or promote products derived from 2614039Sstacze01@arm.com * this software without specific prior written permission. 2714039Sstacze01@arm.com * 2814039Sstacze01@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2914039Sstacze01@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3014039Sstacze01@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3114039Sstacze01@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3214039Sstacze01@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3314039Sstacze01@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3414039Sstacze01@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3514039Sstacze01@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3614039Sstacze01@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3714039Sstacze01@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3814039Sstacze01@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3914039Sstacze01@arm.com * 4014039Sstacze01@arm.com * Authors: Ron Dreslinski 4114039Sstacze01@arm.com * Ali Saidi 4214039Sstacze01@arm.com * Andreas Hansson 4314039Sstacze01@arm.com */ 4414039Sstacze01@arm.com 4514039Sstacze01@arm.com/** 4614039Sstacze01@arm.com * @file 4714039Sstacze01@arm.com * Declaration of a bus object. 4814039Sstacze01@arm.com */ 4914039Sstacze01@arm.com 5014039Sstacze01@arm.com#ifndef __MEM_BUS_HH__ 5114039Sstacze01@arm.com#define __MEM_BUS_HH__ 5214039Sstacze01@arm.com 5314039Sstacze01@arm.com#include <list> 5414039Sstacze01@arm.com#include <set> 5514039Sstacze01@arm.com#include <string> 5614039Sstacze01@arm.com 5714039Sstacze01@arm.com#include "base/hashmap.hh" 5814039Sstacze01@arm.com#include "base/range.hh" 5914039Sstacze01@arm.com#include "base/range_map.hh" 6014039Sstacze01@arm.com#include "base/types.hh" 6114039Sstacze01@arm.com#include "mem/mem_object.hh" 6214039Sstacze01@arm.com#include "mem/packet.hh" 6314039Sstacze01@arm.com#include "mem/port.hh" 6414039Sstacze01@arm.com#include "mem/request.hh" 6514039Sstacze01@arm.com#include "params/Bus.hh" 6614039Sstacze01@arm.com#include "sim/eventq.hh" 6714039Sstacze01@arm.com 6814039Sstacze01@arm.comclass Bus : public MemObject 6914039Sstacze01@arm.com{ 7014039Sstacze01@arm.com /** Declaration of the buses port type, one will be instantiated for each 7114039Sstacze01@arm.com of the interfaces connecting to the bus. */ 7214039Sstacze01@arm.com class BusPort : public Port 7314039Sstacze01@arm.com { 7414039Sstacze01@arm.com bool _onRetryList; 7514039Sstacze01@arm.com 7614039Sstacze01@arm.com /** A pointer to the bus to which this port belongs. */ 7714039Sstacze01@arm.com Bus *bus; 7814039Sstacze01@arm.com 7914039Sstacze01@arm.com /** A id to keep track of the intercafe ID this port is connected to. */ 8014039Sstacze01@arm.com int id; 8114039Sstacze01@arm.com 8214039Sstacze01@arm.com public: 8314039Sstacze01@arm.com 8414039Sstacze01@arm.com /** Constructor for the BusPort.*/ 8514039Sstacze01@arm.com BusPort(const std::string &_name, Bus *_bus, int _id) 8614039Sstacze01@arm.com : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id) 8714039Sstacze01@arm.com { } 8814039Sstacze01@arm.com 8914039Sstacze01@arm.com bool onRetryList() 9014039Sstacze01@arm.com { return _onRetryList; } 9114039Sstacze01@arm.com 9214039Sstacze01@arm.com void onRetryList(bool newVal) 9314039Sstacze01@arm.com { _onRetryList = newVal; } 9414039Sstacze01@arm.com 9514039Sstacze01@arm.com int getId() const { return id; } 9614039Sstacze01@arm.com 9714039Sstacze01@arm.com /** 9814039Sstacze01@arm.com * Determine if this port should be considered a snooper. This 9914039Sstacze01@arm.com * is determined by the bus. 10014039Sstacze01@arm.com * 10114039Sstacze01@arm.com * @return a boolean that is true if this port is snooping 10214039Sstacze01@arm.com */ 10314039Sstacze01@arm.com virtual bool isSnooping() 10414039Sstacze01@arm.com { return bus->isSnooping(id); } 10514039Sstacze01@arm.com 10614039Sstacze01@arm.com protected: 10714039Sstacze01@arm.com 10814039Sstacze01@arm.com /** When reciving a timing request from the peer port (at id), 10914039Sstacze01@arm.com pass it to the bus. */ 11014039Sstacze01@arm.com virtual bool recvTiming(PacketPtr pkt) 11114039Sstacze01@arm.com { pkt->setSrc(id); return bus->recvTiming(pkt); } 11214039Sstacze01@arm.com 11314039Sstacze01@arm.com /** When reciving a Atomic requestfrom the peer port (at id), 11414039Sstacze01@arm.com pass it to the bus. */ 11514039Sstacze01@arm.com virtual Tick recvAtomic(PacketPtr pkt) 11614039Sstacze01@arm.com { pkt->setSrc(id); return bus->recvAtomic(pkt); } 11714039Sstacze01@arm.com 11814039Sstacze01@arm.com /** When reciving a Functional requestfrom the peer port (at id), 11914039Sstacze01@arm.com pass it to the bus. */ 12014039Sstacze01@arm.com virtual void recvFunctional(PacketPtr pkt) 12114039Sstacze01@arm.com { pkt->setSrc(id); bus->recvFunctional(pkt); } 12214039Sstacze01@arm.com 12314039Sstacze01@arm.com /** When reciving a range change from the peer port (at id), 12414039Sstacze01@arm.com pass it to the bus. */ 12514039Sstacze01@arm.com virtual void recvRangeChange() 12614039Sstacze01@arm.com { bus->recvRangeChange(id); } 12714039Sstacze01@arm.com 12814039Sstacze01@arm.com /** When reciving a retry from the peer port (at id), 12914039Sstacze01@arm.com pass it to the bus. */ 13014039Sstacze01@arm.com virtual void recvRetry() 13114039Sstacze01@arm.com { bus->recvRetry(id); } 13214039Sstacze01@arm.com 13314039Sstacze01@arm.com // This should return all the 'owned' addresses that are 13414039Sstacze01@arm.com // downstream from this bus, yes? That is, the union of all 13514039Sstacze01@arm.com // the 'owned' address ranges of all the other interfaces on 13614039Sstacze01@arm.com // this bus... 13714039Sstacze01@arm.com virtual AddrRangeList getAddrRanges() 13814039Sstacze01@arm.com { return bus->getAddrRanges(id); } 13914039Sstacze01@arm.com 14014039Sstacze01@arm.com // Ask the bus to ask everyone on the bus what their block size is and 14114039Sstacze01@arm.com // take the max of it. This might need to be changed a bit if we ever 14214039Sstacze01@arm.com // support multiple block sizes. 14314039Sstacze01@arm.com virtual unsigned deviceBlockSize() const 14414039Sstacze01@arm.com { return bus->findBlockSize(id); } 14514039Sstacze01@arm.com 14614039Sstacze01@arm.com }; 14714039Sstacze01@arm.com 14814039Sstacze01@arm.com class BusFreeEvent : public Event 14914039Sstacze01@arm.com { 15014039Sstacze01@arm.com Bus * bus; 15114039Sstacze01@arm.com 15214039Sstacze01@arm.com public: 15314039Sstacze01@arm.com BusFreeEvent(Bus * _bus); 15414039Sstacze01@arm.com void process(); 15514039Sstacze01@arm.com const char *description() const; 15614039Sstacze01@arm.com }; 15714039Sstacze01@arm.com 15814039Sstacze01@arm.com /** a globally unique id for this bus. */ 15914039Sstacze01@arm.com int busId; 16014039Sstacze01@arm.com /** the clock speed for the bus */ 16114039Sstacze01@arm.com int clock; 16214039Sstacze01@arm.com /** cycles of overhead per transaction */ 16314039Sstacze01@arm.com int headerCycles; 16414039Sstacze01@arm.com /** the width of the bus in bytes */ 16514039Sstacze01@arm.com int width; 16614039Sstacze01@arm.com /** the next tick at which the bus will be idle */ 16714039Sstacze01@arm.com Tick tickNextIdle; 16814039Sstacze01@arm.com 16914039Sstacze01@arm.com Event * drainEvent; 17014039Sstacze01@arm.com 17114039Sstacze01@arm.com typedef range_map<Addr,int>::iterator PortIter; 17214039Sstacze01@arm.com range_map<Addr, int> portMap; 17314039Sstacze01@arm.com 17414039Sstacze01@arm.com AddrRangeList defaultRange; 17514039Sstacze01@arm.com 17614039Sstacze01@arm.com typedef std::vector<BusPort*>::iterator SnoopIter; 17714039Sstacze01@arm.com std::vector<BusPort*> snoopPorts; 17814039Sstacze01@arm.com 179 /** Function called by the port when the bus is recieving a Timing 180 transaction.*/ 181 bool recvTiming(PacketPtr pkt); 182 183 /** Function called by the port when the bus is recieving a Atomic 184 transaction.*/ 185 Tick recvAtomic(PacketPtr pkt); 186 187 /** Function called by the port when the bus is recieving a Functional 188 transaction.*/ 189 void recvFunctional(PacketPtr pkt); 190 191 /** Timing function called by port when it is once again able to process 192 * requests. */ 193 void recvRetry(int id); 194 195 /** Function called by the port when the bus is recieving a range change.*/ 196 void recvRangeChange(int id); 197 198 /** Find which port connected to this bus (if any) should be given a packet 199 * with this address. 200 * @param addr Address to find port for. 201 * @return id of port that the packet should be sent out of. 202 */ 203 int findPort(Addr addr); 204 205 // Cache for the findPort function storing recently used ports from portMap 206 struct PortCache { 207 bool valid; 208 int id; 209 Addr start; 210 Addr end; 211 }; 212 213 PortCache portCache[3]; 214 215 // Checks the cache and returns the id of the port that has the requested 216 // address within its range 217 inline int checkPortCache(Addr addr) { 218 if (portCache[0].valid && addr >= portCache[0].start && 219 addr < portCache[0].end) { 220 return portCache[0].id; 221 } 222 if (portCache[1].valid && addr >= portCache[1].start && 223 addr < portCache[1].end) { 224 return portCache[1].id; 225 } 226 if (portCache[2].valid && addr >= portCache[2].start && 227 addr < portCache[2].end) { 228 return portCache[2].id; 229 } 230 231 return -1; 232 } 233 234 // Clears the earliest entry of the cache and inserts a new port entry 235 inline void updatePortCache(short id, Addr start, Addr end) { 236 portCache[2].valid = portCache[1].valid; 237 portCache[2].id = portCache[1].id; 238 portCache[2].start = portCache[1].start; 239 portCache[2].end = portCache[1].end; 240 241 portCache[1].valid = portCache[0].valid; 242 portCache[1].id = portCache[0].id; 243 portCache[1].start = portCache[0].start; 244 portCache[1].end = portCache[0].end; 245 246 portCache[0].valid = true; 247 portCache[0].id = id; 248 portCache[0].start = start; 249 portCache[0].end = end; 250 } 251 252 // Clears the cache. Needs to be called in constructor. 253 inline void clearPortCache() { 254 portCache[2].valid = false; 255 portCache[1].valid = false; 256 portCache[0].valid = false; 257 } 258 259 /** 260 * Return the address ranges this port is responsible for. 261 * 262 * @param id id of the bus port that made the request 263 * 264 * @return a list of non-overlapping address ranges 265 */ 266 AddrRangeList getAddrRanges(int id); 267 268 /** 269 * Determine if the bus port is snooping or not. 270 * 271 * @param id id of the bus port that made the request 272 * 273 * @return a boolean indicating if this port is snooping or not 274 */ 275 bool isSnooping(int id); 276 277 /** Calculate the timing parameters for the packet. Updates the 278 * firstWordTime and finishTime fields of the packet object. 279 * Returns the tick at which the packet header is completed (which 280 * will be all that is sent if the target rejects the packet). 281 */ 282 Tick calcPacketTiming(PacketPtr pkt); 283 284 /** Occupy the bus until until */ 285 void occupyBus(Tick until); 286 287 /** Ask everyone on the bus what their size is 288 * @param id id of the busport that made the request 289 * @return the max of all the sizes 290 */ 291 unsigned findBlockSize(int id); 292 293 BusFreeEvent busIdle; 294 295 bool inRetry; 296 std::set<int> inRecvRangeChange; 297 298 /** An ordered vector of pointers to the peer port interfaces 299 connected to this bus.*/ 300 std::vector<BusPort*> interfaces; 301 302 /** An array of pointers to ports that retry should be called on because the 303 * original send failed for whatever reason.*/ 304 std::list<BusPort*> retryList; 305 306 void addToRetryList(BusPort * port) 307 { 308 if (!inRetry) { 309 // The device wasn't retrying a packet, or wasn't at an appropriate 310 // time. 311 assert(!port->onRetryList()); 312 port->onRetryList(true); 313 retryList.push_back(port); 314 } else { 315 if (port->onRetryList()) { 316 // The device was retrying a packet. It didn't work, so we'll leave 317 // it at the head of the retry list. 318 assert(port == retryList.front()); 319 inRetry = false; 320 } 321 else { 322 port->onRetryList(true); 323 retryList.push_back(port); 324 } 325 } 326 } 327 328 /** Port that handles requests that don't match any of the interfaces.*/ 329 short defaultPortId; 330 331 /** If true, use address range provided by default device. Any 332 address not handled by another port and not in default device's 333 range will cause a fatal error. If false, just send all 334 addresses not handled by another port to default device. */ 335 bool useDefaultRange; 336 337 unsigned defaultBlockSize; 338 unsigned cachedBlockSize; 339 bool cachedBlockSizeValid; 340 341 public: 342 343 /** A function used to return the port associated with this bus object. */ 344 virtual Port *getPort(const std::string &if_name, int idx = -1); 345 346 virtual void init(); 347 virtual void startup(); 348 349 unsigned int drain(Event *de); 350 351 Bus(const BusParams *p); 352}; 353 354#endif //__MEM_BUS_HH__ 355