xbar.cc revision 9547
1/* 2 * Copyright (c) 2011-2013 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 gotAddrRanges(p->port_default_connection_count + 61 p->port_master_connection_count, false), 62 gotAllAddrRanges(false), defaultPortID(InvalidPortID), 63 useDefaultRange(p->use_default_range), 64 blockSize(p->block_size) 65{} 66 67BaseBus::~BaseBus() 68{ 69 for (MasterPortIter m = masterPorts.begin(); m != masterPorts.end(); 70 ++m) { 71 delete *m; 72 } 73 74 for (SlavePortIter s = slavePorts.begin(); s != slavePorts.end(); 75 ++s) { 76 delete *s; 77 } 78} 79 80void 81BaseBus::init() 82{ 83 // determine the maximum peer block size, look at both the 84 // connected master and slave modules 85 uint32_t peer_block_size = 0; 86 87 for (MasterPortConstIter m = masterPorts.begin(); m != masterPorts.end(); 88 ++m) { 89 peer_block_size = std::max((*m)->peerBlockSize(), peer_block_size); 90 } 91 92 for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end(); 93 ++s) { 94 peer_block_size = std::max((*s)->peerBlockSize(), peer_block_size); 95 } 96 97 // if the peers do not have a block size, use the default value 98 // set through the bus parameters 99 if (peer_block_size != 0) 100 blockSize = peer_block_size; 101 102 // check if the block size is a value known to work 103 if (!(blockSize == 16 || blockSize == 32 || blockSize == 64 || 104 blockSize == 128)) 105 warn_once("Block size is neither 16, 32, 64 or 128 bytes.\n"); 106} 107 108BaseMasterPort & 109BaseBus::getMasterPort(const std::string &if_name, PortID idx) 110{ 111 if (if_name == "master" && idx < masterPorts.size()) { 112 // the master port index translates directly to the vector position 113 return *masterPorts[idx]; 114 } else if (if_name == "default") { 115 return *masterPorts[defaultPortID]; 116 } else { 117 return MemObject::getMasterPort(if_name, idx); 118 } 119} 120 121BaseSlavePort & 122BaseBus::getSlavePort(const std::string &if_name, PortID idx) 123{ 124 if (if_name == "slave" && idx < slavePorts.size()) { 125 // the slave port index translates directly to the vector position 126 return *slavePorts[idx]; 127 } else { 128 return MemObject::getSlavePort(if_name, idx); 129 } 130} 131 132void 133BaseBus::calcPacketTiming(PacketPtr pkt) 134{ 135 // the bus will be called at a time that is not necessarily 136 // coinciding with its own clock, so start by determining how long 137 // until the next clock edge (could be zero) 138 Tick offset = nextCycle() - curTick(); 139 140 // determine how many cycles are needed to send the data 141 unsigned dataCycles = pkt->hasData() ? divCeil(pkt->getSize(), width) : 0; 142 143 // The first word will be delivered on the cycle after the header. 144 pkt->busFirstWordDelay = (headerCycles + 1) * clockPeriod() + offset; 145 146 // Note that currently busLastWordDelay can be smaller than 147 // busFirstWordDelay if the packet has no data 148 pkt->busLastWordDelay = (headerCycles + dataCycles) * clockPeriod() + 149 offset; 150} 151 152template <typename PortClass> 153BaseBus::Layer<PortClass>::Layer(BaseBus& _bus, const std::string& _name) : 154 Drainable(), 155 bus(_bus), _name(_name), state(IDLE), drainManager(NULL), 156 releaseEvent(this) 157{ 158} 159 160template <typename PortClass> 161void BaseBus::Layer<PortClass>::occupyLayer(Tick until) 162{ 163 // ensure the state is busy or in retry and never idle at this 164 // point, as the bus should transition from idle as soon as it has 165 // decided to forward the packet to prevent any follow-on calls to 166 // sendTiming seeing an unoccupied bus 167 assert(state != IDLE); 168 169 // note that we do not change the bus state here, if we are going 170 // from idle to busy it is handled by tryTiming, and if we 171 // are in retry we should remain in retry such that 172 // succeededTiming still sees the accurate state 173 174 // until should never be 0 as express snoops never occupy the bus 175 assert(until != 0); 176 bus.schedule(releaseEvent, until); 177 178 DPRINTF(BaseBus, "The bus is now busy from tick %d to %d\n", 179 curTick(), until); 180} 181 182template <typename PortClass> 183bool 184BaseBus::Layer<PortClass>::tryTiming(PortClass* port) 185{ 186 // first we see if the bus is busy, next we check if we are in a 187 // retry with a port other than the current one 188 if (state == BUSY || (state == RETRY && port != retryList.front())) { 189 // put the port at the end of the retry list 190 retryList.push_back(port); 191 return false; 192 } 193 194 // update the state which is shared for request, response and 195 // snoop responses, if we were idle we are now busy, if we are in 196 // a retry, then do not change 197 if (state == IDLE) 198 state = BUSY; 199 200 return true; 201} 202 203template <typename PortClass> 204void 205BaseBus::Layer<PortClass>::succeededTiming(Tick busy_time) 206{ 207 // if a retrying port succeeded, also take it off the retry list 208 if (state == RETRY) { 209 DPRINTF(BaseBus, "Remove retry from list %s\n", 210 retryList.front()->name()); 211 retryList.pop_front(); 212 state = BUSY; 213 } 214 215 // we should either have gone from idle to busy in the 216 // tryTiming test, or just gone from a retry to busy 217 assert(state == BUSY); 218 219 // occupy the bus accordingly 220 occupyLayer(busy_time); 221} 222 223template <typename PortClass> 224void 225BaseBus::Layer<PortClass>::failedTiming(PortClass* port, Tick busy_time) 226{ 227 // if we are not in a retry, i.e. busy (but never idle), or we are 228 // in a retry but not for the current port, then add the port at 229 // the end of the retry list 230 if (state != RETRY || port != retryList.front()) { 231 retryList.push_back(port); 232 } 233 234 // even if we retried the current one and did not succeed, 235 // we are no longer retrying but instead busy 236 state = BUSY; 237 238 // occupy the bus accordingly 239 occupyLayer(busy_time); 240} 241 242template <typename PortClass> 243void 244BaseBus::Layer<PortClass>::releaseLayer() 245{ 246 // releasing the bus means we should now be idle 247 assert(state == BUSY); 248 assert(!releaseEvent.scheduled()); 249 250 // update the state 251 state = IDLE; 252 253 // bus is now idle, so if someone is waiting we can retry 254 if (!retryList.empty()) { 255 // note that we block (return false on recvTiming) both 256 // because the bus is busy and because the destination is 257 // busy, and in the latter case the bus may be released before 258 // we see a retry from the destination 259 retryWaiting(); 260 } else if (drainManager) { 261 DPRINTF(Drain, "Bus done draining, signaling drain manager\n"); 262 //If we weren't able to drain before, do it now. 263 drainManager->signalDrainDone(); 264 // Clear the drain event once we're done with it. 265 drainManager = NULL; 266 } 267} 268 269template <typename PortClass> 270void 271BaseBus::Layer<PortClass>::retryWaiting() 272{ 273 // this should never be called with an empty retry list 274 assert(!retryList.empty()); 275 276 // we always go to retrying from idle 277 assert(state == IDLE); 278 279 // update the state which is shared for request, response and 280 // snoop responses 281 state = RETRY; 282 283 // note that we might have blocked on the receiving port being 284 // busy (rather than the bus itself) and now call retry before the 285 // destination called retry on the bus 286 retryList.front()->sendRetry(); 287 288 // If the bus is still in the retry state, sendTiming wasn't 289 // called in zero time (e.g. the cache does this) 290 if (state == RETRY) { 291 retryList.pop_front(); 292 293 //Burn a cycle for the missed grant. 294 295 // update the state which is shared for request, response and 296 // snoop responses 297 state = BUSY; 298 299 // occupy the bus layer until the next cycle ends 300 occupyLayer(bus.clockEdge(Cycles(1))); 301 } 302} 303 304template <typename PortClass> 305void 306BaseBus::Layer<PortClass>::recvRetry() 307{ 308 // we got a retry from a peer that we tried to send something to 309 // and failed, but we sent it on the account of someone else, and 310 // that source port should be on our retry list, however if the 311 // bus layer is released before this happens and the retry (from 312 // the bus point of view) is successful then this no longer holds 313 // and we could in fact have an empty retry list 314 if (retryList.empty()) 315 return; 316 317 // if the bus layer is idle 318 if (state == IDLE) { 319 // note that we do not care who told us to retry at the moment, we 320 // merely let the first one on the retry list go 321 retryWaiting(); 322 } 323} 324 325PortID 326BaseBus::findPort(Addr addr) 327{ 328 // we should never see any address lookups before we've got the 329 // ranges of all connected slave modules 330 assert(gotAllAddrRanges); 331 332 // Check the cache 333 PortID dest_id = checkPortCache(addr); 334 if (dest_id != InvalidPortID) 335 return dest_id; 336 337 // Check the address map interval tree 338 PortMapConstIter i = portMap.find(addr); 339 if (i != portMap.end()) { 340 dest_id = i->second; 341 updatePortCache(dest_id, i->first); 342 return dest_id; 343 } 344 345 // Check if this matches the default range 346 if (useDefaultRange) { 347 if (defaultRange.contains(addr)) { 348 DPRINTF(BusAddrRanges, " found addr %#llx on default\n", 349 addr); 350 return defaultPortID; 351 } 352 } else if (defaultPortID != InvalidPortID) { 353 DPRINTF(BusAddrRanges, "Unable to find destination for addr %#llx, " 354 "will use default port\n", addr); 355 return defaultPortID; 356 } 357 358 // we should use the range for the default port and it did not 359 // match, or the default port is not set 360 fatal("Unable to find destination for addr %#llx on bus %s\n", addr, 361 name()); 362} 363 364/** Function called by the port when the bus is receiving a range change.*/ 365void 366BaseBus::recvRangeChange(PortID master_port_id) 367{ 368 DPRINTF(BusAddrRanges, "Received range change from slave port %s\n", 369 masterPorts[master_port_id]->getSlavePort().name()); 370 371 // remember that we got a range from this master port and thus the 372 // connected slave module 373 gotAddrRanges[master_port_id] = true; 374 375 // update the global flag 376 if (!gotAllAddrRanges) { 377 // take a logical AND of all the ports and see if we got 378 // ranges from everyone 379 gotAllAddrRanges = true; 380 std::vector<bool>::const_iterator r = gotAddrRanges.begin(); 381 while (gotAllAddrRanges && r != gotAddrRanges.end()) { 382 gotAllAddrRanges &= *r++; 383 } 384 if (gotAllAddrRanges) 385 DPRINTF(BusAddrRanges, "Got address ranges from all slaves\n"); 386 } 387 388 // note that we could get the range from the default port at any 389 // point in time, and we cannot assume that the default range is 390 // set before the other ones are, so we do additional checks once 391 // all ranges are provided 392 if (master_port_id == defaultPortID) { 393 // only update if we are indeed checking ranges for the 394 // default port since the port might not have a valid range 395 // otherwise 396 if (useDefaultRange) { 397 AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges(); 398 399 if (ranges.size() != 1) 400 fatal("Bus %s may only have a single default range", 401 name()); 402 403 defaultRange = ranges.front(); 404 } 405 } else { 406 // the ports are allowed to update their address ranges 407 // dynamically, so remove any existing entries 408 if (gotAddrRanges[master_port_id]) { 409 for (PortMapIter p = portMap.begin(); p != portMap.end(); ) { 410 if (p->second == master_port_id) 411 // erasing invalidates the iterator, so advance it 412 // before the deletion takes place 413 portMap.erase(p++); 414 else 415 p++; 416 } 417 } 418 419 AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges(); 420 421 for (AddrRangeConstIter r = ranges.begin(); r != ranges.end(); ++r) { 422 DPRINTF(BusAddrRanges, "Adding range %s for id %d\n", 423 r->to_string(), master_port_id); 424 if (portMap.insert(*r, master_port_id) == portMap.end()) { 425 PortID conflict_id = portMap.find(*r)->second; 426 fatal("%s has two ports with same range:\n\t%s\n\t%s\n", 427 name(), 428 masterPorts[master_port_id]->getSlavePort().name(), 429 masterPorts[conflict_id]->getSlavePort().name()); 430 } 431 } 432 } 433 434 // if we have received ranges from all our neighbouring slave 435 // modules, go ahead and tell our connected master modules in 436 // turn, this effectively assumes a tree structure of the system 437 if (gotAllAddrRanges) { 438 // also check that no range partially overlaps with the 439 // default range, this has to be done after all ranges are set 440 // as there are no guarantees for when the default range is 441 // update with respect to the other ones 442 if (useDefaultRange) { 443 for (PortID port_id = 0; port_id < masterPorts.size(); ++port_id) { 444 if (port_id == defaultPortID) { 445 if (!gotAddrRanges[port_id]) 446 fatal("Bus %s uses default range, but none provided", 447 name()); 448 } else { 449 AddrRangeList ranges = 450 masterPorts[port_id]->getAddrRanges(); 451 452 for (AddrRangeConstIter r = ranges.begin(); 453 r != ranges.end(); ++r) { 454 // see if the new range is partially 455 // overlapping the default range 456 if (r->intersects(defaultRange) && 457 !r->isSubset(defaultRange)) 458 fatal("Range %s intersects the " \ 459 "default range of %s but is not a " \ 460 "subset\n", r->to_string(), name()); 461 } 462 } 463 } 464 } 465 466 // tell all our neighbouring master ports that our address 467 // ranges have changed 468 for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end(); 469 ++s) 470 (*s)->sendRangeChange(); 471 } 472 473 clearPortCache(); 474} 475 476AddrRangeList 477BaseBus::getAddrRanges() const 478{ 479 // we should never be asked without first having sent a range 480 // change, and the latter is only done once we have all the ranges 481 // of the connected devices 482 assert(gotAllAddrRanges); 483 484 // at the moment, this never happens, as there are no cycles in 485 // the range queries and no devices on the master side of a bus 486 // (CPU, cache, bridge etc) actually care about the ranges of the 487 // ports they are connected to 488 489 DPRINTF(BusAddrRanges, "Received address range request, returning:\n"); 490 491 // start out with the default range 492 AddrRangeList ranges; 493 if (useDefaultRange) { 494 ranges.push_back(defaultRange); 495 DPRINTF(BusAddrRanges, " -- Default %s\n", defaultRange.to_string()); 496 } 497 498 // add any range that is not a subset of the default range 499 for (PortMapConstIter p = portMap.begin(); p != portMap.end(); ++p) { 500 if (useDefaultRange && p->first.isSubset(defaultRange)) { 501 DPRINTF(BusAddrRanges, " -- %s is a subset of default\n", 502 p->first.to_string()); 503 } else { 504 ranges.push_back(p->first); 505 DPRINTF(BusAddrRanges, " -- %s\n", p->first.to_string()); 506 } 507 } 508 509 return ranges; 510} 511 512unsigned 513BaseBus::deviceBlockSize() const 514{ 515 return blockSize; 516} 517 518template <typename PortClass> 519unsigned int 520BaseBus::Layer<PortClass>::drain(DrainManager *dm) 521{ 522 //We should check that we're not "doing" anything, and that noone is 523 //waiting. We might be idle but have someone waiting if the device we 524 //contacted for a retry didn't actually retry. 525 if (!retryList.empty() || state != IDLE) { 526 DPRINTF(Drain, "Bus not drained\n"); 527 drainManager = dm; 528 return 1; 529 } 530 return 0; 531} 532 533/** 534 * Bus layer template instantiations. Could be removed with _impl.hh 535 * file, but since there are only two given options (MasterPort and 536 * SlavePort) it seems a bit excessive at this point. 537 */ 538template class BaseBus::Layer<SlavePort>; 539template class BaseBus::Layer<MasterPort>; 540