xbar.cc revision 9093
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/intmath.hh" 51#include "base/misc.hh" 52#include "base/trace.hh" 53#include "debug/Bus.hh" 54#include "debug/BusAddrRanges.hh" 55#include "mem/bus.hh" 56 57BaseBus::BaseBus(const BaseBusParams *p) 58 : MemObject(p), clock(p->clock), 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 = divCeil(curTick(), clock) * clock; 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 //If we weren't able to drain before, do it now. 250 drainEvent->process(); 251 // Clear the drain event once we're done with it. 252 drainEvent = NULL; 253 } 254} 255 256template <typename PortClass> 257void 258BaseBus::Layer<PortClass>::retryWaiting() 259{ 260 // this should never be called with an empty retry list 261 assert(!retryList.empty()); 262 263 // we always go to retrying from idle 264 assert(state == IDLE); 265 266 // update the state which is shared for request, response and 267 // snoop responses 268 state = RETRY; 269 270 // note that we might have blocked on the receiving port being 271 // busy (rather than the bus itself) and now call retry before the 272 // destination called retry on the bus 273 retryList.front()->sendRetry(); 274 275 // If the bus is still in the retry state, sendTiming wasn't 276 // called in zero time (e.g. the cache does this) 277 if (state == RETRY) { 278 retryList.pop_front(); 279 280 //Burn a cycle for the missed grant. 281 282 // update the state which is shared for request, response and 283 // snoop responses 284 state = BUSY; 285 286 // determine the current time rounded to the closest following 287 // clock edge 288 Tick now = divCeil(curTick(), clock) * clock; 289 290 occupyLayer(now + clock); 291 } 292} 293 294template <typename PortClass> 295void 296BaseBus::Layer<PortClass>::recvRetry() 297{ 298 // we got a retry from a peer that we tried to send something to 299 // and failed, but we sent it on the account of someone else, and 300 // that source port should be on our retry list, however if the 301 // bus layer is released before this happens and the retry (from 302 // the bus point of view) is successful then this no longer holds 303 // and we could in fact have an empty retry list 304 if (retryList.empty()) 305 return; 306 307 // if the bus layer is idle 308 if (state == IDLE) { 309 // note that we do not care who told us to retry at the moment, we 310 // merely let the first one on the retry list go 311 retryWaiting(); 312 } 313} 314 315PortID 316BaseBus::findPort(Addr addr) 317{ 318 /* An interval tree would be a better way to do this. --ali. */ 319 PortID dest_id = checkPortCache(addr); 320 if (dest_id != InvalidPortID) 321 return dest_id; 322 323 // Check normal port ranges 324 PortMapConstIter i = portMap.find(RangeSize(addr,1)); 325 if (i != portMap.end()) { 326 dest_id = i->second; 327 updatePortCache(dest_id, i->first.start, i->first.end); 328 return dest_id; 329 } 330 331 // Check if this matches the default range 332 if (useDefaultRange) { 333 AddrRangeConstIter a_end = defaultRange.end(); 334 for (AddrRangeConstIter i = defaultRange.begin(); i != a_end; i++) { 335 if (*i == addr) { 336 DPRINTF(BusAddrRanges, " found addr %#llx on default\n", 337 addr); 338 return defaultPortID; 339 } 340 } 341 } else if (defaultPortID != InvalidPortID) { 342 DPRINTF(BusAddrRanges, "Unable to find destination for addr %#llx, " 343 "will use default port\n", addr); 344 return defaultPortID; 345 } 346 347 // we should use the range for the default port and it did not 348 // match, or the default port is not set 349 fatal("Unable to find destination for addr %#llx on bus %s\n", addr, 350 name()); 351} 352 353/** Function called by the port when the bus is receiving a range change.*/ 354void 355BaseBus::recvRangeChange(PortID master_port_id) 356{ 357 AddrRangeList ranges; 358 AddrRangeIter iter; 359 360 if (inRecvRangeChange.count(master_port_id)) 361 return; 362 inRecvRangeChange.insert(master_port_id); 363 364 DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", 365 master_port_id); 366 367 clearPortCache(); 368 if (master_port_id == defaultPortID) { 369 defaultRange.clear(); 370 // Only try to update these ranges if the user set a default responder. 371 if (useDefaultRange) { 372 // get the address ranges of the connected slave port 373 AddrRangeList ranges = 374 masterPorts[master_port_id]->getAddrRanges(); 375 for(iter = ranges.begin(); iter != ranges.end(); iter++) { 376 defaultRange.push_back(*iter); 377 DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", 378 iter->start, iter->end); 379 } 380 } 381 } else { 382 383 assert(master_port_id < masterPorts.size() && master_port_id >= 0); 384 MasterPort *port = masterPorts[master_port_id]; 385 386 // Clean out any previously existent ids 387 for (PortMapIter portIter = portMap.begin(); 388 portIter != portMap.end(); ) { 389 if (portIter->second == master_port_id) 390 portMap.erase(portIter++); 391 else 392 portIter++; 393 } 394 395 // get the address ranges of the connected slave port 396 ranges = port->getAddrRanges(); 397 398 for (iter = ranges.begin(); iter != ranges.end(); iter++) { 399 DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", 400 iter->start, iter->end, master_port_id); 401 if (portMap.insert(*iter, master_port_id) == portMap.end()) { 402 PortID conflict_id = portMap.find(*iter)->second; 403 fatal("%s has two ports with same range:\n\t%s\n\t%s\n", 404 name(), 405 masterPorts[master_port_id]->getSlavePort().name(), 406 masterPorts[conflict_id]->getSlavePort().name()); 407 } 408 } 409 } 410 DPRINTF(BusAddrRanges, "port list has %d entries\n", portMap.size()); 411 412 // tell all our neighbouring master ports that our address range 413 // has changed 414 for (SlavePortConstIter p = slavePorts.begin(); p != slavePorts.end(); 415 ++p) 416 (*p)->sendRangeChange(); 417 418 inRecvRangeChange.erase(master_port_id); 419} 420 421AddrRangeList 422BaseBus::getAddrRanges() const 423{ 424 AddrRangeList ranges; 425 426 DPRINTF(BusAddrRanges, "received address range request, returning:\n"); 427 428 for (AddrRangeConstIter dflt_iter = defaultRange.begin(); 429 dflt_iter != defaultRange.end(); dflt_iter++) { 430 ranges.push_back(*dflt_iter); 431 DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start, 432 dflt_iter->end); 433 } 434 for (PortMapConstIter portIter = portMap.begin(); 435 portIter != portMap.end(); portIter++) { 436 bool subset = false; 437 for (AddrRangeConstIter dflt_iter = defaultRange.begin(); 438 dflt_iter != defaultRange.end(); dflt_iter++) { 439 if ((portIter->first.start < dflt_iter->start && 440 portIter->first.end >= dflt_iter->start) || 441 (portIter->first.start < dflt_iter->end && 442 portIter->first.end >= dflt_iter->end)) 443 fatal("Devices can not set ranges that itersect the default set\ 444 but are not a subset of the default set.\n"); 445 if (portIter->first.start >= dflt_iter->start && 446 portIter->first.end <= dflt_iter->end) { 447 subset = true; 448 DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n", 449 portIter->first.start, portIter->first.end); 450 } 451 } 452 if (!subset) { 453 ranges.push_back(portIter->first); 454 DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", 455 portIter->first.start, portIter->first.end); 456 } 457 } 458 459 return ranges; 460} 461 462unsigned 463BaseBus::findBlockSize() 464{ 465 if (cachedBlockSizeValid) 466 return cachedBlockSize; 467 468 unsigned max_bs = 0; 469 470 for (MasterPortConstIter m = masterPorts.begin(); m != masterPorts.end(); 471 ++m) { 472 unsigned tmp_bs = (*m)->peerBlockSize(); 473 if (tmp_bs > max_bs) 474 max_bs = tmp_bs; 475 } 476 477 for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end(); 478 ++s) { 479 unsigned tmp_bs = (*s)->peerBlockSize(); 480 if (tmp_bs > max_bs) 481 max_bs = tmp_bs; 482 } 483 if (max_bs == 0) 484 max_bs = defaultBlockSize; 485 486 if (max_bs != 64) 487 warn_once("Blocksize found to not be 64... hmm... probably not.\n"); 488 cachedBlockSize = max_bs; 489 cachedBlockSizeValid = true; 490 return max_bs; 491} 492 493template <typename PortClass> 494unsigned int 495BaseBus::Layer<PortClass>::drain(Event * de) 496{ 497 //We should check that we're not "doing" anything, and that noone is 498 //waiting. We might be idle but have someone waiting if the device we 499 //contacted for a retry didn't actually retry. 500 if (!retryList.empty() || state != IDLE) { 501 drainEvent = de; 502 return 1; 503 } 504 return 0; 505} 506 507/** 508 * Bus layer template instantiations. Could be removed with _impl.hh 509 * file, but since there are only two given options (MasterPort and 510 * SlavePort) it seems a bit excessive at this point. 511 */ 512template class BaseBus::Layer<SlavePort>; 513template class BaseBus::Layer<MasterPort>; 514