coherent_xbar.cc revision 8915
15647Sgblack@eecs.umich.edu/* 28922Swilliam.wang@arm.com * Copyright (c) 2011-2012 ARM Limited 38922Swilliam.wang@arm.com * All rights reserved 48922Swilliam.wang@arm.com * 58922Swilliam.wang@arm.com * The license below extends only to copyright in the software and shall 68922Swilliam.wang@arm.com * not be construed as granting a license to any other intellectual 78922Swilliam.wang@arm.com * property including but not limited to intellectual property relating 88922Swilliam.wang@arm.com * to a hardware implementation of the functionality of the software 98922Swilliam.wang@arm.com * licensed hereunder. You may use the software subject to the license 108922Swilliam.wang@arm.com * terms below provided that you ensure that this notice is replicated 118922Swilliam.wang@arm.com * unmodified and in its entirety in all distributions of the software, 128922Swilliam.wang@arm.com * modified or unmodified, in source code or in binary form. 138922Swilliam.wang@arm.com * 145647Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan 155647Sgblack@eecs.umich.edu * All rights reserved. 165647Sgblack@eecs.umich.edu * 177087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 187087Snate@binkert.org * modification, are permitted provided that the following conditions are 197087Snate@binkert.org * met: redistributions of source code must retain the above copyright 207087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 217087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 227087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 237087Snate@binkert.org * documentation and/or other materials provided with the distribution; 247087Snate@binkert.org * neither the name of the copyright holders nor the names of its 255647Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 267087Snate@binkert.org * this software without specific prior written permission. 277087Snate@binkert.org * 287087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 297087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 307087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 317087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 327087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 337087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 345647Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 357087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 365647Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 375647Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 385647Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 395647Sgblack@eecs.umich.edu * 405647Sgblack@eecs.umich.edu * Authors: Ali Saidi 415647Sgblack@eecs.umich.edu * Andreas Hansson 425647Sgblack@eecs.umich.edu */ 435647Sgblack@eecs.umich.edu 445647Sgblack@eecs.umich.edu/** 455647Sgblack@eecs.umich.edu * @file 465647Sgblack@eecs.umich.edu * Definition of a bus object. 475647Sgblack@eecs.umich.edu */ 485647Sgblack@eecs.umich.edu 495647Sgblack@eecs.umich.edu#include "base/misc.hh" 505647Sgblack@eecs.umich.edu#include "base/trace.hh" 515647Sgblack@eecs.umich.edu#include "debug/Bus.hh" 528229Snate@binkert.org#include "debug/BusAddrRanges.hh" 535647Sgblack@eecs.umich.edu#include "mem/bus.hh" 545654Sgblack@eecs.umich.edu 555647Sgblack@eecs.umich.eduBus::Bus(const BusParams *p) 568232Snate@binkert.org : MemObject(p), clock(p->clock), 576137Sgblack@eecs.umich.edu headerCycles(p->header_cycles), width(p->width), tickNextIdle(0), 586137Sgblack@eecs.umich.edu drainEvent(NULL), busIdleEvent(this), inRetry(false), 596137Sgblack@eecs.umich.edu nbrMasterPorts(p->port_master_connection_count), 605654Sgblack@eecs.umich.edu defaultPortId(INVALID_PORT_ID), useDefaultRange(p->use_default_range), 616046Sgblack@eecs.umich.edu defaultBlockSize(p->block_size), 628781Sgblack@eecs.umich.edu cachedBlockSize(0), cachedBlockSizeValid(false) 635647Sgblack@eecs.umich.edu{ 645648Sgblack@eecs.umich.edu //width, clock period, and header cycles must be positive 655648Sgblack@eecs.umich.edu if (width <= 0) 665647Sgblack@eecs.umich.edu fatal("Bus width must be positive\n"); 675647Sgblack@eecs.umich.edu if (clock <= 0) 685647Sgblack@eecs.umich.edu fatal("Bus clock period must be positive\n"); 695647Sgblack@eecs.umich.edu if (headerCycles <= 0) 705647Sgblack@eecs.umich.edu fatal("Number of header cycles must be positive\n"); 715647Sgblack@eecs.umich.edu 725647Sgblack@eecs.umich.edu // create the ports based on the size of the master and slave 735647Sgblack@eecs.umich.edu // vector ports, and the presence of the default master 745647Sgblack@eecs.umich.edu 755648Sgblack@eecs.umich.edu // id used to index into interfaces which is a flat vector of all 765647Sgblack@eecs.umich.edu // ports 775648Sgblack@eecs.umich.edu int id = 0; 785648Sgblack@eecs.umich.edu for (int i = 0; i < p->port_master_connection_count; ++i) { 795648Sgblack@eecs.umich.edu std::string portName = csprintf("%s-p%d", name(), id); 805648Sgblack@eecs.umich.edu interfaces.push_back(new BusPort(portName, this, id)); 815648Sgblack@eecs.umich.edu ++id; 825648Sgblack@eecs.umich.edu } 835648Sgblack@eecs.umich.edu 845648Sgblack@eecs.umich.edu // see if we have a default master connected and if so add the 855648Sgblack@eecs.umich.edu // port 865648Sgblack@eecs.umich.edu if (p->port_default_connection_count) { 875648Sgblack@eecs.umich.edu defaultPortId = id; 885648Sgblack@eecs.umich.edu std::string portName = csprintf("%s-default", name()); 895648Sgblack@eecs.umich.edu interfaces.push_back(new BusPort(portName, this, id)); 905648Sgblack@eecs.umich.edu ++id; 915648Sgblack@eecs.umich.edu // this is an additional master port 925648Sgblack@eecs.umich.edu ++nbrMasterPorts; 935648Sgblack@eecs.umich.edu } 945648Sgblack@eecs.umich.edu 955648Sgblack@eecs.umich.edu // note that the first slave port is now stored on index 965648Sgblack@eecs.umich.edu // nbrMasterPorts in the vector 975648Sgblack@eecs.umich.edu for (int i = 0; i < p->port_slave_connection_count; ++i) { 985648Sgblack@eecs.umich.edu std::string portName = csprintf("%s-p%d", name(), id); 995648Sgblack@eecs.umich.edu interfaces.push_back(new BusPort(portName, this, id)); 1005648Sgblack@eecs.umich.edu ++id; 1015648Sgblack@eecs.umich.edu } 1025648Sgblack@eecs.umich.edu 1035648Sgblack@eecs.umich.edu clearPortCache(); 1045648Sgblack@eecs.umich.edu} 1055648Sgblack@eecs.umich.edu 1065648Sgblack@eecs.umich.eduPort * 1075648Sgblack@eecs.umich.eduBus::getPort(const std::string &if_name, int idx) 1085648Sgblack@eecs.umich.edu{ 1095648Sgblack@eecs.umich.edu if (if_name == "master") { 1105648Sgblack@eecs.umich.edu // the master index translates directly to the interfaces 1115648Sgblack@eecs.umich.edu // vector as they are stored first 1125648Sgblack@eecs.umich.edu return interfaces[idx]; 1135648Sgblack@eecs.umich.edu } else if (if_name == "slave") { 1145648Sgblack@eecs.umich.edu // the slaves are stored after the masters and we must thus 1155648Sgblack@eecs.umich.edu // offset the slave index with the number of master ports 1165648Sgblack@eecs.umich.edu return interfaces[nbrMasterPorts + idx]; 1175648Sgblack@eecs.umich.edu } else if (if_name == "default") { 1185648Sgblack@eecs.umich.edu return interfaces[defaultPortId]; 1195648Sgblack@eecs.umich.edu } else { 1205648Sgblack@eecs.umich.edu panic("No port %s %d on bus %s\n", if_name, idx, name()); 1215648Sgblack@eecs.umich.edu } 1225648Sgblack@eecs.umich.edu} 1235648Sgblack@eecs.umich.edu 1245648Sgblack@eecs.umich.eduvoid 1255648Sgblack@eecs.umich.eduBus::init() 1265648Sgblack@eecs.umich.edu{ 1275648Sgblack@eecs.umich.edu std::vector<BusPort*>::iterator intIter; 1285648Sgblack@eecs.umich.edu 1295648Sgblack@eecs.umich.edu // iterate over our interfaces and determine which of our neighbours 1305648Sgblack@eecs.umich.edu // are snooping and add them as snoopers 1315648Sgblack@eecs.umich.edu for (intIter = interfaces.begin(); intIter != interfaces.end(); 1325648Sgblack@eecs.umich.edu intIter++) { 1335648Sgblack@eecs.umich.edu if ((*intIter)->getPeer()->isSnooping()) { 1345648Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n", 1355648Sgblack@eecs.umich.edu (*intIter)->getPeer()->name()); 1365648Sgblack@eecs.umich.edu snoopPorts.push_back(*intIter); 1375648Sgblack@eecs.umich.edu } 1385648Sgblack@eecs.umich.edu } 1395648Sgblack@eecs.umich.edu} 1405648Sgblack@eecs.umich.edu 1415648Sgblack@eecs.umich.eduTick 1425648Sgblack@eecs.umich.eduBus::calcPacketTiming(PacketPtr pkt) 1435648Sgblack@eecs.umich.edu{ 1445648Sgblack@eecs.umich.edu // determine the current time rounded to the closest following 1455648Sgblack@eecs.umich.edu // clock edge 1465648Sgblack@eecs.umich.edu Tick now = curTick(); 1475648Sgblack@eecs.umich.edu if (now % clock != 0) { 1485648Sgblack@eecs.umich.edu now = ((now / clock) + 1) * clock; 1495648Sgblack@eecs.umich.edu } 1505648Sgblack@eecs.umich.edu 1515648Sgblack@eecs.umich.edu Tick headerTime = now + headerCycles * clock; 1525648Sgblack@eecs.umich.edu 1535648Sgblack@eecs.umich.edu // The packet will be sent. Figure out how long it occupies the bus, and 1545648Sgblack@eecs.umich.edu // how much of that time is for the first "word", aka bus width. 1555648Sgblack@eecs.umich.edu int numCycles = 0; 1565648Sgblack@eecs.umich.edu if (pkt->hasData()) { 1575648Sgblack@eecs.umich.edu // If a packet has data, it needs ceil(size/width) cycles to send it 1585648Sgblack@eecs.umich.edu int dataSize = pkt->getSize(); 1595648Sgblack@eecs.umich.edu numCycles += dataSize/width; 1605648Sgblack@eecs.umich.edu if (dataSize % width) 1615648Sgblack@eecs.umich.edu numCycles++; 1625648Sgblack@eecs.umich.edu } 1635648Sgblack@eecs.umich.edu 1645648Sgblack@eecs.umich.edu // The first word will be delivered after the current tick, the delivery 1655648Sgblack@eecs.umich.edu // of the address if any, and one bus cycle to deliver the data 1665648Sgblack@eecs.umich.edu pkt->firstWordTime = headerTime + clock; 1675648Sgblack@eecs.umich.edu 1685648Sgblack@eecs.umich.edu pkt->finishTime = headerTime + numCycles * clock; 1695648Sgblack@eecs.umich.edu 1705648Sgblack@eecs.umich.edu return headerTime; 1715648Sgblack@eecs.umich.edu} 1725648Sgblack@eecs.umich.edu 1735648Sgblack@eecs.umich.eduvoid Bus::occupyBus(Tick until) 1745648Sgblack@eecs.umich.edu{ 1755648Sgblack@eecs.umich.edu if (until == 0) { 1765648Sgblack@eecs.umich.edu // shortcut for express snoop packets 1775648Sgblack@eecs.umich.edu return; 1785648Sgblack@eecs.umich.edu } 1795648Sgblack@eecs.umich.edu 1805648Sgblack@eecs.umich.edu tickNextIdle = until; 1815648Sgblack@eecs.umich.edu reschedule(busIdleEvent, tickNextIdle, true); 1825648Sgblack@eecs.umich.edu 1835648Sgblack@eecs.umich.edu DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n", 1845648Sgblack@eecs.umich.edu curTick(), tickNextIdle); 1855648Sgblack@eecs.umich.edu} 1865648Sgblack@eecs.umich.edu 1875648Sgblack@eecs.umich.edu/** Function called by the port when the bus is receiving a Timing 1885648Sgblack@eecs.umich.edu * transaction.*/ 1895648Sgblack@eecs.umich.edubool 1905648Sgblack@eecs.umich.eduBus::recvTiming(PacketPtr pkt) 1915648Sgblack@eecs.umich.edu{ 1925648Sgblack@eecs.umich.edu // called for both requests and responses 1935648Sgblack@eecs.umich.edu 1945648Sgblack@eecs.umich.edu // get the source id and port 1955648Sgblack@eecs.umich.edu Packet::NodeID src_id = pkt->getSrc(); 1965648Sgblack@eecs.umich.edu 1975648Sgblack@eecs.umich.edu BusPort *src_port = interfaces[src_id]; 1985648Sgblack@eecs.umich.edu 1995648Sgblack@eecs.umich.edu // If the bus is busy, or other devices are in line ahead of the current 2005648Sgblack@eecs.umich.edu // one, put this device on the retry list. 2015648Sgblack@eecs.umich.edu if (!pkt->isExpressSnoop() && 2025648Sgblack@eecs.umich.edu (tickNextIdle > curTick() || 2035648Sgblack@eecs.umich.edu (!retryList.empty() && (!inRetry || src_port != retryList.front())))) 2045648Sgblack@eecs.umich.edu { 2055648Sgblack@eecs.umich.edu addToRetryList(src_port); 2065648Sgblack@eecs.umich.edu DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x BUSY\n", 2075648Sgblack@eecs.umich.edu src_id, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); 2085648Sgblack@eecs.umich.edu return false; 2095648Sgblack@eecs.umich.edu } 2105648Sgblack@eecs.umich.edu 2115648Sgblack@eecs.umich.edu DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x\n", 2125648Sgblack@eecs.umich.edu src_id, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); 2135648Sgblack@eecs.umich.edu 2145648Sgblack@eecs.umich.edu Tick headerFinishTime = pkt->isExpressSnoop() ? 0 : calcPacketTiming(pkt); 2155648Sgblack@eecs.umich.edu Tick packetFinishTime = pkt->isExpressSnoop() ? 0 : pkt->finishTime; 2165648Sgblack@eecs.umich.edu 2175648Sgblack@eecs.umich.edu Packet::NodeID dest = pkt->getDest(); 2185648Sgblack@eecs.umich.edu int dest_id; 2195648Sgblack@eecs.umich.edu Port *dest_port; 2205649Sgblack@eecs.umich.edu 2215649Sgblack@eecs.umich.edu if (dest == Packet::Broadcast) { 2225649Sgblack@eecs.umich.edu // the packet is a memory-mapped request and should be broadcasted to 2235648Sgblack@eecs.umich.edu // our snoopers 2245898Sgblack@eecs.umich.edu assert(pkt->isRequest()); 2255648Sgblack@eecs.umich.edu 2265648Sgblack@eecs.umich.edu SnoopIter s_end = snoopPorts.end(); 2275648Sgblack@eecs.umich.edu for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { 2285648Sgblack@eecs.umich.edu BusPort *p = *s_iter; 2295648Sgblack@eecs.umich.edu // we got this request from a snooping master 2305648Sgblack@eecs.umich.edu // (corresponding to our own slave port that is also in 2315648Sgblack@eecs.umich.edu // snoopPorts) and should not send it back to where it 2325648Sgblack@eecs.umich.edu // came from 2335648Sgblack@eecs.umich.edu if (p->getId() != src_id) { 2345648Sgblack@eecs.umich.edu // cache is not allowed to refuse snoop 2355648Sgblack@eecs.umich.edu bool success M5_VAR_USED = p->sendTiming(pkt); 2365648Sgblack@eecs.umich.edu assert(success); 2375648Sgblack@eecs.umich.edu } 2385649Sgblack@eecs.umich.edu } 2395649Sgblack@eecs.umich.edu 2405649Sgblack@eecs.umich.edu // since it is a request, similar to functional and atomic, 2415648Sgblack@eecs.umich.edu // determine the destination based on the address and forward 2425898Sgblack@eecs.umich.edu // through the corresponding master port 2435648Sgblack@eecs.umich.edu dest_id = findPort(pkt->getAddr()); 2445647Sgblack@eecs.umich.edu dest_port = interfaces[dest_id]; 2455691Sgblack@eecs.umich.edu } else { 2465691Sgblack@eecs.umich.edu // the packet is a response, and it should always go back to 2475691Sgblack@eecs.umich.edu // the port determined by the destination field 2485691Sgblack@eecs.umich.edu dest_id = dest; 2495691Sgblack@eecs.umich.edu assert(dest_id != src_id); // catch infinite loops 2505691Sgblack@eecs.umich.edu assert(dest_id < interfaces.size()); 2515691Sgblack@eecs.umich.edu dest_port = interfaces[dest_id]; 2525691Sgblack@eecs.umich.edu } 2535691Sgblack@eecs.umich.edu 2545691Sgblack@eecs.umich.edu // if this is a snoop from a slave (corresponding to our own 2555691Sgblack@eecs.umich.edu // master), i.e. the memory side of the bus, then do not send it 2565691Sgblack@eecs.umich.edu // back to where it came from 2575691Sgblack@eecs.umich.edu if (dest_id != src_id) { 2585691Sgblack@eecs.umich.edu // send to actual target 2595691Sgblack@eecs.umich.edu if (!dest_port->sendTiming(pkt)) { 2605691Sgblack@eecs.umich.edu // Packet not successfully sent. Leave or put it on the retry list. 2615691Sgblack@eecs.umich.edu // illegal to block responses... can lead to deadlock 2625691Sgblack@eecs.umich.edu assert(!pkt->isResponse()); 2635691Sgblack@eecs.umich.edu // It's also illegal to force a transaction to retry after 2645691Sgblack@eecs.umich.edu // someone else has committed to respond. 2655691Sgblack@eecs.umich.edu assert(!pkt->memInhibitAsserted()); 2665691Sgblack@eecs.umich.edu DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x TGT RETRY\n", 2675691Sgblack@eecs.umich.edu src_id, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); 2685691Sgblack@eecs.umich.edu addToRetryList(src_port); 2695691Sgblack@eecs.umich.edu occupyBus(headerFinishTime); 2705691Sgblack@eecs.umich.edu return false; 2715691Sgblack@eecs.umich.edu } 2725691Sgblack@eecs.umich.edu // send OK, fall through... pkt may have been deleted by 2735691Sgblack@eecs.umich.edu // target at this point, so it should *not* be referenced 2745691Sgblack@eecs.umich.edu // again. We'll set it to NULL here just to be safe. 2755691Sgblack@eecs.umich.edu pkt = NULL; 2765691Sgblack@eecs.umich.edu } 2775691Sgblack@eecs.umich.edu 2785691Sgblack@eecs.umich.edu occupyBus(packetFinishTime); 2795691Sgblack@eecs.umich.edu 2805691Sgblack@eecs.umich.edu // Packet was successfully sent. 2815691Sgblack@eecs.umich.edu // Also take care of retries 2825691Sgblack@eecs.umich.edu if (inRetry) { 2835691Sgblack@eecs.umich.edu DPRINTF(Bus, "Remove retry from list %d\n", src_id); 2846066Sgblack@eecs.umich.edu retryList.pop_front(); 2856066Sgblack@eecs.umich.edu inRetry = false; 2866050Sgblack@eecs.umich.edu } 2876050Sgblack@eecs.umich.edu return true; 2885691Sgblack@eecs.umich.edu} 2898745Sgblack@eecs.umich.edu 2908781Sgblack@eecs.umich.eduvoid 2918781Sgblack@eecs.umich.eduBus::releaseBus() 2925691Sgblack@eecs.umich.edu{ 2935647Sgblack@eecs.umich.edu // releasing the bus means we should now be idle 2946041Sgblack@eecs.umich.edu assert(curTick() >= tickNextIdle); 2956041Sgblack@eecs.umich.edu 2966041Sgblack@eecs.umich.edu // bus is now idle, so if someone is waiting we can retry 2976041Sgblack@eecs.umich.edu if (!retryList.empty()) { 2986136Sgblack@eecs.umich.edu // note that we block (return false on recvTiming) both 2996136Sgblack@eecs.umich.edu // because the bus is busy and because the destination is 3006136Sgblack@eecs.umich.edu // busy, and in the latter case the bus may be released before 3016136Sgblack@eecs.umich.edu // we see a retry from the destination 3026136Sgblack@eecs.umich.edu retryWaiting(); 3036041Sgblack@eecs.umich.edu } 3046136Sgblack@eecs.umich.edu 3056136Sgblack@eecs.umich.edu //If we weren't able to drain before, we might be able to now. 3069090Sandreas.hansson@arm.com if (drainEvent && retryList.empty() && curTick() >= tickNextIdle) { 3076041Sgblack@eecs.umich.edu drainEvent->process(); 3086041Sgblack@eecs.umich.edu // Clear the drain event once we're done with it. 3096041Sgblack@eecs.umich.edu drainEvent = NULL; 3106137Sgblack@eecs.umich.edu } 3116137Sgblack@eecs.umich.edu} 3126137Sgblack@eecs.umich.edu 3137913SBrad.Beckmann@amd.comvoid 3147913SBrad.Beckmann@amd.comBus::retryWaiting() 3157913SBrad.Beckmann@amd.com{ 3167913SBrad.Beckmann@amd.com // this should never be called with an empty retry list 3177913SBrad.Beckmann@amd.com assert(!retryList.empty()); 3186137Sgblack@eecs.umich.edu 3197913SBrad.Beckmann@amd.com // send a retry to the port at the head of the retry list 3208922Swilliam.wang@arm.com inRetry = true; 3218922Swilliam.wang@arm.com DPRINTF(Bus, "Sending a retry to %s\n", 3228922Swilliam.wang@arm.com retryList.front()->getPeer()->name()); 3236137Sgblack@eecs.umich.edu 3246137Sgblack@eecs.umich.edu // note that we might have blocked on the receiving port being 3256137Sgblack@eecs.umich.edu // busy (rather than the bus itself) and now call retry before the 3265651Sgblack@eecs.umich.edu // destination called retry on the bus 3275651Sgblack@eecs.umich.edu retryList.front()->sendRetry(); 3285651Sgblack@eecs.umich.edu 3296136Sgblack@eecs.umich.edu // If inRetry is still true, sendTiming wasn't called in zero time 3305651Sgblack@eecs.umich.edu // (e.g. the cache does this) 3315651Sgblack@eecs.umich.edu if (inRetry) { 3325651Sgblack@eecs.umich.edu retryList.pop_front(); 3335651Sgblack@eecs.umich.edu inRetry = false; 3345654Sgblack@eecs.umich.edu 3355654Sgblack@eecs.umich.edu //Bring tickNextIdle up to the present 3365654Sgblack@eecs.umich.edu while (tickNextIdle < curTick()) 3375654Sgblack@eecs.umich.edu tickNextIdle += clock; 3385697Snate@binkert.org 3395655Sgblack@eecs.umich.edu //Burn a cycle for the missed grant. 3405691Sgblack@eecs.umich.edu tickNextIdle += clock; 3415691Sgblack@eecs.umich.edu 3425654Sgblack@eecs.umich.edu reschedule(busIdleEvent, tickNextIdle, true); 3435651Sgblack@eecs.umich.edu } 3445651Sgblack@eecs.umich.edu} 3455651Sgblack@eecs.umich.edu 3465651Sgblack@eecs.umich.eduvoid 3475651Sgblack@eecs.umich.eduBus::recvRetry(int id) 3485651Sgblack@eecs.umich.edu{ 3496064Sgblack@eecs.umich.edu // we got a retry from a peer that we tried to send something to 3505651Sgblack@eecs.umich.edu // and failed, but we sent it on the account of someone else, and 3515651Sgblack@eecs.umich.edu // that source port should be on our retry list, however if the 3525651Sgblack@eecs.umich.edu // bus is released before this happens and the retry (from the bus 3535651Sgblack@eecs.umich.edu // point of view) is successful then this no longer holds and we 3546065Sgblack@eecs.umich.edu // could in fact have an empty retry list 3556065Sgblack@eecs.umich.edu if (retryList.empty()) 3566065Sgblack@eecs.umich.edu return; 3576065Sgblack@eecs.umich.edu 3586065Sgblack@eecs.umich.edu // if the bus isn't busy 3596069Sgblack@eecs.umich.edu if (curTick() >= tickNextIdle) { 3606069Sgblack@eecs.umich.edu // note that we do not care who told us to retry at the moment, we 3616069Sgblack@eecs.umich.edu // merely let the first one on the retry list go 3626069Sgblack@eecs.umich.edu retryWaiting(); 3636069Sgblack@eecs.umich.edu } 3646069Sgblack@eecs.umich.edu} 3656065Sgblack@eecs.umich.edu 3666065Sgblack@eecs.umich.eduint 3676065Sgblack@eecs.umich.eduBus::findPort(Addr addr) 3686065Sgblack@eecs.umich.edu{ 3696065Sgblack@eecs.umich.edu /* An interval tree would be a better way to do this. --ali. */ 3708711Sandreas.hansson@arm.com int dest_id; 3719090Sandreas.hansson@arm.com 3726041Sgblack@eecs.umich.edu dest_id = checkPortCache(addr); 3738711Sandreas.hansson@arm.com if (dest_id != INVALID_PORT_ID) 3746136Sgblack@eecs.umich.edu return dest_id; 3756136Sgblack@eecs.umich.edu 3766136Sgblack@eecs.umich.edu // Check normal port ranges 3778711Sandreas.hansson@arm.com PortIter i = portMap.find(RangeSize(addr,1)); 3788711Sandreas.hansson@arm.com if (i != portMap.end()) { 3796041Sgblack@eecs.umich.edu dest_id = i->second; 3806041Sgblack@eecs.umich.edu updatePortCache(dest_id, i->first.start, i->first.end); 3816041Sgblack@eecs.umich.edu return dest_id; 3828711Sandreas.hansson@arm.com } 3839090Sandreas.hansson@arm.com 3846041Sgblack@eecs.umich.edu // Check if this matches the default range 3858711Sandreas.hansson@arm.com if (useDefaultRange) { 3868711Sandreas.hansson@arm.com AddrRangeIter a_end = defaultRange.end(); 3878711Sandreas.hansson@arm.com for (AddrRangeIter i = defaultRange.begin(); i != a_end; i++) { 3888711Sandreas.hansson@arm.com if (*i == addr) { 3898711Sandreas.hansson@arm.com DPRINTF(Bus, " found addr %#llx on default\n", addr); 3906041Sgblack@eecs.umich.edu return defaultPortId; 3916041Sgblack@eecs.umich.edu } 3926041Sgblack@eecs.umich.edu } 3935647Sgblack@eecs.umich.edu } else if (defaultPortId != INVALID_PORT_ID) { 3945648Sgblack@eecs.umich.edu DPRINTF(Bus, "Unable to find destination for addr %#llx, " 3955647Sgblack@eecs.umich.edu "will use default port\n", addr); 3965647Sgblack@eecs.umich.edu return defaultPortId; 3975647Sgblack@eecs.umich.edu } 3985647Sgblack@eecs.umich.edu 3995647Sgblack@eecs.umich.edu // we should use the range for the default port and it did not 4005647Sgblack@eecs.umich.edu // match, or the default port is not set 4015647Sgblack@eecs.umich.edu fatal("Unable to find destination for addr %#llx on bus %s\n", addr, 4025647Sgblack@eecs.umich.edu name()); 4035647Sgblack@eecs.umich.edu} 4045647Sgblack@eecs.umich.edu 4055647Sgblack@eecs.umich.edu 4065647Sgblack@eecs.umich.edu/** Function called by the port when the bus is receiving a Atomic 4075647Sgblack@eecs.umich.edu * transaction.*/ 4085647Sgblack@eecs.umich.eduTick 4095647Sgblack@eecs.umich.eduBus::recvAtomic(PacketPtr pkt) 4105647Sgblack@eecs.umich.edu{ 4115647Sgblack@eecs.umich.edu DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n", 4125848Sgblack@eecs.umich.edu pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); 4135848Sgblack@eecs.umich.edu 4145848Sgblack@eecs.umich.edu // we should always see a request routed based on the address 4155848Sgblack@eecs.umich.edu assert(pkt->getDest() == Packet::Broadcast); 4165848Sgblack@eecs.umich.edu assert(pkt->isRequest()); 4175848Sgblack@eecs.umich.edu 4187823Ssteve.reinhardt@amd.com // the packet may be changed by another bus on snoops, record the 4195848Sgblack@eecs.umich.edu // source id here 4205848Sgblack@eecs.umich.edu Packet::NodeID src_id = pkt->getSrc(); 4215848Sgblack@eecs.umich.edu 4225848Sgblack@eecs.umich.edu // record the original command to enable us to restore it between 4235848Sgblack@eecs.umich.edu // snoops so that additional snoops can take place properly 4245848Sgblack@eecs.umich.edu MemCmd orig_cmd = pkt->cmd; 4255647Sgblack@eecs.umich.edu MemCmd snoop_response_cmd = MemCmd::InvalidCmd; 4265647Sgblack@eecs.umich.edu Tick snoop_response_latency = 0; 4275647Sgblack@eecs.umich.edu 4285647Sgblack@eecs.umich.edu SnoopIter s_end = snoopPorts.end(); 4295648Sgblack@eecs.umich.edu for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { 4305647Sgblack@eecs.umich.edu BusPort *p = *s_iter; 4315647Sgblack@eecs.umich.edu // we could have gotten this request from a snooping master 4325647Sgblack@eecs.umich.edu // (corresponding to our own slave port that is also in 4335648Sgblack@eecs.umich.edu // snoopPorts) and should not send it back to where it came 4345647Sgblack@eecs.umich.edu // from 4355647Sgblack@eecs.umich.edu if (p->getId() != src_id) { 4365647Sgblack@eecs.umich.edu Tick latency = p->sendAtomic(pkt); 4375647Sgblack@eecs.umich.edu // in contrast to a functional access, we have to keep on 4385647Sgblack@eecs.umich.edu // going as all snoopers must be updated even if we get a 4395647Sgblack@eecs.umich.edu // response 4405647Sgblack@eecs.umich.edu if (pkt->isResponse()) { 4415647Sgblack@eecs.umich.edu // response from snoop agent 4425647Sgblack@eecs.umich.edu assert(pkt->cmd != orig_cmd); 4435647Sgblack@eecs.umich.edu assert(pkt->memInhibitAsserted()); 4445647Sgblack@eecs.umich.edu // should only happen once 4455647Sgblack@eecs.umich.edu assert(snoop_response_cmd == MemCmd::InvalidCmd); 4465647Sgblack@eecs.umich.edu // save response state 4475647Sgblack@eecs.umich.edu snoop_response_cmd = pkt->cmd; 4485647Sgblack@eecs.umich.edu snoop_response_latency = latency; 4495647Sgblack@eecs.umich.edu // restore original packet state for remaining snoopers 4505647Sgblack@eecs.umich.edu pkt->cmd = orig_cmd; 4515647Sgblack@eecs.umich.edu pkt->setSrc(src_id); 4525647Sgblack@eecs.umich.edu pkt->setDest(Packet::Broadcast); 4535647Sgblack@eecs.umich.edu } 4545647Sgblack@eecs.umich.edu } 4555647Sgblack@eecs.umich.edu } 4565647Sgblack@eecs.umich.edu 4575647Sgblack@eecs.umich.edu // even if we had a snoop response, we must continue and also 4585647Sgblack@eecs.umich.edu // perform the actual request at the destination 4595647Sgblack@eecs.umich.edu int dest_id = findPort(pkt->getAddr()); 4605647Sgblack@eecs.umich.edu 4615647Sgblack@eecs.umich.edu Tick response_latency = 0; 4625647Sgblack@eecs.umich.edu 4635647Sgblack@eecs.umich.edu // if this is a snoop from a slave (corresponding to our own 4645647Sgblack@eecs.umich.edu // master), i.e. the memory side of the bus, then do not send it 4655647Sgblack@eecs.umich.edu // back to where it came from 4665690Sgblack@eecs.umich.edu if (dest_id != src_id) { 4675690Sgblack@eecs.umich.edu response_latency = interfaces[dest_id]->sendAtomic(pkt); 4685690Sgblack@eecs.umich.edu } 4695690Sgblack@eecs.umich.edu 4705647Sgblack@eecs.umich.edu // if we got a response from a snooper, restore it here 4715647Sgblack@eecs.umich.edu if (snoop_response_cmd != MemCmd::InvalidCmd) { 4725647Sgblack@eecs.umich.edu // no one else should have responded 4735647Sgblack@eecs.umich.edu assert(!pkt->isResponse()); 4745647Sgblack@eecs.umich.edu assert(pkt->cmd == orig_cmd); 4755647Sgblack@eecs.umich.edu pkt->cmd = snoop_response_cmd; 4765647Sgblack@eecs.umich.edu response_latency = snoop_response_latency; 4775647Sgblack@eecs.umich.edu } 4785647Sgblack@eecs.umich.edu 4795647Sgblack@eecs.umich.edu // why do we have this packet field and the return value both??? 4805647Sgblack@eecs.umich.edu pkt->finishTime = curTick() + response_latency; 4815647Sgblack@eecs.umich.edu return response_latency; 4825647Sgblack@eecs.umich.edu} 4835647Sgblack@eecs.umich.edu 4845647Sgblack@eecs.umich.edu/** Function called by the port when the bus is receiving a Functional 4855647Sgblack@eecs.umich.edu * transaction.*/ 4865647Sgblack@eecs.umich.eduvoid 4875647Sgblack@eecs.umich.eduBus::recvFunctional(PacketPtr pkt) 4885647Sgblack@eecs.umich.edu{ 4895647Sgblack@eecs.umich.edu if (!pkt->isPrint()) { 4905647Sgblack@eecs.umich.edu // don't do DPRINTFs on PrintReq as it clutters up the output 4915647Sgblack@eecs.umich.edu DPRINTF(Bus, 4925647Sgblack@eecs.umich.edu "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", 4935647Sgblack@eecs.umich.edu pkt->getSrc(), pkt->getDest(), pkt->getAddr(), 4945647Sgblack@eecs.umich.edu pkt->cmdString()); 4956046Sgblack@eecs.umich.edu } 4966046Sgblack@eecs.umich.edu 4976046Sgblack@eecs.umich.edu // we should always see a request routed based on the address 4986046Sgblack@eecs.umich.edu assert(pkt->getDest() == Packet::Broadcast); 4996046Sgblack@eecs.umich.edu assert(pkt->isRequest()); 5006046Sgblack@eecs.umich.edu 5016046Sgblack@eecs.umich.edu // the packet may be changed by another bus on snoops, record the 5026046Sgblack@eecs.umich.edu // source id here 5036046Sgblack@eecs.umich.edu Packet::NodeID src_id = pkt->getSrc(); 5046046Sgblack@eecs.umich.edu 5056046Sgblack@eecs.umich.edu SnoopIter s_end = snoopPorts.end(); 5066712Snate@binkert.org for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { 5076046Sgblack@eecs.umich.edu BusPort *p = *s_iter; 5086046Sgblack@eecs.umich.edu // we could have gotten this request from a snooping master 5096046Sgblack@eecs.umich.edu // (corresponding to our own slave port that is also in 5106046Sgblack@eecs.umich.edu // snoopPorts) and should not send it back to where it came 5116046Sgblack@eecs.umich.edu // from 5126046Sgblack@eecs.umich.edu if (p->getId() != src_id) { 5136046Sgblack@eecs.umich.edu p->sendFunctional(pkt); 5146065Sgblack@eecs.umich.edu 5156065Sgblack@eecs.umich.edu // if we get a response we are done 5166138Sgblack@eecs.umich.edu if (pkt->isResponse()) { 5176138Sgblack@eecs.umich.edu break; 5186046Sgblack@eecs.umich.edu } 5196046Sgblack@eecs.umich.edu } 5206138Sgblack@eecs.umich.edu } 5216138Sgblack@eecs.umich.edu 5226138Sgblack@eecs.umich.edu // there is no need to continue if the snooping has found what we 5236138Sgblack@eecs.umich.edu // were looking for and the packet is already a response 5246138Sgblack@eecs.umich.edu if (!pkt->isResponse()) { 5256138Sgblack@eecs.umich.edu int dest_id = findPort(pkt->getAddr()); 5266138Sgblack@eecs.umich.edu 5276138Sgblack@eecs.umich.edu // if this is a snoop from a slave (corresponding to our own 5286138Sgblack@eecs.umich.edu // master), i.e. the memory side of the bus, then do not send 5296138Sgblack@eecs.umich.edu // it back to where it came from, 5306138Sgblack@eecs.umich.edu if (dest_id != src_id) { 5316138Sgblack@eecs.umich.edu interfaces[dest_id]->sendFunctional(pkt); 5326138Sgblack@eecs.umich.edu } 5336138Sgblack@eecs.umich.edu } 5346138Sgblack@eecs.umich.edu} 5356138Sgblack@eecs.umich.edu 5366138Sgblack@eecs.umich.edu/** Function called by the port when the bus is receiving a range change.*/ 5376138Sgblack@eecs.umich.eduvoid 5386138Sgblack@eecs.umich.eduBus::recvRangeChange(int id) 5396138Sgblack@eecs.umich.edu{ 5406138Sgblack@eecs.umich.edu AddrRangeList ranges; 5416138Sgblack@eecs.umich.edu AddrRangeIter iter; 5426138Sgblack@eecs.umich.edu 5436138Sgblack@eecs.umich.edu if (inRecvRangeChange.count(id)) 5446138Sgblack@eecs.umich.edu return; 5456138Sgblack@eecs.umich.edu inRecvRangeChange.insert(id); 5466138Sgblack@eecs.umich.edu 5476138Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id); 5486138Sgblack@eecs.umich.edu 5496138Sgblack@eecs.umich.edu clearPortCache(); 5506138Sgblack@eecs.umich.edu if (id == defaultPortId) { 5516046Sgblack@eecs.umich.edu defaultRange.clear(); 5526046Sgblack@eecs.umich.edu // Only try to update these ranges if the user set a default responder. 5536069Sgblack@eecs.umich.edu if (useDefaultRange) { 5546069Sgblack@eecs.umich.edu AddrRangeList ranges = interfaces[id]->getPeer()->getAddrRanges(); 5556069Sgblack@eecs.umich.edu for(iter = ranges.begin(); iter != ranges.end(); iter++) { 5566046Sgblack@eecs.umich.edu defaultRange.push_back(*iter); 5576046Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", 5586069Sgblack@eecs.umich.edu iter->start, iter->end); 5596069Sgblack@eecs.umich.edu } 5606069Sgblack@eecs.umich.edu } 5616046Sgblack@eecs.umich.edu } else { 5626069Sgblack@eecs.umich.edu 5636069Sgblack@eecs.umich.edu assert(id < interfaces.size() && id >= 0); 5646138Sgblack@eecs.umich.edu BusPort *port = interfaces[id]; 5656138Sgblack@eecs.umich.edu 5666069Sgblack@eecs.umich.edu // Clean out any previously existent ids 5676069Sgblack@eecs.umich.edu for (PortIter portIter = portMap.begin(); 5686069Sgblack@eecs.umich.edu portIter != portMap.end(); ) { 5696046Sgblack@eecs.umich.edu if (portIter->second == id) 5706046Sgblack@eecs.umich.edu portMap.erase(portIter++); 5716138Sgblack@eecs.umich.edu else 5728922Swilliam.wang@arm.com portIter++; 5736138Sgblack@eecs.umich.edu } 5746046Sgblack@eecs.umich.edu 5755647Sgblack@eecs.umich.edu ranges = port->getPeer()->getAddrRanges(); 5765647Sgblack@eecs.umich.edu 5775647Sgblack@eecs.umich.edu for (iter = ranges.begin(); iter != ranges.end(); iter++) { 5785647Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", 5795647Sgblack@eecs.umich.edu iter->start, iter->end, id); 5805647Sgblack@eecs.umich.edu if (portMap.insert(*iter, id) == portMap.end()) { 5815647Sgblack@eecs.umich.edu int conflict_id = portMap.find(*iter)->second; 5825647Sgblack@eecs.umich.edu fatal("%s has two ports with same range:\n\t%s\n\t%s\n", 5835647Sgblack@eecs.umich.edu name(), interfaces[id]->getPeer()->name(), 5845647Sgblack@eecs.umich.edu interfaces[conflict_id]->getPeer()->name()); 5855647Sgblack@eecs.umich.edu } 5865647Sgblack@eecs.umich.edu } 5875647Sgblack@eecs.umich.edu } 5885647Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "port list has %d entries\n", portMap.size()); 5895648Sgblack@eecs.umich.edu 5905648Sgblack@eecs.umich.edu // tell all our peers that our address range has changed. 5915648Sgblack@eecs.umich.edu // Don't tell the device that caused this change, it already knows 5925848Sgblack@eecs.umich.edu std::vector<BusPort*>::const_iterator intIter; 5935848Sgblack@eecs.umich.edu 5945848Sgblack@eecs.umich.edu for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) 5955648Sgblack@eecs.umich.edu if ((*intIter)->getId() != id) 5967823Ssteve.reinhardt@amd.com (*intIter)->sendRangeChange(); 5975648Sgblack@eecs.umich.edu 5985648Sgblack@eecs.umich.edu inRecvRangeChange.erase(id); 5997823Ssteve.reinhardt@amd.com} 6005648Sgblack@eecs.umich.edu 6015648Sgblack@eecs.umich.eduAddrRangeList 6027823Ssteve.reinhardt@amd.comBus::getAddrRanges(int id) 6035648Sgblack@eecs.umich.edu{ 6045648Sgblack@eecs.umich.edu AddrRangeList ranges; 6055647Sgblack@eecs.umich.edu 6065647Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "received address range request, returning:\n"); 6075647Sgblack@eecs.umich.edu 6085647Sgblack@eecs.umich.edu for (AddrRangeIter dflt_iter = defaultRange.begin(); 6095647Sgblack@eecs.umich.edu dflt_iter != defaultRange.end(); dflt_iter++) { 6105647Sgblack@eecs.umich.edu ranges.push_back(*dflt_iter); 6115647Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start, 6125647Sgblack@eecs.umich.edu dflt_iter->end); 6135647Sgblack@eecs.umich.edu } 6145647Sgblack@eecs.umich.edu for (PortIter portIter = portMap.begin(); 6155648Sgblack@eecs.umich.edu portIter != portMap.end(); portIter++) { 6165647Sgblack@eecs.umich.edu bool subset = false; 6175647Sgblack@eecs.umich.edu for (AddrRangeIter dflt_iter = defaultRange.begin(); 6185647Sgblack@eecs.umich.edu dflt_iter != defaultRange.end(); dflt_iter++) { 6196041Sgblack@eecs.umich.edu if ((portIter->first.start < dflt_iter->start && 6206041Sgblack@eecs.umich.edu portIter->first.end >= dflt_iter->start) || 6217900Shestness@cs.utexas.edu (portIter->first.start < dflt_iter->end && 6227900Shestness@cs.utexas.edu portIter->first.end >= dflt_iter->end)) 6236041Sgblack@eecs.umich.edu fatal("Devices can not set ranges that itersect the default set\ 6246041Sgblack@eecs.umich.edu but are not a subset of the default set.\n"); 6256041Sgblack@eecs.umich.edu if (portIter->first.start >= dflt_iter->start && 6266041Sgblack@eecs.umich.edu portIter->first.end <= dflt_iter->end) { 6276041Sgblack@eecs.umich.edu subset = true; 6286050Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n", 6296069Sgblack@eecs.umich.edu portIter->first.start, portIter->first.end); 6308851Sandreas.hansson@arm.com } 6318851Sandreas.hansson@arm.com } 6326041Sgblack@eecs.umich.edu if (portIter->second != id && !subset) { 6336041Sgblack@eecs.umich.edu ranges.push_back(portIter->first); 6346041Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", 6356041Sgblack@eecs.umich.edu portIter->first.start, portIter->first.end); 6366041Sgblack@eecs.umich.edu } 6376041Sgblack@eecs.umich.edu } 6386041Sgblack@eecs.umich.edu 6396041Sgblack@eecs.umich.edu return ranges; 6406041Sgblack@eecs.umich.edu} 6416041Sgblack@eecs.umich.edu 6425654Sgblack@eecs.umich.edubool 6435704Snate@binkert.orgBus::isSnooping(int id) 6445654Sgblack@eecs.umich.edu{ 6455654Sgblack@eecs.umich.edu // in essence, answer the question if there are snooping ports 6465689Sgblack@eecs.umich.edu return !snoopPorts.empty(); 6475689Sgblack@eecs.umich.edu} 6485654Sgblack@eecs.umich.edu 6495689Sgblack@eecs.umich.eduunsigned 6505655Sgblack@eecs.umich.eduBus::findBlockSize(int id) 6515689Sgblack@eecs.umich.edu{ 6525689Sgblack@eecs.umich.edu if (cachedBlockSizeValid) 6535655Sgblack@eecs.umich.edu return cachedBlockSize; 6545689Sgblack@eecs.umich.edu 6555655Sgblack@eecs.umich.edu unsigned max_bs = 0; 6565689Sgblack@eecs.umich.edu 6575689Sgblack@eecs.umich.edu PortIter p_end = portMap.end(); 6585655Sgblack@eecs.umich.edu for (PortIter p_iter = portMap.begin(); p_iter != p_end; p_iter++) { 6595689Sgblack@eecs.umich.edu unsigned tmp_bs = interfaces[p_iter->second]->peerBlockSize(); 6605654Sgblack@eecs.umich.edu if (tmp_bs > max_bs) 6615654Sgblack@eecs.umich.edu max_bs = tmp_bs; 6625654Sgblack@eecs.umich.edu } 6635654Sgblack@eecs.umich.edu SnoopIter s_end = snoopPorts.end(); 6645654Sgblack@eecs.umich.edu for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { 6655704Snate@binkert.org unsigned tmp_bs = (*s_iter)->peerBlockSize(); 6665654Sgblack@eecs.umich.edu if (tmp_bs > max_bs) 6675704Snate@binkert.org max_bs = tmp_bs; 6685655Sgblack@eecs.umich.edu } 6695655Sgblack@eecs.umich.edu if (max_bs == 0) 6705655Sgblack@eecs.umich.edu max_bs = defaultBlockSize; 6715655Sgblack@eecs.umich.edu 6725689Sgblack@eecs.umich.edu if (max_bs != 64) 6735655Sgblack@eecs.umich.edu warn_once("Blocksize found to not be 64... hmm... probably not.\n"); 6745655Sgblack@eecs.umich.edu cachedBlockSize = max_bs; 6755689Sgblack@eecs.umich.edu cachedBlockSizeValid = true; 6765691Sgblack@eecs.umich.edu return max_bs; 6775655Sgblack@eecs.umich.edu} 6785689Sgblack@eecs.umich.edu 6795691Sgblack@eecs.umich.edu 6806050Sgblack@eecs.umich.eduunsigned int 6816050Sgblack@eecs.umich.eduBus::drain(Event * de) 6826050Sgblack@eecs.umich.edu{ 6835655Sgblack@eecs.umich.edu //We should check that we're not "doing" anything, and that noone is 6845655Sgblack@eecs.umich.edu //waiting. We might be idle but have someone waiting if the device we 6855655Sgblack@eecs.umich.edu //contacted for a retry didn't actually retry. 6865655Sgblack@eecs.umich.edu if (!retryList.empty() || (curTick() < tickNextIdle && 6875655Sgblack@eecs.umich.edu busIdleEvent.scheduled())) { 6885655Sgblack@eecs.umich.edu drainEvent = de; 6895689Sgblack@eecs.umich.edu return 1; 6905691Sgblack@eecs.umich.edu } 6915655Sgblack@eecs.umich.edu return 0; 6925689Sgblack@eecs.umich.edu} 6935655Sgblack@eecs.umich.edu 6945655Sgblack@eecs.umich.eduvoid 6955655Sgblack@eecs.umich.eduBus::startup() 6965654Sgblack@eecs.umich.edu{ 6975654Sgblack@eecs.umich.edu if (tickNextIdle < curTick()) 6985654Sgblack@eecs.umich.edu tickNextIdle = (curTick() / clock) * clock + clock; 6995704Snate@binkert.org} 7005654Sgblack@eecs.umich.edu 7015704Snate@binkert.orgBus * 7025655Sgblack@eecs.umich.eduBusParams::create() 7035655Sgblack@eecs.umich.edu{ 7045689Sgblack@eecs.umich.edu return new Bus(this); 7055655Sgblack@eecs.umich.edu} 7065655Sgblack@eecs.umich.edu