xbar.hh revision 8715
1/* 2 * Copyright (c) 2011 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) 2002-2005 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: Ron Dreslinski 41 * Ali Saidi 42 * Andreas Hansson 43 */ 44 45/** 46 * @file 47 * Declaration of a bus object. 48 */ 49 50#ifndef __MEM_BUS_HH__ 51#define __MEM_BUS_HH__ 52 53#include <list> 54#include <set> 55#include <string> 56 57#include "base/hashmap.hh" 58#include "base/range.hh" 59#include "base/range_map.hh" 60#include "base/types.hh" 61#include "mem/mem_object.hh" 62#include "mem/packet.hh" 63#include "mem/port.hh" 64#include "mem/request.hh" 65#include "params/Bus.hh" 66#include "sim/eventq.hh" 67 68class Bus : public MemObject 69{ 70 /** Declaration of the buses port type, one will be instantiated for each 71 of the interfaces connecting to the bus. */ 72 class BusPort : public Port 73 { 74 bool _onRetryList; 75 76 /** A pointer to the bus to which this port belongs. */ 77 Bus *bus; 78 79 /** A id to keep track of the intercafe ID this port is connected to. */ 80 int id; 81 82 public: 83 84 /** Constructor for the BusPort.*/ 85 BusPort(const std::string &_name, Bus *_bus, int _id) 86 : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id) 87 { } 88 89 bool onRetryList() 90 { return _onRetryList; } 91 92 void onRetryList(bool newVal) 93 { _onRetryList = newVal; } 94 95 int getId() const { return id; } 96 97 /** 98 * Determine if this port should be considered a snooper. This 99 * is determined by the bus. 100 * 101 * @return a boolean that is true if this port is snooping 102 */ 103 virtual bool isSnooping() 104 { return bus->isSnooping(id); } 105 106 protected: 107 108 /** When reciving a timing request from the peer port (at id), 109 pass it to the bus. */ 110 virtual bool recvTiming(PacketPtr pkt) 111 { pkt->setSrc(id); return bus->recvTiming(pkt); } 112 113 /** When reciving a Atomic requestfrom the peer port (at id), 114 pass it to the bus. */ 115 virtual Tick recvAtomic(PacketPtr pkt) 116 { pkt->setSrc(id); return bus->recvAtomic(pkt); } 117 118 /** When reciving a Functional requestfrom the peer port (at id), 119 pass it to the bus. */ 120 virtual void recvFunctional(PacketPtr pkt) 121 { pkt->setSrc(id); bus->recvFunctional(pkt); } 122 123 /** When reciving a range change from the peer port (at id), 124 pass it to the bus. */ 125 virtual void recvRangeChange() 126 { bus->recvRangeChange(id); } 127 128 /** When reciving a retry from the peer port (at id), 129 pass it to the bus. */ 130 virtual void recvRetry() 131 { bus->recvRetry(id); } 132 133 // This should return all the 'owned' addresses that are 134 // downstream from this bus, yes? That is, the union of all 135 // the 'owned' address ranges of all the other interfaces on 136 // this bus... 137 virtual AddrRangeList getAddrRanges() 138 { return bus->getAddrRanges(id); } 139 140 // Ask the bus to ask everyone on the bus what their block size is and 141 // take the max of it. This might need to be changed a bit if we ever 142 // support multiple block sizes. 143 virtual unsigned deviceBlockSize() const 144 { return bus->findBlockSize(id); } 145 146 }; 147 148 class BusFreeEvent : public Event 149 { 150 Bus * bus; 151 152 public: 153 BusFreeEvent(Bus * _bus); 154 void process(); 155 const char *description() const; 156 }; 157 158 /** a globally unique id for this bus. */ 159 int busId; 160 /** the clock speed for the bus */ 161 int clock; 162 /** cycles of overhead per transaction */ 163 int headerCycles; 164 /** the width of the bus in bytes */ 165 int width; 166 /** the next tick at which the bus will be idle */ 167 Tick tickNextIdle; 168 169 Event * drainEvent; 170 171 typedef range_map<Addr,int>::iterator PortIter; 172 range_map<Addr, int> portMap; 173 174 AddrRangeList defaultRange; 175 176 typedef std::vector<BusPort*>::iterator SnoopIter; 177 std::vector<BusPort*> snoopPorts; 178 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