xbar.cc revision 8851
17513SN/A/* 27513SN/A * Copyright (c) 2011-2012 ARM Limited 37513SN/A * All rights reserved 410036SN/A * 58835SN/A * The license below extends only to copyright in the software and shall 610036SN/A * not be construed as granting a license to any other intellectual 77935SN/A * property including but not limited to intellectual property relating 87935SN/A * to a hardware implementation of the functionality of the software 97935SN/A * licensed hereunder. You may use the software subject to the license 107513SN/A * terms below provided that you ensure that this notice is replicated 117513SN/A * unmodified and in its entirety in all distributions of the software, 127513SN/A * modified or unmodified, in source code or in binary form. 1310315SN/A * 148835SN/A * Copyright (c) 2006 The Regents of The University of Michigan 159885SN/A * All rights reserved. 169885SN/A * 1711570SCurtis.Dunham@arm.com * Redistribution and use in source and binary forms, with or without 1810036SN/A * modification, are permitted provided that the following conditions are 1911312Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 208835SN/A * notice, this list of conditions and the following disclaimer; 218835SN/A * redistributions in binary form must reproduce the above copyright 2210315SN/A * notice, this list of conditions and the following disclaimer in the 238835SN/A * documentation and/or other materials provided with the distribution; 2410038SN/A * neither the name of the copyright holders nor the names of its 257513SN/A * contributors may be used to endorse or promote products derived from 269481SN/A * this software without specific prior written permission. 278721SN/A * 2811066Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2911219Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 308721SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3111570SCurtis.Dunham@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3211570SCurtis.Dunham@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3311570SCurtis.Dunham@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3411570SCurtis.Dunham@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 358835SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 368835SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3711440SCurtis.Dunham@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3811440SCurtis.Dunham@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 397935SN/A * 407935SN/A * Authors: Ali Saidi 417935SN/A * Andreas Hansson 427935SN/A */ 437935SN/A 447935SN/A/** 457935SN/A * @file 468893SN/A * Definition of a bus object. 477513SN/A */ 489885SN/A 499885SN/A#include "base/misc.hh" 509885SN/A#include "base/trace.hh" 5110315SN/A#include "debug/Bus.hh" 5210036SN/A#include "debug/BusAddrRanges.hh" 5310315SN/A#include "debug/MMU.hh" 549885SN/A#include "mem/bus.hh" 559885SN/A 567513SN/ABus::Bus(const BusParams *p) 577513SN/A : MemObject(p), busId(p->bus_id), clock(p->clock), 5810038SN/A headerCycles(p->header_cycles), width(p->width), tickNextIdle(0), 5910315SN/A drainEvent(NULL), busIdle(this), inRetry(false), 607513SN/A nbrMasterPorts(p->port_master_connection_count), 619885SN/A defaultPortId(INVALID_PORT_ID), useDefaultRange(p->use_default_range), 627513SN/A defaultBlockSize(p->block_size), 6311570SCurtis.Dunham@arm.com cachedBlockSize(0), cachedBlockSizeValid(false) 647513SN/A{ 658835SN/A //width, clock period, and header cycles must be positive 667513SN/A if (width <= 0) 6710038SN/A fatal("Bus width must be positive\n"); 687513SN/A if (clock <= 0) 6910036SN/A fatal("Bus clock period must be positive\n"); 708983SN/A if (headerCycles <= 0) 717513SN/A fatal("Number of header cycles must be positive\n"); 727513SN/A 738835SN/A // create the ports based on the size of the master and slave 749481SN/A // vector ports, and the presence of the default master 7510038SN/A 767513SN/A // id used to index into interfaces which is a flat vector of all 777513SN/A // ports 787513SN/A int id = 0; 797513SN/A for (int i = 0; i < p->port_master_connection_count; ++i) { 807513SN/A std::string portName = csprintf("%s-p%d", name(), id); 817513SN/A interfaces.push_back(new BusPort(portName, this, id)); 8211570SCurtis.Dunham@arm.com ++id; 8311570SCurtis.Dunham@arm.com } 8411570SCurtis.Dunham@arm.com 8511570SCurtis.Dunham@arm.com // note that the first slave port is now stored on index 868835SN/A // nbrMasterPorts in the vector 877513SN/A for (int i = 0; i < p->port_slave_connection_count; ++i) { 889885SN/A std::string portName = csprintf("%s-p%d", name(), id); 897513SN/A interfaces.push_back(new BusPort(portName, this, id)); 907513SN/A ++id; 9110315SN/A } 929481SN/A 9311960Sgabeblack@google.com // see if we have a default master connected and if so add the 947513SN/A // port at the end 957513SN/A if (p->port_default_connection_count) { 967513SN/A defaultPortId = id; 977513SN/A std::string portName = csprintf("%s-default", name()); 988893SN/A interfaces.push_back(new BusPort(portName, this, id)); 998893SN/A ++id; 1007513SN/A } 10110038SN/A 10210038SN/A clearPortCache(); 10310038SN/A} 10410038SN/A 10510038SN/APort * 10611066Snilay@cs.wisc.eduBus::getPort(const std::string &if_name, int idx) 10710038SN/A{ 10810038SN/A if (if_name == "master") { 10910038SN/A // the master index translates directly to the interfaces 11010038SN/A // vector as they are stored first 11110038SN/A return interfaces[idx]; 11210038SN/A } else if (if_name == "slave") { 11310038SN/A // the slaves are stored after the masters and we must thus 11410038SN/A // offset the slave index with the number of master ports 11510038SN/A return interfaces[nbrMasterPorts + idx]; 11610038SN/A } else if (if_name == "default") { 11710038SN/A return interfaces[defaultPortId]; 11810038SN/A } else { 11910038SN/A panic("No port %s %d on bus %s\n", if_name, idx, name()); 12011570SCurtis.Dunham@arm.com } 12110038SN/A} 12210038SN/A 12310038SN/Avoid 12411570SCurtis.Dunham@arm.comBus::init() 12511570SCurtis.Dunham@arm.com{ 12611570SCurtis.Dunham@arm.com std::vector<BusPort*>::iterator intIter; 12711570SCurtis.Dunham@arm.com 12810038SN/A // iterate over our interfaces and determine which of our neighbours 12910038SN/A // are snooping and add them as snoopers 1307513SN/A for (intIter = interfaces.begin(); intIter != interfaces.end(); 1317513SN/A intIter++) { 1328835SN/A if ((*intIter)->getPeer()->isSnooping()) { 13310036SN/A DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n", 13410038SN/A (*intIter)->getPeer()->name()); 1357513SN/A snoopPorts.push_back(*intIter); 1368835SN/A } 1378835SN/A } 1388835SN/A} 1398835SN/A 1409885SN/ABus::BusFreeEvent::BusFreeEvent(Bus *_bus) 14111570SCurtis.Dunham@arm.com : bus(_bus) 14210036SN/A{} 14310038SN/A 1449265SN/Avoid 14511570SCurtis.Dunham@arm.comBus::BusFreeEvent::process() 14611570SCurtis.Dunham@arm.com{ 14711570SCurtis.Dunham@arm.com bus->recvRetry(-1); 14811570SCurtis.Dunham@arm.com} 1498835SN/A 1508893SN/Aconst char * 1518835SN/ABus::BusFreeEvent::description() const 1528835SN/A{ 1538835SN/A return "bus became available"; 15410036SN/A} 1557513SN/A 1569481SN/ATick 1579481SN/ABus::calcPacketTiming(PacketPtr pkt) 15811219Snilay@cs.wisc.edu{ 15910036SN/A // Bring tickNextIdle up to the present tick. 1609481SN/A // There is some potential ambiguity where a cycle starts, which 16110038SN/A // might make a difference when devices are acting right around a 16210038SN/A // cycle boundary. Using a < allows things which happen exactly on 16310038SN/A // a cycle boundary to take up only the following cycle. Anything 16410038SN/A // that happens later will have to "wait" for the end of that 16510038SN/A // cycle, and then start using the bus after that. 16610038SN/A if (tickNextIdle < curTick()) { 16710038SN/A tickNextIdle = curTick(); 16810038SN/A if (tickNextIdle % clock != 0) 1699481SN/A tickNextIdle = curTick() - (curTick() % clock) + clock; 1709481SN/A } 1719481SN/A 1729481SN/A Tick headerTime = tickNextIdle + headerCycles * clock; 1739481SN/A 1749481SN/A // The packet will be sent. Figure out how long it occupies the bus, and 17510038SN/A // how much of that time is for the first "word", aka bus width. 1769481SN/A int numCycles = 0; 1779481SN/A if (pkt->hasData()) { 17810038SN/A // If a packet has data, it needs ceil(size/width) cycles to send it 17910038SN/A int dataSize = pkt->getSize(); 18011066Snilay@cs.wisc.edu numCycles += dataSize/width; 18110038SN/A if (dataSize % width) 18210038SN/A numCycles++; 18310038SN/A } 18410038SN/A 18510038SN/A // The first word will be delivered after the current tick, the delivery 18610038SN/A // of the address if any, and one bus cycle to deliver the data 18710038SN/A pkt->firstWordTime = headerTime + clock; 18811066Snilay@cs.wisc.edu 18910038SN/A pkt->finishTime = headerTime + numCycles * clock; 19010038SN/A 19110038SN/A return headerTime; 19210038SN/A} 19310038SN/A 19410038SN/Avoid Bus::occupyBus(Tick until) 19510038SN/A{ 19610038SN/A if (until == 0) { 19710038SN/A // shortcut for express snoop packets 19810038SN/A return; 19910038SN/A } 20010038SN/A 20110038SN/A tickNextIdle = until; 20211570SCurtis.Dunham@arm.com reschedule(busIdle, tickNextIdle, true); 20310038SN/A 20410038SN/A DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n", 20510038SN/A curTick(), tickNextIdle); 20611570SCurtis.Dunham@arm.com} 20711570SCurtis.Dunham@arm.com 20811570SCurtis.Dunham@arm.com/** Function called by the port when the bus is receiving a Timing 20911570SCurtis.Dunham@arm.com * transaction.*/ 21010038SN/Abool 2119481SN/ABus::recvTiming(PacketPtr pkt) 2127513SN/A{ 2137513SN/A short src = pkt->getSrc(); 2148835SN/A 21510036SN/A BusPort *src_port = interfaces[src]; 21610038SN/A 2177513SN/A // If the bus is busy, or other devices are in line ahead of the current 2188835SN/A // one, put this device on the retry list. 2198835SN/A if (!pkt->isExpressSnoop() && 2208835SN/A (tickNextIdle > curTick() || 2218835SN/A (retryList.size() && (!inRetry || src_port != retryList.front())))) 2229885SN/A { 22311570SCurtis.Dunham@arm.com addToRetryList(src_port); 22410036SN/A DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x BUSY\n", 22510038SN/A src, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); 2269265SN/A return false; 22711570SCurtis.Dunham@arm.com } 22811570SCurtis.Dunham@arm.com 22911570SCurtis.Dunham@arm.com DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x\n", 23011570SCurtis.Dunham@arm.com src, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); 2318835SN/A 2328893SN/A Tick headerFinishTime = pkt->isExpressSnoop() ? 0 : calcPacketTiming(pkt); 2337513SN/A Tick packetFinishTime = pkt->isExpressSnoop() ? 0 : pkt->finishTime; 2347513SN/A 2357513SN/A short dest = pkt->getDest(); 23610036SN/A int dest_port_id; 2377513SN/A Port *dest_port; 2387513SN/A 23911960Sgabeblack@google.com if (dest == Packet::Broadcast) { 2407513SN/A dest_port_id = findPort(pkt->getAddr()); 24111066Snilay@cs.wisc.edu dest_port = interfaces[dest_port_id]; 24211066Snilay@cs.wisc.edu SnoopIter s_end = snoopPorts.end(); 2437513SN/A for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { 2447513SN/A BusPort *p = *s_iter; 2457513SN/A if (p != dest_port && p != src_port) { 2467513SN/A // cache is not allowed to refuse snoop 24710036SN/A bool success M5_VAR_USED = p->sendTiming(pkt); 24811960Sgabeblack@google.com assert(success); 2497513SN/A } 2507513SN/A } 25111066Snilay@cs.wisc.edu } else { 25211960Sgabeblack@google.com assert(dest < interfaces.size()); 2537513SN/A assert(dest != src); // catch infinite loops 25411960Sgabeblack@google.com dest_port_id = dest; 2557513SN/A dest_port = interfaces[dest_port_id]; 25611960Sgabeblack@google.com } 2577513SN/A 2587513SN/A if (dest_port_id == src) { 2597513SN/A // Must be forwarded snoop up from below... 26010451SN/A assert(dest == Packet::Broadcast); 2617513SN/A } else { 2629885SN/A // send to actual target 2639885SN/A if (!dest_port->sendTiming(pkt)) { 2649885SN/A // Packet not successfully sent. Leave or put it on the retry list. 26510315SN/A // illegal to block responses... can lead to deadlock 26610036SN/A assert(!pkt->isResponse()); 26710315SN/A // It's also illegal to force a transaction to retry after 2689885SN/A // someone else has committed to respond. 2699885SN/A assert(!pkt->memInhibitAsserted()); 27010315SN/A DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x TGT RETRY\n", 27110315SN/A src, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); 27210315SN/A addToRetryList(src_port); 27310315SN/A occupyBus(headerFinishTime); 27410315SN/A return false; 27510315SN/A } 27610315SN/A // send OK, fall through... pkt may have been deleted by 27710315SN/A // target at this point, so it should *not* be referenced 2787513SN/A // again. We'll set it to NULL here just to be safe. 27910451SN/A pkt = NULL; 28011960Sgabeblack@google.com } 2819885SN/A 28211570SCurtis.Dunham@arm.com occupyBus(packetFinishTime); 28310036SN/A 28411066Snilay@cs.wisc.edu // Packet was successfully sent. 28511066Snilay@cs.wisc.edu // Also take care of retries 28611570SCurtis.Dunham@arm.com if (inRetry) { 28711570SCurtis.Dunham@arm.com DPRINTF(Bus, "Remove retry from list %d\n", src); 28811570SCurtis.Dunham@arm.com retryList.pop_front(); 28911388Ssteve.reinhardt@amd.com inRetry = false; 29011570SCurtis.Dunham@arm.com } 29111066Snilay@cs.wisc.edu return true; 29211960Sgabeblack@google.com} 29311066Snilay@cs.wisc.edu 2949885SN/Avoid 2957524SN/ABus::recvRetry(int id) 29611066Snilay@cs.wisc.edu{ 2979265SN/A // If there's anything waiting, and the bus isn't busy... 29811066Snilay@cs.wisc.edu if (retryList.size() && curTick() >= tickNextIdle) { 2997513SN/A //retryingPort = retryList.front(); 30011960Sgabeblack@google.com inRetry = true; 30111960Sgabeblack@google.com DPRINTF(Bus, "Sending a retry to %s\n", retryList.front()->getPeer()->name()); 30211960Sgabeblack@google.com retryList.front()->sendRetry(); 30311960Sgabeblack@google.com // If inRetry is still true, sendTiming wasn't called 30411960Sgabeblack@google.com if (inRetry) 30511960Sgabeblack@google.com { 30611960Sgabeblack@google.com retryList.pop_front(); 3077513SN/A inRetry = false; 3088983SN/A 3099265SN/A //Bring tickNextIdle up to the present 3109885SN/A while (tickNextIdle < curTick()) 3119885SN/A tickNextIdle += clock; 31211570SCurtis.Dunham@arm.com 31310036SN/A //Burn a cycle for the missed grant. 3148983SN/A tickNextIdle += clock; 31511960Sgabeblack@google.com 3167513SN/A reschedule(busIdle, tickNextIdle, true); 3177513SN/A } 3187513SN/A } 31911570SCurtis.Dunham@arm.com //If we weren't able to drain before, we might be able to now. 32011570SCurtis.Dunham@arm.com if (drainEvent && retryList.size() == 0 && curTick() >= tickNextIdle) { 32111570SCurtis.Dunham@arm.com drainEvent->process(); 32211570SCurtis.Dunham@arm.com // Clear the drain event once we're done with it. 32311960Sgabeblack@google.com drainEvent = NULL; 3248893SN/A } 3257513SN/A} 3269885SN/A 3279885SN/Aint 32810036SN/ABus::findPort(Addr addr) 3299885SN/A{ 3309885SN/A /* An interval tree would be a better way to do this. --ali. */ 331 int dest_id; 332 333 dest_id = checkPortCache(addr); 334 if (dest_id != INVALID_PORT_ID) 335 return dest_id; 336 337 // Check normal port ranges 338 PortIter i = portMap.find(RangeSize(addr,1)); 339 if (i != portMap.end()) { 340 dest_id = i->second; 341 updatePortCache(dest_id, i->first.start, i->first.end); 342 return dest_id; 343 } 344 345 // Check if this matches the default range 346 if (useDefaultRange) { 347 AddrRangeIter a_end = defaultRange.end(); 348 for (AddrRangeIter i = defaultRange.begin(); i != a_end; i++) { 349 if (*i == addr) { 350 DPRINTF(Bus, " found addr %#llx on default\n", addr); 351 return defaultPortId; 352 } 353 } 354 } else if (defaultPortId != INVALID_PORT_ID) { 355 DPRINTF(Bus, "Unable to find destination for addr %#llx, " 356 "will use default port\n", addr); 357 return defaultPortId; 358 } 359 360 // we should use the range for the default port and it did not 361 // match, or the default port is not set 362 fatal("Unable to find destination for addr %#llx on bus %s\n", addr, 363 name()); 364} 365 366 367/** Function called by the port when the bus is receiving a Atomic 368 * transaction.*/ 369Tick 370Bus::recvAtomic(PacketPtr pkt) 371{ 372 DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n", 373 pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); 374 assert(pkt->getDest() == Packet::Broadcast); 375 assert(pkt->isRequest()); 376 377 // Variables for recording original command and snoop response (if 378 // any)... if a snooper respondes, we will need to restore 379 // original command so that additional snoops can take place 380 // properly 381 MemCmd orig_cmd = pkt->cmd; 382 MemCmd snoop_response_cmd = MemCmd::InvalidCmd; 383 Tick snoop_response_latency = 0; 384 int orig_src = pkt->getSrc(); 385 386 int target_port_id = findPort(pkt->getAddr()); 387 BusPort *target_port = interfaces[target_port_id]; 388 389 SnoopIter s_end = snoopPorts.end(); 390 for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { 391 BusPort *p = *s_iter; 392 // same port should not have both target addresses and snooping 393 assert(p != target_port); 394 if (p->getId() != pkt->getSrc()) { 395 Tick latency = p->sendAtomic(pkt); 396 if (pkt->isResponse()) { 397 // response from snoop agent 398 assert(pkt->cmd != orig_cmd); 399 assert(pkt->memInhibitAsserted()); 400 // should only happen once 401 assert(snoop_response_cmd == MemCmd::InvalidCmd); 402 // save response state 403 snoop_response_cmd = pkt->cmd; 404 snoop_response_latency = latency; 405 // restore original packet state for remaining snoopers 406 pkt->cmd = orig_cmd; 407 pkt->setSrc(orig_src); 408 pkt->setDest(Packet::Broadcast); 409 } 410 } 411 } 412 413 Tick response_latency = 0; 414 415 // we can get requests sent up from the memory side of the bus for 416 // snooping... don't send them back down! 417 if (target_port_id != pkt->getSrc()) { 418 response_latency = target_port->sendAtomic(pkt); 419 } 420 421 // if we got a response from a snooper, restore it here 422 if (snoop_response_cmd != MemCmd::InvalidCmd) { 423 // no one else should have responded 424 assert(!pkt->isResponse()); 425 assert(pkt->cmd == orig_cmd); 426 pkt->cmd = snoop_response_cmd; 427 response_latency = snoop_response_latency; 428 } 429 430 // why do we have this packet field and the return value both??? 431 pkt->finishTime = curTick() + response_latency; 432 return response_latency; 433} 434 435/** Function called by the port when the bus is receiving a Functional 436 * transaction.*/ 437void 438Bus::recvFunctional(PacketPtr pkt) 439{ 440 assert(pkt->getDest() == Packet::Broadcast); 441 442 int port_id = findPort(pkt->getAddr()); 443 Port *port = interfaces[port_id]; 444 // The packet may be changed by another bus on snoops, restore the 445 // id after each 446 int src_id = pkt->getSrc(); 447 448 if (!pkt->isPrint()) { 449 // don't do DPRINTFs on PrintReq as it clutters up the output 450 DPRINTF(Bus, 451 "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", 452 src_id, port_id, pkt->getAddr(), 453 pkt->cmdString()); 454 } 455 456 assert(pkt->isRequest()); // hasn't already been satisfied 457 458 SnoopIter s_end = snoopPorts.end(); 459 for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { 460 BusPort *p = *s_iter; 461 if (p != port && p->getId() != src_id) { 462 p->sendFunctional(pkt); 463 } 464 if (pkt->isResponse()) { 465 break; 466 } 467 pkt->setSrc(src_id); 468 } 469 470 // If the snooping hasn't found what we were looking for and it is not 471 // a forwarded snoop from below, keep going. 472 if (!pkt->isResponse() && port_id != pkt->getSrc()) { 473 port->sendFunctional(pkt); 474 } 475} 476 477/** Function called by the port when the bus is receiving a range change.*/ 478void 479Bus::recvRangeChange(int id) 480{ 481 AddrRangeList ranges; 482 AddrRangeIter iter; 483 484 if (inRecvRangeChange.count(id)) 485 return; 486 inRecvRangeChange.insert(id); 487 488 DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id); 489 490 clearPortCache(); 491 if (id == defaultPortId) { 492 defaultRange.clear(); 493 // Only try to update these ranges if the user set a default responder. 494 if (useDefaultRange) { 495 AddrRangeList ranges = interfaces[id]->getPeer()->getAddrRanges(); 496 for(iter = ranges.begin(); iter != ranges.end(); iter++) { 497 defaultRange.push_back(*iter); 498 DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", 499 iter->start, iter->end); 500 } 501 } 502 } else { 503 504 assert(id < interfaces.size() && id >= 0); 505 BusPort *port = interfaces[id]; 506 507 // Clean out any previously existent ids 508 for (PortIter portIter = portMap.begin(); 509 portIter != portMap.end(); ) { 510 if (portIter->second == id) 511 portMap.erase(portIter++); 512 else 513 portIter++; 514 } 515 516 ranges = port->getPeer()->getAddrRanges(); 517 518 for (iter = ranges.begin(); iter != ranges.end(); iter++) { 519 DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", 520 iter->start, iter->end, id); 521 if (portMap.insert(*iter, id) == portMap.end()) { 522 int conflict_id = portMap.find(*iter)->second; 523 fatal("%s has two ports with same range:\n\t%s\n\t%s\n", 524 name(), interfaces[id]->getPeer()->name(), 525 interfaces[conflict_id]->getPeer()->name()); 526 } 527 } 528 } 529 DPRINTF(MMU, "port list has %d entries\n", portMap.size()); 530 531 // tell all our peers that our address range has changed. 532 // Don't tell the device that caused this change, it already knows 533 std::vector<BusPort*>::const_iterator intIter; 534 535 for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) 536 if ((*intIter)->getId() != id) 537 (*intIter)->sendRangeChange(); 538 539 inRecvRangeChange.erase(id); 540} 541 542AddrRangeList 543Bus::getAddrRanges(int id) 544{ 545 AddrRangeList ranges; 546 547 DPRINTF(BusAddrRanges, "received address range request, returning:\n"); 548 549 for (AddrRangeIter dflt_iter = defaultRange.begin(); 550 dflt_iter != defaultRange.end(); dflt_iter++) { 551 ranges.push_back(*dflt_iter); 552 DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start, 553 dflt_iter->end); 554 } 555 for (PortIter portIter = portMap.begin(); 556 portIter != portMap.end(); portIter++) { 557 bool subset = false; 558 for (AddrRangeIter dflt_iter = defaultRange.begin(); 559 dflt_iter != defaultRange.end(); dflt_iter++) { 560 if ((portIter->first.start < dflt_iter->start && 561 portIter->first.end >= dflt_iter->start) || 562 (portIter->first.start < dflt_iter->end && 563 portIter->first.end >= dflt_iter->end)) 564 fatal("Devices can not set ranges that itersect the default set\ 565 but are not a subset of the default set.\n"); 566 if (portIter->first.start >= dflt_iter->start && 567 portIter->first.end <= dflt_iter->end) { 568 subset = true; 569 DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n", 570 portIter->first.start, portIter->first.end); 571 } 572 } 573 if (portIter->second != id && !subset) { 574 ranges.push_back(portIter->first); 575 DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", 576 portIter->first.start, portIter->first.end); 577 } 578 } 579 580 return ranges; 581} 582 583bool 584Bus::isSnooping(int id) 585{ 586 // in essence, answer the question if there are other snooping 587 // ports rather than the port that is asking 588 bool snoop = false; 589 for (SnoopIter s_iter = snoopPorts.begin(); s_iter != snoopPorts.end(); 590 s_iter++) { 591 if ((*s_iter)->getId() != id) { 592 snoop = true; 593 break; 594 } 595 } 596 return snoop; 597} 598 599unsigned 600Bus::findBlockSize(int id) 601{ 602 if (cachedBlockSizeValid) 603 return cachedBlockSize; 604 605 unsigned max_bs = 0; 606 607 PortIter p_end = portMap.end(); 608 for (PortIter p_iter = portMap.begin(); p_iter != p_end; p_iter++) { 609 unsigned tmp_bs = interfaces[p_iter->second]->peerBlockSize(); 610 if (tmp_bs > max_bs) 611 max_bs = tmp_bs; 612 } 613 SnoopIter s_end = snoopPorts.end(); 614 for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { 615 unsigned tmp_bs = (*s_iter)->peerBlockSize(); 616 if (tmp_bs > max_bs) 617 max_bs = tmp_bs; 618 } 619 if (max_bs == 0) 620 max_bs = defaultBlockSize; 621 622 if (max_bs != 64) 623 warn_once("Blocksize found to not be 64... hmm... probably not.\n"); 624 cachedBlockSize = max_bs; 625 cachedBlockSizeValid = true; 626 return max_bs; 627} 628 629 630unsigned int 631Bus::drain(Event * de) 632{ 633 //We should check that we're not "doing" anything, and that noone is 634 //waiting. We might be idle but have someone waiting if the device we 635 //contacted for a retry didn't actually retry. 636 if (retryList.size() || (curTick() < tickNextIdle && busIdle.scheduled())) { 637 drainEvent = de; 638 return 1; 639 } 640 return 0; 641} 642 643void 644Bus::startup() 645{ 646 if (tickNextIdle < curTick()) 647 tickNextIdle = (curTick() / clock) * clock + clock; 648} 649 650Bus * 651BusParams::create() 652{ 653 return new Bus(this); 654} 655