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