noncoherent_xbar.hh revision 4475
1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Ron Dreslinski 29 * Ali Saidi 30 */ 31 32/** 33 * @file 34 * Declaration of a bus object. 35 */ 36 37#ifndef __MEM_BUS_HH__ 38#define __MEM_BUS_HH__ 39 40#include <string> 41#include <list> 42#include <inttypes.h> 43 44#include "base/range.hh" 45#include "base/hashmap.hh" 46#include "base/range_map.hh" 47#include "mem/mem_object.hh" 48#include "mem/packet.hh" 49#include "mem/port.hh" 50#include "mem/request.hh" 51#include "sim/eventq.hh" 52 53class Bus : public MemObject 54{ 55 /** Declaration of the buses port type, one will be instantiated for each 56 of the interfaces connecting to the bus. */ 57 class BusPort : public Port 58 { 59 bool _onRetryList; 60 61 /** A pointer to the bus to which this port belongs. */ 62 Bus *bus; 63 64 /** A id to keep track of the intercafe ID this port is connected to. */ 65 int id; 66 67 public: 68 69 /** Constructor for the BusPort.*/ 70 BusPort(const std::string &_name, Bus *_bus, int _id) 71 : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id) 72 { } 73 74 bool onRetryList() 75 { return _onRetryList; } 76 77 void onRetryList(bool newVal) 78 { _onRetryList = newVal; } 79 80 int getId() { return id; } 81 82 protected: 83 84 /** When reciving a timing request from the peer port (at id), 85 pass it to the bus. */ 86 virtual bool recvTiming(PacketPtr pkt) 87 { pkt->setSrc(id); return bus->recvTiming(pkt); } 88 89 /** When reciving a Atomic requestfrom the peer port (at id), 90 pass it to the bus. */ 91 virtual Tick recvAtomic(PacketPtr pkt) 92 { pkt->setSrc(id); return bus->recvAtomic(pkt); } 93 94 /** When reciving a Functional requestfrom the peer port (at id), 95 pass it to the bus. */ 96 virtual void recvFunctional(PacketPtr pkt) 97 { pkt->setSrc(id); bus->recvFunctional(pkt); } 98 99 /** When reciving a status changefrom the peer port (at id), 100 pass it to the bus. */ 101 virtual void recvStatusChange(Status status) 102 { bus->recvStatusChange(status, id); } 103 104 /** When reciving a retry from the peer port (at id), 105 pass it to the bus. */ 106 virtual void recvRetry() 107 { bus->recvRetry(id); } 108 109 // This should return all the 'owned' addresses that are 110 // downstream from this bus, yes? That is, the union of all 111 // the 'owned' address ranges of all the other interfaces on 112 // this bus... 113 virtual void getDeviceAddressRanges(AddrRangeList &resp, 114 bool &snoop) 115 { bus->addressRanges(resp, snoop, id); } 116 117 // Ask the bus to ask everyone on the bus what their block size is and 118 // take the max of it. This might need to be changed a bit if we ever 119 // support multiple block sizes. 120 virtual int deviceBlockSize() 121 { return bus->findBlockSize(id); } 122 123 }; 124 125 class BusFreeEvent : public Event 126 { 127 Bus * bus; 128 129 public: 130 BusFreeEvent(Bus * _bus); 131 void process(); 132 const char *description(); 133 }; 134 135 /** a globally unique id for this bus. */ 136 int busId; 137 /** the clock speed for the bus */ 138 int clock; 139 /** the width of the bus in bytes */ 140 int width; 141 /** the next tick at which the bus will be idle */ 142 Tick tickNextIdle; 143 144 Event * drainEvent; 145 146 147 static const int defaultId = -3; //Make it unique from Broadcast 148 149 typedef range_map<Addr,int>::iterator PortIter; 150 range_map<Addr, int> portMap; 151 152 AddrRangeList defaultRange; 153 154 typedef std::vector<BusPort*>::iterator SnoopIter; 155 std::vector<BusPort*> snoopPorts; 156 157 /** Function called by the port when the bus is recieving a Timing 158 transaction.*/ 159 bool recvTiming(PacketPtr pkt); 160 161 /** Function called by the port when the bus is recieving a Atomic 162 transaction.*/ 163 Tick recvAtomic(PacketPtr pkt); 164 165 /** Function called by the port when the bus is recieving a Functional 166 transaction.*/ 167 void recvFunctional(PacketPtr pkt); 168 169 /** Timing function called by port when it is once again able to process 170 * requests. */ 171 void recvRetry(int id); 172 173 /** Function called by the port when the bus is recieving a status change.*/ 174 void recvStatusChange(Port::Status status, int id); 175 176 /** Find which port connected to this bus (if any) should be given a packet 177 * with this address. 178 * @param addr Address to find port for. 179 * @param id Id of the port this packet was received from (to prevent 180 * loops) 181 * @return pointer to port that the packet should be sent out of. 182 */ 183 Port *findPort(Addr addr, int id); 184 185 /** Snoop all relevant ports atomicly. */ 186 Tick atomicSnoop(PacketPtr pkt, Port* responder); 187 188 /** Snoop all relevant ports functionally. */ 189 void functionalSnoop(PacketPtr pkt, Port *responder); 190 191 /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want 192 * the snoop to happen 193 * @return True if succeds. 194 */ 195 bool timingSnoop(PacketPtr pkt, Port *responder); 196 197 /** Process address range request. 198 * @param resp addresses that we can respond to 199 * @param snoop addresses that we would like to snoop 200 * @param id ide of the busport that made the request. 201 */ 202 void addressRanges(AddrRangeList &resp, bool &snoop, int id); 203 204 /** Occupy the bus with transmitting the packet pkt */ 205 void occupyBus(PacketPtr pkt); 206 207 /** Ask everyone on the bus what their size is 208 * @param id id of the busport that made the request 209 * @return the max of all the sizes 210 */ 211 int findBlockSize(int id); 212 213 BusFreeEvent busIdle; 214 215 bool inRetry; 216 217 /** max number of bus ids we've handed out so far */ 218 short maxId; 219 220 /** An array of pointers to the peer port interfaces 221 connected to this bus.*/ 222 m5::hash_map<short,BusPort*> interfaces; 223 224 /** An array of pointers to ports that retry should be called on because the 225 * original send failed for whatever reason.*/ 226 std::list<BusPort*> retryList; 227 228 void addToRetryList(BusPort * port) 229 { 230 if (!inRetry) { 231 // The device wasn't retrying a packet, or wasn't at an appropriate 232 // time. 233 assert(!port->onRetryList()); 234 port->onRetryList(true); 235 retryList.push_back(port); 236 } else { 237 if (port->onRetryList()) { 238 // The device was retrying a packet. It didn't work, so we'll leave 239 // it at the head of the retry list. 240 assert(port == retryList.front()); 241 inRetry = false; 242 } 243 else { 244 port->onRetryList(true); 245 retryList.push_back(port); 246 } 247 } 248 } 249 250 /** Port that handles requests that don't match any of the interfaces.*/ 251 BusPort *defaultPort; 252 253 BusPort *funcPort; 254 int funcPortId; 255 256 /** Has the user specified their own default responder? */ 257 bool responderSet; 258 259 int defaultBlockSize; 260 int cachedBlockSize; 261 bool cachedBlockSizeValid; 262 263 public: 264 265 /** A function used to return the port associated with this bus object. */ 266 virtual Port *getPort(const std::string &if_name, int idx = -1); 267 virtual void deletePortRefs(Port *p); 268 269 virtual void init(); 270 271 unsigned int drain(Event *de); 272 273 Bus(const std::string &n, int bus_id, int _clock, int _width, 274 bool responder_set, int dflt_blk_size) 275 : MemObject(n), busId(bus_id), clock(_clock), width(_width), 276 tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false), 277 maxId(0), defaultPort(NULL), funcPort(NULL), funcPortId(-4), 278 responderSet(responder_set), defaultBlockSize(dflt_blk_size), 279 cachedBlockSize(0), cachedBlockSizeValid(false) 280 { 281 //Both the width and clock period must be positive 282 if (width <= 0) 283 fatal("Bus width must be positive\n"); 284 if (clock <= 0) 285 fatal("Bus clock period must be positive\n"); 286 } 287 288}; 289 290#endif //__MEM_BUS_HH__ 291