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