xbar.hh revision 9090
1/* 2 * Copyright (c) 2011-2012 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 * William Wang 44 */ 45 46/** 47 * @file 48 * Declaration of an abstract bus base class. 49 */ 50 51#ifndef __MEM_BUS_HH__ 52#define __MEM_BUS_HH__ 53 54#include <list> 55#include <set> 56 57#include "base/range.hh" 58#include "base/range_map.hh" 59#include "base/types.hh" 60#include "mem/mem_object.hh" 61#include "params/BaseBus.hh" 62 63/** 64 * The base bus contains the common elements of the non-coherent and 65 * coherent bus. It is an abstract class that does not have any of the 66 * functionality relating to the actual reception and transmission of 67 * packets, as this is left for the subclasses. 68 * 69 * The BaseBus is responsible for the basic flow control (busy or 70 * not), the administration of retries, and the address decoding. 71 */ 72class BaseBus : public MemObject 73{ 74 75 protected: 76 77 /** the clock speed for the bus */ 78 int clock; 79 /** cycles of overhead per transaction */ 80 int headerCycles; 81 /** the width of the bus in bytes */ 82 int width; 83 /** the next tick at which the bus will be idle */ 84 Tick tickNextIdle; 85 86 Event * drainEvent; 87 88 typedef range_map<Addr, PortID>::iterator PortMapIter; 89 typedef range_map<Addr, PortID>::const_iterator PortMapConstIter; 90 range_map<Addr, PortID> portMap; 91 92 AddrRangeList defaultRange; 93 94 /** 95 * Determine if the bus is to be considered occupied when being 96 * presented with a packet from a specific port. If so, the port 97 * in question is also added to the retry list. 98 * 99 * @param port Source port on the bus presenting the packet 100 * 101 * @return True if the bus is to be considered occupied 102 */ 103 bool isOccupied(Port* port); 104 105 /** 106 * Deal with a destination port accepting a packet by potentially 107 * removing the source port from the retry list (if retrying) and 108 * occupying the bus accordingly. 109 * 110 * @param busy_time Time to spend as a result of a successful send 111 */ 112 void succeededTiming(Tick busy_time); 113 114 /** Timing function called by port when it is once again able to process 115 * requests. */ 116 void recvRetry(); 117 118 /** 119 * Function called by the port when the bus is recieving a range change. 120 * 121 * @param master_port_id id of the port that received the change 122 */ 123 void recvRangeChange(PortID master_port_id); 124 125 /** Find which port connected to this bus (if any) should be given a packet 126 * with this address. 127 * @param addr Address to find port for. 128 * @return id of port that the packet should be sent out of. 129 */ 130 PortID findPort(Addr addr); 131 132 // Cache for the findPort function storing recently used ports from portMap 133 struct PortCache { 134 bool valid; 135 PortID id; 136 Addr start; 137 Addr end; 138 }; 139 140 PortCache portCache[3]; 141 142 // Checks the cache and returns the id of the port that has the requested 143 // address within its range 144 inline PortID checkPortCache(Addr addr) { 145 if (portCache[0].valid && addr >= portCache[0].start && 146 addr < portCache[0].end) { 147 return portCache[0].id; 148 } 149 if (portCache[1].valid && addr >= portCache[1].start && 150 addr < portCache[1].end) { 151 return portCache[1].id; 152 } 153 if (portCache[2].valid && addr >= portCache[2].start && 154 addr < portCache[2].end) { 155 return portCache[2].id; 156 } 157 158 return InvalidPortID; 159 } 160 161 // Clears the earliest entry of the cache and inserts a new port entry 162 inline void updatePortCache(short id, Addr start, Addr end) { 163 portCache[2].valid = portCache[1].valid; 164 portCache[2].id = portCache[1].id; 165 portCache[2].start = portCache[1].start; 166 portCache[2].end = portCache[1].end; 167 168 portCache[1].valid = portCache[0].valid; 169 portCache[1].id = portCache[0].id; 170 portCache[1].start = portCache[0].start; 171 portCache[1].end = portCache[0].end; 172 173 portCache[0].valid = true; 174 portCache[0].id = id; 175 portCache[0].start = start; 176 portCache[0].end = end; 177 } 178 179 // Clears the cache. Needs to be called in constructor. 180 inline void clearPortCache() { 181 portCache[2].valid = false; 182 portCache[1].valid = false; 183 portCache[0].valid = false; 184 } 185 186 /** 187 * Return the address ranges the bus is responsible for. 188 * 189 * @return a list of non-overlapping address ranges 190 */ 191 AddrRangeList getAddrRanges() const; 192 193 /** Calculate the timing parameters for the packet. Updates the 194 * firstWordTime and finishTime fields of the packet object. 195 * Returns the tick at which the packet header is completed (which 196 * will be all that is sent if the target rejects the packet). 197 */ 198 Tick calcPacketTiming(PacketPtr pkt); 199 200 /** Occupy the bus until until */ 201 void occupyBus(Tick until); 202 203 /** 204 * Release the bus after being occupied and return to an idle 205 * state where we proceed to send a retry to any potential waiting 206 * port, or drain if asked to do so. 207 */ 208 void releaseBus(); 209 210 /** 211 * Send a retry to the port at the head of the retryList. The 212 * caller must ensure that the list is not empty. 213 */ 214 void retryWaiting(); 215 216 /** 217 * Ask everyone on the bus what their size is 218 * 219 * @return the max of all the sizes 220 */ 221 unsigned findBlockSize(); 222 223 // event used to schedule a release of the bus 224 EventWrapper<BaseBus, &BaseBus::releaseBus> busIdleEvent; 225 226 bool inRetry; 227 std::set<PortID> inRecvRangeChange; 228 229 /** The master and slave ports of the bus */ 230 std::vector<SlavePort*> slavePorts; 231 std::vector<MasterPort*> masterPorts; 232 233 /** Convenience typedefs. */ 234 typedef std::vector<SlavePort*>::iterator SlavePortIter; 235 typedef std::vector<MasterPort*>::iterator MasterPortIter; 236 typedef std::vector<SlavePort*>::const_iterator SlavePortConstIter; 237 typedef std::vector<MasterPort*>::const_iterator MasterPortConstIter; 238 239 /** An array of pointers to ports that retry should be called on because the 240 * original send failed for whatever reason.*/ 241 std::list<Port*> retryList; 242 243 void addToRetryList(Port* port) 244 { 245 if (!inRetry) { 246 // The device wasn't retrying a packet, or wasn't at an 247 // appropriate time. 248 retryList.push_back(port); 249 } else { 250 if (!retryList.empty() && port == retryList.front()) { 251 // The device was retrying a packet. It didn't work, 252 // so we'll leave it at the head of the retry list. 253 inRetry = false; 254 } else { 255 // We are in retry, but not for this port, put it at 256 // the end. 257 retryList.push_back(port); 258 } 259 } 260 } 261 262 /** Port that handles requests that don't match any of the interfaces.*/ 263 PortID defaultPortID; 264 265 /** If true, use address range provided by default device. Any 266 address not handled by another port and not in default device's 267 range will cause a fatal error. If false, just send all 268 addresses not handled by another port to default device. */ 269 bool useDefaultRange; 270 271 unsigned defaultBlockSize; 272 unsigned cachedBlockSize; 273 bool cachedBlockSizeValid; 274 275 BaseBus(const BaseBusParams *p); 276 277 virtual ~BaseBus(); 278 279 public: 280 281 /** A function used to return the port associated with this bus object. */ 282 virtual MasterPort& getMasterPort(const std::string& if_name, int idx = -1); 283 virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1); 284 285 virtual void startup(); 286 287 unsigned int drain(Event *de); 288 289}; 290 291#endif //__MEM_BUS_HH__ 292