xbar.hh revision 3489
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 "mem/mem_object.hh" 46#include "mem/packet.hh" 47#include "mem/port.hh" 48#include "mem/request.hh" 49#include "sim/eventq.hh" 50 51class Bus : public MemObject 52{ 53 /** a globally unique id for this bus. */ 54 int busId; 55 /** the clock speed for the bus */ 56 int clock; 57 /** the width of the bus in bytes */ 58 int width; 59 /** the next tick at which the bus will be idle */ 60 Tick tickNextIdle; 61 62 static const int defaultId = -3; //Make it unique from Broadcast 63 64 struct DevMap { 65 int portId; 66 Range<Addr> range; 67 }; 68 std::vector<DevMap> portList; 69 AddrRangeList defaultRange; 70 std::vector<DevMap> portSnoopList; 71 72 /** Function called by the port when the bus is recieving a Timing 73 transaction.*/ 74 bool recvTiming(PacketPtr pkt); 75 76 /** Function called by the port when the bus is recieving a Atomic 77 transaction.*/ 78 Tick recvAtomic(PacketPtr pkt); 79 80 /** Function called by the port when the bus is recieving a Functional 81 transaction.*/ 82 void recvFunctional(PacketPtr pkt); 83 84 /** Timing function called by port when it is once again able to process 85 * requests. */ 86 void recvRetry(int id); 87 88 /** Function called by the port when the bus is recieving a status change.*/ 89 void recvStatusChange(Port::Status status, int id); 90 91 /** Find which port connected to this bus (if any) should be given a packet 92 * with this address. 93 * @param addr Address to find port for. 94 * @param id Id of the port this packet was received from (to prevent 95 * loops) 96 * @return pointer to port that the packet should be sent out of. 97 */ 98 Port *findPort(Addr addr, int id); 99 100 /** Find all ports with a matching snoop range, except src port. Keep in mind 101 * that the ranges shouldn't overlap or you will get a double snoop to the same 102 * interface.and the cache will assert out. 103 * @param addr Address to find snoop prts for. 104 * @param id Id of the src port of the request to avoid calling snoop on src 105 * @return vector of IDs to snoop on 106 */ 107 std::vector<int> findSnoopPorts(Addr addr, int id); 108 109 /** Snoop all relevant ports atomicly. */ 110 Tick atomicSnoop(PacketPtr pkt); 111 112 /** Snoop all relevant ports functionally. */ 113 void functionalSnoop(PacketPtr pkt); 114 115 /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want 116 * the snoop to happen 117 * @return True if succeds. 118 */ 119 bool timingSnoop(PacketPtr pkt); 120 121 /** Process address range request. 122 * @param resp addresses that we can respond to 123 * @param snoop addresses that we would like to snoop 124 * @param id ide of the busport that made the request. 125 */ 126 void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id); 127 128 /** Occupy the bus with transmitting the packet pkt */ 129 void occupyBus(PacketPtr pkt); 130 131 /** Declaration of the buses port type, one will be instantiated for each 132 of the interfaces connecting to the bus. */ 133 class BusPort : public Port 134 { 135 bool _onRetryList; 136 137 /** A pointer to the bus to which this port belongs. */ 138 Bus *bus; 139 140 /** A id to keep track of the intercafe ID this port is connected to. */ 141 int id; 142 143 public: 144 145 /** Constructor for the BusPort.*/ 146 BusPort(const std::string &_name, Bus *_bus, int _id) 147 : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id) 148 { } 149 150 bool onRetryList() 151 { return _onRetryList; } 152 153 void onRetryList(bool newVal) 154 { _onRetryList = newVal; } 155 156 protected: 157 158 /** When reciving a timing request from the peer port (at id), 159 pass it to the bus. */ 160 virtual bool recvTiming(PacketPtr pkt) 161 { pkt->setSrc(id); return bus->recvTiming(pkt); } 162 163 /** When reciving a Atomic requestfrom the peer port (at id), 164 pass it to the bus. */ 165 virtual Tick recvAtomic(PacketPtr pkt) 166 { pkt->setSrc(id); return bus->recvAtomic(pkt); } 167 168 /** When reciving a Functional requestfrom the peer port (at id), 169 pass it to the bus. */ 170 virtual void recvFunctional(PacketPtr pkt) 171 { pkt->setSrc(id); bus->recvFunctional(pkt); } 172 173 /** When reciving a status changefrom the peer port (at id), 174 pass it to the bus. */ 175 virtual void recvStatusChange(Status status) 176 { bus->recvStatusChange(status, id); } 177 178 /** When reciving a retry from the peer port (at id), 179 pass it to the bus. */ 180 virtual void recvRetry() 181 { bus->recvRetry(id); } 182 183 // This should return all the 'owned' addresses that are 184 // downstream from this bus, yes? That is, the union of all 185 // the 'owned' address ranges of all the other interfaces on 186 // this bus... 187 virtual void getDeviceAddressRanges(AddrRangeList &resp, 188 AddrRangeList &snoop) 189 { bus->addressRanges(resp, snoop, id); } 190 191 // Hack to make translating port work without changes 192 virtual int deviceBlockSize() { return 32; } 193 194 }; 195 196 class BusFreeEvent : public Event 197 { 198 Bus * bus; 199 200 public: 201 BusFreeEvent(Bus * _bus); 202 void process(); 203 const char *description(); 204 }; 205 206 BusFreeEvent busIdle; 207 208 bool inRetry; 209 210 /** An array of pointers to the peer port interfaces 211 connected to this bus.*/ 212 std::vector<BusPort*> interfaces; 213 214 /** An array of pointers to ports that retry should be called on because the 215 * original send failed for whatever reason.*/ 216 std::list<BusPort*> retryList; 217 218 void addToRetryList(BusPort * port) 219 { 220 if (!inRetry) { 221 // The device wasn't retrying a packet, or wasn't at an appropriate 222 // time. 223 assert(!port->onRetryList()); 224 port->onRetryList(true); 225 retryList.push_back(port); 226 } else { 227 if (port->onRetryList()) { 228 // The device was retrying a packet. It didn't work, so we'll leave 229 // it at the head of the retry list. 230 assert(port == retryList.front()); 231 inRetry = false; 232 } 233 else { 234 port->onRetryList(true); 235 retryList.push_back(port); 236 } 237 } 238 } 239 240 /** Port that handles requests that don't match any of the interfaces.*/ 241 BusPort *defaultPort; 242 243 /** Has the user specified their own default responder? */ 244 bool responderSet; 245 246 public: 247 248 /** A function used to return the port associated with this bus object. */ 249 virtual Port *getPort(const std::string &if_name, int idx = -1); 250 251 virtual void init(); 252 253 Bus(const std::string &n, int bus_id, int _clock, int _width, 254 bool responder_set) 255 : MemObject(n), busId(bus_id), clock(_clock), width(_width), 256 tickNextIdle(0), busIdle(this), inRetry(false), defaultPort(NULL), 257 responderSet(responder_set) 258 { 259 //Both the width and clock period must be positive 260 if (width <= 0) 261 fatal("Bus width must be positive\n"); 262 if (clock <= 0) 263 fatal("Bus clock period must be positive\n"); 264 } 265 266}; 267 268#endif //__MEM_BUS_HH__ 269