xbar.cc revision 9157
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) 2006 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: Ali Saidi 41 * Andreas Hansson 42 * William Wang 43 */ 44 45/** 46 * @file 47 * Definition of a bus object. 48 */ 49 50#include "base/misc.hh" 51#include "base/trace.hh" 52#include "debug/Bus.hh" 53#include "debug/BusAddrRanges.hh" 54#include "debug/Drain.hh" 55#include "mem/bus.hh" 56 57BaseBus::BaseBus(const BaseBusParams *p) 58 : MemObject(p), 59 headerCycles(p->header_cycles), width(p->width), 60 defaultPortID(InvalidPortID), 61 useDefaultRange(p->use_default_range), 62 defaultBlockSize(p->block_size), 63 cachedBlockSize(0), cachedBlockSizeValid(false) 64{ 65 //width, clock period, and header cycles must be positive 66 if (width <= 0) 67 fatal("Bus width must be positive\n"); 68 if (clock <= 0) 69 fatal("Bus clock period must be positive\n"); 70 if (headerCycles <= 0) 71 fatal("Number of header cycles must be positive\n"); 72} 73 74BaseBus::~BaseBus() 75{ 76 for (MasterPortIter m = masterPorts.begin(); m != masterPorts.end(); 77 ++m) { 78 delete *m; 79 } 80 81 for (SlavePortIter s = slavePorts.begin(); s != slavePorts.end(); 82 ++s) { 83 delete *s; 84 } 85} 86 87MasterPort & 88BaseBus::getMasterPort(const std::string &if_name, int idx) 89{ 90 if (if_name == "master" && idx < masterPorts.size()) { 91 // the master port index translates directly to the vector position 92 return *masterPorts[idx]; 93 } else if (if_name == "default") { 94 return *masterPorts[defaultPortID]; 95 } else { 96 return MemObject::getMasterPort(if_name, idx); 97 } 98} 99 100SlavePort & 101BaseBus::getSlavePort(const std::string &if_name, int idx) 102{ 103 if (if_name == "slave" && idx < slavePorts.size()) { 104 // the slave port index translates directly to the vector position 105 return *slavePorts[idx]; 106 } else { 107 return MemObject::getSlavePort(if_name, idx); 108 } 109} 110 111Tick 112BaseBus::calcPacketTiming(PacketPtr pkt) 113{ 114 // determine the current time rounded to the closest following 115 // clock edge 116 Tick now = nextCycle(); 117 118 Tick headerTime = now + headerCycles * clock; 119 120 // The packet will be sent. Figure out how long it occupies the bus, and 121 // how much of that time is for the first "word", aka bus width. 122 int numCycles = 0; 123 if (pkt->hasData()) { 124 // If a packet has data, it needs ceil(size/width) cycles to send it 125 int dataSize = pkt->getSize(); 126 numCycles += dataSize/width; 127 if (dataSize % width) 128 numCycles++; 129 } 130 131 // The first word will be delivered after the current tick, the delivery 132 // of the address if any, and one bus cycle to deliver the data 133 pkt->firstWordTime = headerTime + clock; 134 135 pkt->finishTime = headerTime + numCycles * clock; 136 137 return headerTime; 138} 139 140template <typename PortClass> 141BaseBus::Layer<PortClass>::Layer(BaseBus& _bus, const std::string& _name, 142 Tick _clock) : 143 bus(_bus), _name(_name), state(IDLE), clock(_clock), drainEvent(NULL), 144 releaseEvent(this) 145{ 146} 147 148template <typename PortClass> 149void BaseBus::Layer<PortClass>::occupyLayer(Tick until) 150{ 151 // ensure the state is busy or in retry and never idle at this 152 // point, as the bus should transition from idle as soon as it has 153 // decided to forward the packet to prevent any follow-on calls to 154 // sendTiming seeing an unoccupied bus 155 assert(state != IDLE); 156 157 // note that we do not change the bus state here, if we are going 158 // from idle to busy it is handled by tryTiming, and if we 159 // are in retry we should remain in retry such that 160 // succeededTiming still sees the accurate state 161 162 // until should never be 0 as express snoops never occupy the bus 163 assert(until != 0); 164 bus.schedule(releaseEvent, until); 165 166 DPRINTF(BaseBus, "The bus is now busy from tick %d to %d\n", 167 curTick(), until); 168} 169 170template <typename PortClass> 171bool 172BaseBus::Layer<PortClass>::tryTiming(PortClass* port) 173{ 174 // first we see if the bus is busy, next we check if we are in a 175 // retry with a port other than the current one 176 if (state == BUSY || (state == RETRY && port != retryList.front())) { 177 // put the port at the end of the retry list 178 retryList.push_back(port); 179 return false; 180 } 181 182 // update the state which is shared for request, response and 183 // snoop responses, if we were idle we are now busy, if we are in 184 // a retry, then do not change 185 if (state == IDLE) 186 state = BUSY; 187 188 return true; 189} 190 191template <typename PortClass> 192void 193BaseBus::Layer<PortClass>::succeededTiming(Tick busy_time) 194{ 195 // if a retrying port succeeded, also take it off the retry list 196 if (state == RETRY) { 197 DPRINTF(BaseBus, "Remove retry from list %s\n", 198 retryList.front()->name()); 199 retryList.pop_front(); 200 state = BUSY; 201 } 202 203 // we should either have gone from idle to busy in the 204 // tryTiming test, or just gone from a retry to busy 205 assert(state == BUSY); 206 207 // occupy the bus accordingly 208 occupyLayer(busy_time); 209} 210 211template <typename PortClass> 212void 213BaseBus::Layer<PortClass>::failedTiming(PortClass* port, Tick busy_time) 214{ 215 // if we are not in a retry, i.e. busy (but never idle), or we are 216 // in a retry but not for the current port, then add the port at 217 // the end of the retry list 218 if (state != RETRY || port != retryList.front()) { 219 retryList.push_back(port); 220 } 221 222 // even if we retried the current one and did not succeed, 223 // we are no longer retrying but instead busy 224 state = BUSY; 225 226 // occupy the bus accordingly 227 occupyLayer(busy_time); 228} 229 230template <typename PortClass> 231void 232BaseBus::Layer<PortClass>::releaseLayer() 233{ 234 // releasing the bus means we should now be idle 235 assert(state == BUSY); 236 assert(!releaseEvent.scheduled()); 237 238 // update the state 239 state = IDLE; 240 241 // bus is now idle, so if someone is waiting we can retry 242 if (!retryList.empty()) { 243 // note that we block (return false on recvTiming) both 244 // because the bus is busy and because the destination is 245 // busy, and in the latter case the bus may be released before 246 // we see a retry from the destination 247 retryWaiting(); 248 } else if (drainEvent) { 249 DPRINTF(Drain, "Bus done draining, processing drain event\n"); 250 //If we weren't able to drain before, do it now. 251 drainEvent->process(); 252 // Clear the drain event once we're done with it. 253 drainEvent = NULL; 254 } 255} 256 257template <typename PortClass> 258void 259BaseBus::Layer<PortClass>::retryWaiting() 260{ 261 // this should never be called with an empty retry list 262 assert(!retryList.empty()); 263 264 // we always go to retrying from idle 265 assert(state == IDLE); 266 267 // update the state which is shared for request, response and 268 // snoop responses 269 state = RETRY; 270 271 // note that we might have blocked on the receiving port being 272 // busy (rather than the bus itself) and now call retry before the 273 // destination called retry on the bus 274 retryList.front()->sendRetry(); 275 276 // If the bus is still in the retry state, sendTiming wasn't 277 // called in zero time (e.g. the cache does this) 278 if (state == RETRY) { 279 retryList.pop_front(); 280 281 //Burn a cycle for the missed grant. 282 283 // update the state which is shared for request, response and 284 // snoop responses 285 state = BUSY; 286 287 // determine the current time rounded to the closest following 288 // clock edge 289 Tick now = bus.nextCycle(); 290 291 occupyLayer(now + clock); 292 } 293} 294 295template <typename PortClass> 296void 297BaseBus::Layer<PortClass>::recvRetry() 298{ 299 // we got a retry from a peer that we tried to send something to 300 // and failed, but we sent it on the account of someone else, and 301 // that source port should be on our retry list, however if the 302 // bus layer is released before this happens and the retry (from 303 // the bus point of view) is successful then this no longer holds 304 // and we could in fact have an empty retry list 305 if (retryList.empty()) 306 return; 307 308 // if the bus layer is idle 309 if (state == IDLE) { 310 // note that we do not care who told us to retry at the moment, we 311 // merely let the first one on the retry list go 312 retryWaiting(); 313 } 314} 315 316PortID 317BaseBus::findPort(Addr addr) 318{ 319 /* An interval tree would be a better way to do this. --ali. */ 320 PortID dest_id = checkPortCache(addr); 321 if (dest_id != InvalidPortID) 322 return dest_id; 323 324 // Check normal port ranges 325 PortMapConstIter i = portMap.find(RangeSize(addr,1)); 326 if (i != portMap.end()) { 327 dest_id = i->second; 328 updatePortCache(dest_id, i->first.start, i->first.end); 329 return dest_id; 330 } 331 332 // Check if this matches the default range 333 if (useDefaultRange) { 334 AddrRangeConstIter a_end = defaultRange.end(); 335 for (AddrRangeConstIter i = defaultRange.begin(); i != a_end; i++) { 336 if (*i == addr) { 337 DPRINTF(BusAddrRanges, " found addr %#llx on default\n", 338 addr); 339 return defaultPortID; 340 } 341 } 342 } else if (defaultPortID != InvalidPortID) { 343 DPRINTF(BusAddrRanges, "Unable to find destination for addr %#llx, " 344 "will use default port\n", addr); 345 return defaultPortID; 346 } 347 348 // we should use the range for the default port and it did not 349 // match, or the default port is not set 350 fatal("Unable to find destination for addr %#llx on bus %s\n", addr, 351 name()); 352} 353 354/** Function called by the port when the bus is receiving a range change.*/ 355void 356BaseBus::recvRangeChange(PortID master_port_id) 357{ 358 AddrRangeList ranges; 359 AddrRangeIter iter; 360 361 if (inRecvRangeChange.count(master_port_id)) 362 return; 363 inRecvRangeChange.insert(master_port_id); 364 365 DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", 366 master_port_id); 367 368 clearPortCache(); 369 if (master_port_id == defaultPortID) { 370 defaultRange.clear(); 371 // Only try to update these ranges if the user set a default responder. 372 if (useDefaultRange) { 373 // get the address ranges of the connected slave port 374 AddrRangeList ranges = 375 masterPorts[master_port_id]->getAddrRanges(); 376 for(iter = ranges.begin(); iter != ranges.end(); iter++) { 377 defaultRange.push_back(*iter); 378 DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", 379 iter->start, iter->end); 380 } 381 } 382 } else { 383 384 assert(master_port_id < masterPorts.size() && master_port_id >= 0); 385 MasterPort *port = masterPorts[master_port_id]; 386 387 // Clean out any previously existent ids 388 for (PortMapIter portIter = portMap.begin(); 389 portIter != portMap.end(); ) { 390 if (portIter->second == master_port_id) 391 portMap.erase(portIter++); 392 else 393 portIter++; 394 } 395 396 // get the address ranges of the connected slave port 397 ranges = port->getAddrRanges(); 398 399 for (iter = ranges.begin(); iter != ranges.end(); iter++) { 400 DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", 401 iter->start, iter->end, master_port_id); 402 if (portMap.insert(*iter, master_port_id) == portMap.end()) { 403 PortID conflict_id = portMap.find(*iter)->second; 404 fatal("%s has two ports with same range:\n\t%s\n\t%s\n", 405 name(), 406 masterPorts[master_port_id]->getSlavePort().name(), 407 masterPorts[conflict_id]->getSlavePort().name()); 408 } 409 } 410 } 411 DPRINTF(BusAddrRanges, "port list has %d entries\n", portMap.size()); 412 413 // tell all our neighbouring master ports that our address range 414 // has changed 415 for (SlavePortConstIter p = slavePorts.begin(); p != slavePorts.end(); 416 ++p) 417 (*p)->sendRangeChange(); 418 419 inRecvRangeChange.erase(master_port_id); 420} 421 422AddrRangeList 423BaseBus::getAddrRanges() const 424{ 425 AddrRangeList ranges; 426 427 DPRINTF(BusAddrRanges, "received address range request, returning:\n"); 428 429 for (AddrRangeConstIter dflt_iter = defaultRange.begin(); 430 dflt_iter != defaultRange.end(); dflt_iter++) { 431 ranges.push_back(*dflt_iter); 432 DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start, 433 dflt_iter->end); 434 } 435 for (PortMapConstIter portIter = portMap.begin(); 436 portIter != portMap.end(); portIter++) { 437 bool subset = false; 438 for (AddrRangeConstIter dflt_iter = defaultRange.begin(); 439 dflt_iter != defaultRange.end(); dflt_iter++) { 440 if ((portIter->first.start < dflt_iter->start && 441 portIter->first.end >= dflt_iter->start) || 442 (portIter->first.start < dflt_iter->end && 443 portIter->first.end >= dflt_iter->end)) 444 fatal("Devices can not set ranges that itersect the default set\ 445 but are not a subset of the default set.\n"); 446 if (portIter->first.start >= dflt_iter->start && 447 portIter->first.end <= dflt_iter->end) { 448 subset = true; 449 DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n", 450 portIter->first.start, portIter->first.end); 451 } 452 } 453 if (!subset) { 454 ranges.push_back(portIter->first); 455 DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", 456 portIter->first.start, portIter->first.end); 457 } 458 } 459 460 return ranges; 461} 462 463unsigned 464BaseBus::findBlockSize() 465{ 466 if (cachedBlockSizeValid) 467 return cachedBlockSize; 468 469 unsigned max_bs = 0; 470 471 for (MasterPortConstIter m = masterPorts.begin(); m != masterPorts.end(); 472 ++m) { 473 unsigned tmp_bs = (*m)->peerBlockSize(); 474 if (tmp_bs > max_bs) 475 max_bs = tmp_bs; 476 } 477 478 for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end(); 479 ++s) { 480 unsigned tmp_bs = (*s)->peerBlockSize(); 481 if (tmp_bs > max_bs) 482 max_bs = tmp_bs; 483 } 484 if (max_bs == 0) 485 max_bs = defaultBlockSize; 486 487 if (max_bs != 64) 488 warn_once("Blocksize found to not be 64... hmm... probably not.\n"); 489 cachedBlockSize = max_bs; 490 cachedBlockSizeValid = true; 491 return max_bs; 492} 493 494template <typename PortClass> 495unsigned int 496BaseBus::Layer<PortClass>::drain(Event * de) 497{ 498 //We should check that we're not "doing" anything, and that noone is 499 //waiting. We might be idle but have someone waiting if the device we 500 //contacted for a retry didn't actually retry. 501 if (!retryList.empty() || state != IDLE) { 502 DPRINTF(Drain, "Bus not drained\n"); 503 drainEvent = de; 504 return 1; 505 } 506 return 0; 507} 508 509/** 510 * Bus layer template instantiations. Could be removed with _impl.hh 511 * file, but since there are only two given options (MasterPort and 512 * SlavePort) it seems a bit excessive at this point. 513 */ 514template class BaseBus::Layer<SlavePort>; 515template class BaseBus::Layer<MasterPort>; 516