xbar.cc revision 3244
15245Sgblack@eecs.umich.edu/* 25245Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan 35245Sgblack@eecs.umich.edu * All rights reserved. 45245Sgblack@eecs.umich.edu * 55245Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 65245Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 75245Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 85245Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 95245Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 105245Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 115245Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 125245Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 135245Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 145245Sgblack@eecs.umich.edu * this software without specific prior written permission. 155245Sgblack@eecs.umich.edu * 165245Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175245Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185245Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195245Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205245Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215245Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225245Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235245Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245245Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255245Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265245Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275245Sgblack@eecs.umich.edu * 285245Sgblack@eecs.umich.edu * Authors: Ali Saidi 295245Sgblack@eecs.umich.edu */ 305245Sgblack@eecs.umich.edu 315245Sgblack@eecs.umich.edu/** 325245Sgblack@eecs.umich.edu * @file 335245Sgblack@eecs.umich.edu * Definition of a bus object. 345245Sgblack@eecs.umich.edu */ 355245Sgblack@eecs.umich.edu 365245Sgblack@eecs.umich.edu 375245Sgblack@eecs.umich.edu#include "base/misc.hh" 385245Sgblack@eecs.umich.edu#include "base/trace.hh" 395245Sgblack@eecs.umich.edu#include "mem/bus.hh" 405245Sgblack@eecs.umich.edu#include "sim/builder.hh" 415245Sgblack@eecs.umich.edu 425245Sgblack@eecs.umich.eduPort * 435245Sgblack@eecs.umich.eduBus::getPort(const std::string &if_name, int idx) 445245Sgblack@eecs.umich.edu{ 455245Sgblack@eecs.umich.edu if (if_name == "default") 465245Sgblack@eecs.umich.edu if (defaultPort == NULL) { 475245Sgblack@eecs.umich.edu defaultPort = new BusPort(csprintf("%s-default",name()), this, 485245Sgblack@eecs.umich.edu defaultId); 495245Sgblack@eecs.umich.edu return defaultPort; 505245Sgblack@eecs.umich.edu } else 515245Sgblack@eecs.umich.edu fatal("Default port already set\n"); 525245Sgblack@eecs.umich.edu 535245Sgblack@eecs.umich.edu // if_name ignored? forced to be empty? 545245Sgblack@eecs.umich.edu int id = interfaces.size(); 555245Sgblack@eecs.umich.edu BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id); 565245Sgblack@eecs.umich.edu interfaces.push_back(bp); 575245Sgblack@eecs.umich.edu return bp; 585245Sgblack@eecs.umich.edu} 595245Sgblack@eecs.umich.edu 605245Sgblack@eecs.umich.edu/** Get the ranges of anyone other buses that we are connected to. */ 615245Sgblack@eecs.umich.eduvoid 625245Sgblack@eecs.umich.eduBus::init() 635245Sgblack@eecs.umich.edu{ 645245Sgblack@eecs.umich.edu std::vector<BusPort*>::iterator intIter; 655245Sgblack@eecs.umich.edu 665245Sgblack@eecs.umich.edu for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) 675245Sgblack@eecs.umich.edu (*intIter)->sendStatusChange(Port::RangeChange); 685245Sgblack@eecs.umich.edu} 695245Sgblack@eecs.umich.edu 705245Sgblack@eecs.umich.eduBus::BusFreeEvent::BusFreeEvent(Bus *_bus) : Event(&mainEventQueue), bus(_bus) 715245Sgblack@eecs.umich.edu{} 725245Sgblack@eecs.umich.edu 735245Sgblack@eecs.umich.eduvoid Bus::BusFreeEvent::process() 745245Sgblack@eecs.umich.edu{ 755245Sgblack@eecs.umich.edu bus->recvRetry(-1); 765245Sgblack@eecs.umich.edu} 775245Sgblack@eecs.umich.edu 785245Sgblack@eecs.umich.educonst char * Bus::BusFreeEvent::description() 795245Sgblack@eecs.umich.edu{ 805245Sgblack@eecs.umich.edu return "bus became available"; 815245Sgblack@eecs.umich.edu} 825245Sgblack@eecs.umich.edu 835245Sgblack@eecs.umich.eduvoid Bus::occupyBus(PacketPtr pkt) 845245Sgblack@eecs.umich.edu{ 855245Sgblack@eecs.umich.edu //Bring tickNextIdle up to the present tick 865245Sgblack@eecs.umich.edu //There is some potential ambiguity where a cycle starts, which might make 875895Sgblack@eecs.umich.edu //a difference when devices are acting right around a cycle boundary. Using 885897Sgblack@eecs.umich.edu //a < allows things which happen exactly on a cycle boundary to take up only 895245Sgblack@eecs.umich.edu //the following cycle. Anthing that happens later will have to "wait" for 905245Sgblack@eecs.umich.edu //the end of that cycle, and then start using the bus after that. 915245Sgblack@eecs.umich.edu while (tickNextIdle < curTick) 925245Sgblack@eecs.umich.edu tickNextIdle += clock; 935245Sgblack@eecs.umich.edu 945245Sgblack@eecs.umich.edu // The packet will be sent. Figure out how long it occupies the bus, and 955245Sgblack@eecs.umich.edu // how much of that time is for the first "word", aka bus width. 965245Sgblack@eecs.umich.edu int numCycles = 0; 975245Sgblack@eecs.umich.edu // Requests need one cycle to send an address 985245Sgblack@eecs.umich.edu if (pkt->isRequest()) 995245Sgblack@eecs.umich.edu numCycles++; 1005245Sgblack@eecs.umich.edu else if (pkt->isResponse() || pkt->hasData()) { 1016027Sgblack@eecs.umich.edu // If a packet has data, it needs ceil(size/width) cycles to send it 1025245Sgblack@eecs.umich.edu // We're using the "adding instead of dividing" trick again here 1035245Sgblack@eecs.umich.edu if (pkt->hasData()) { 1045904Sgblack@eecs.umich.edu int dataSize = pkt->getSize(); 1055904Sgblack@eecs.umich.edu for (int transmitted = 0; transmitted < dataSize; 1065245Sgblack@eecs.umich.edu transmitted += width) { 1075245Sgblack@eecs.umich.edu numCycles++; 1085245Sgblack@eecs.umich.edu } 1095245Sgblack@eecs.umich.edu } else { 1105245Sgblack@eecs.umich.edu // If the packet didn't have data, it must have been a response. 1115895Sgblack@eecs.umich.edu // Those use the bus for one cycle to send their data. 1125895Sgblack@eecs.umich.edu numCycles++; 1135895Sgblack@eecs.umich.edu } 1145895Sgblack@eecs.umich.edu } 1155245Sgblack@eecs.umich.edu 1165245Sgblack@eecs.umich.edu // The first word will be delivered after the current tick, the delivery 1175245Sgblack@eecs.umich.edu // of the address if any, and one bus cycle to deliver the data 1185245Sgblack@eecs.umich.edu pkt->firstWordTime = 1195904Sgblack@eecs.umich.edu tickNextIdle + 1205904Sgblack@eecs.umich.edu pkt->isRequest() ? clock : 0 + 1215245Sgblack@eecs.umich.edu clock; 1225245Sgblack@eecs.umich.edu 1235245Sgblack@eecs.umich.edu //Advance it numCycles bus cycles. 1245245Sgblack@eecs.umich.edu //XXX Should this use the repeated addition trick as well? 1255245Sgblack@eecs.umich.edu tickNextIdle += (numCycles * clock); 1265895Sgblack@eecs.umich.edu if (!busIdle.scheduled()) { 1275895Sgblack@eecs.umich.edu busIdle.schedule(tickNextIdle); 1285895Sgblack@eecs.umich.edu } else { 1295895Sgblack@eecs.umich.edu busIdle.reschedule(tickNextIdle); 1305245Sgblack@eecs.umich.edu } 1315245Sgblack@eecs.umich.edu DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n", 1325245Sgblack@eecs.umich.edu curTick, tickNextIdle); 1335904Sgblack@eecs.umich.edu 1345904Sgblack@eecs.umich.edu // The bus will become idle once the current packet is delivered. 1355245Sgblack@eecs.umich.edu pkt->finishTime = tickNextIdle; 1365245Sgblack@eecs.umich.edu} 1375245Sgblack@eecs.umich.edu 1385245Sgblack@eecs.umich.edu/** Function called by the port when the bus is receiving a Timing 1395895Sgblack@eecs.umich.edu * transaction.*/ 1405895Sgblack@eecs.umich.edubool 1415895Sgblack@eecs.umich.eduBus::recvTiming(Packet *pkt) 1425895Sgblack@eecs.umich.edu{ 1435245Sgblack@eecs.umich.edu Port *port; 1445245Sgblack@eecs.umich.edu DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n", 1455245Sgblack@eecs.umich.edu pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); 1465245Sgblack@eecs.umich.edu 1475245Sgblack@eecs.umich.edu BusPort *pktPort = interfaces[pkt->getSrc()]; 1485245Sgblack@eecs.umich.edu 1495245Sgblack@eecs.umich.edu // If the bus is busy, or other devices are in line ahead of the current 1505245Sgblack@eecs.umich.edu // one, put this device on the retry list. 1515245Sgblack@eecs.umich.edu if (tickNextIdle > curTick || 1525245Sgblack@eecs.umich.edu (retryList.size() && (!inRetry || pktPort != retryList.front()))) { 1535245Sgblack@eecs.umich.edu addToRetryList(pktPort); 1545245Sgblack@eecs.umich.edu return false; 1555245Sgblack@eecs.umich.edu } 1565245Sgblack@eecs.umich.edu 1575245Sgblack@eecs.umich.edu short dest = pkt->getDest(); 1585245Sgblack@eecs.umich.edu if (dest == Packet::Broadcast) { 1595895Sgblack@eecs.umich.edu if (timingSnoop(pkt)) { 1605895Sgblack@eecs.umich.edu pkt->flags |= SNOOP_COMMIT; 1615245Sgblack@eecs.umich.edu bool success = timingSnoop(pkt); 1625245Sgblack@eecs.umich.edu assert(success); 1635904Sgblack@eecs.umich.edu if (pkt->flags & SATISFIED) { 1645904Sgblack@eecs.umich.edu //Cache-Cache transfer occuring 1655245Sgblack@eecs.umich.edu if (inRetry) { 1665245Sgblack@eecs.umich.edu retryList.front()->onRetryList(false); 1675245Sgblack@eecs.umich.edu retryList.pop_front(); 1685245Sgblack@eecs.umich.edu inRetry = false; 1695895Sgblack@eecs.umich.edu } 1705895Sgblack@eecs.umich.edu occupyBus(pkt); 1715895Sgblack@eecs.umich.edu return true; 1725895Sgblack@eecs.umich.edu } 1735245Sgblack@eecs.umich.edu port = findPort(pkt->getAddr(), pkt->getSrc()); 1745245Sgblack@eecs.umich.edu } else { 1755245Sgblack@eecs.umich.edu //Snoop didn't succeed 1765245Sgblack@eecs.umich.edu addToRetryList(pktPort); 1775245Sgblack@eecs.umich.edu return false; 1785245Sgblack@eecs.umich.edu } 1795895Sgblack@eecs.umich.edu } else { 1805895Sgblack@eecs.umich.edu assert(dest >= 0 && dest < interfaces.size()); 1815245Sgblack@eecs.umich.edu assert(dest != pkt->getSrc()); // catch infinite loops 1825904Sgblack@eecs.umich.edu port = interfaces[dest]; 1835904Sgblack@eecs.umich.edu } 1845245Sgblack@eecs.umich.edu 1855895Sgblack@eecs.umich.edu occupyBus(pkt); 1865895Sgblack@eecs.umich.edu 1875895Sgblack@eecs.umich.edu if (port->sendTiming(pkt)) { 1885895Sgblack@eecs.umich.edu // Packet was successfully sent. Return true. 1895245Sgblack@eecs.umich.edu // Also take care of retries 1905245Sgblack@eecs.umich.edu if (inRetry) { 1915245Sgblack@eecs.umich.edu retryList.front()->onRetryList(false); 1925904Sgblack@eecs.umich.edu retryList.pop_front(); 1935904Sgblack@eecs.umich.edu inRetry = false; 1945245Sgblack@eecs.umich.edu } 1955245Sgblack@eecs.umich.edu return true; 1965245Sgblack@eecs.umich.edu } 1975245Sgblack@eecs.umich.edu 1985895Sgblack@eecs.umich.edu // Packet not successfully sent. Leave or put it on the retry list. 1995895Sgblack@eecs.umich.edu addToRetryList(pktPort); 2005895Sgblack@eecs.umich.edu return false; 2015895Sgblack@eecs.umich.edu} 2025245Sgblack@eecs.umich.edu 2035245Sgblack@eecs.umich.eduvoid 2045245Sgblack@eecs.umich.eduBus::recvRetry(int id) 2055245Sgblack@eecs.umich.edu{ 2065245Sgblack@eecs.umich.edu // If there's anything waiting... 2075245Sgblack@eecs.umich.edu if (retryList.size()) { 2085245Sgblack@eecs.umich.edu //retryingPort = retryList.front(); 2095245Sgblack@eecs.umich.edu inRetry = true; 2105245Sgblack@eecs.umich.edu retryList.front()->sendRetry(); 2115245Sgblack@eecs.umich.edu // If inRetry is still true, sendTiming wasn't called 2125245Sgblack@eecs.umich.edu if (inRetry) 2135245Sgblack@eecs.umich.edu panic("Port %s didn't call sendTiming in it's recvRetry\n",\ 2145245Sgblack@eecs.umich.edu retryList.front()->getPeer()->name()); 2155245Sgblack@eecs.umich.edu //assert(!inRetry); 2165245Sgblack@eecs.umich.edu } 2175895Sgblack@eecs.umich.edu} 2185895Sgblack@eecs.umich.edu 2195245Sgblack@eecs.umich.eduPort * 2205245Sgblack@eecs.umich.eduBus::findPort(Addr addr, int id) 2215904Sgblack@eecs.umich.edu{ 2225904Sgblack@eecs.umich.edu /* An interval tree would be a better way to do this. --ali. */ 2235245Sgblack@eecs.umich.edu int dest_id = -1; 2245245Sgblack@eecs.umich.edu int i = 0; 2255245Sgblack@eecs.umich.edu bool found = false; 2265245Sgblack@eecs.umich.edu AddrRangeIter iter; 2275895Sgblack@eecs.umich.edu 2285895Sgblack@eecs.umich.edu while (i < portList.size() && !found) 2295895Sgblack@eecs.umich.edu { 2305895Sgblack@eecs.umich.edu if (portList[i].range == addr) { 2315245Sgblack@eecs.umich.edu dest_id = portList[i].portId; 2325245Sgblack@eecs.umich.edu found = true; 2335245Sgblack@eecs.umich.edu DPRINTF(Bus, " found addr %#llx on device %d\n", addr, dest_id); 2345245Sgblack@eecs.umich.edu } 2355245Sgblack@eecs.umich.edu i++; 2365245Sgblack@eecs.umich.edu } 2375895Sgblack@eecs.umich.edu 2385895Sgblack@eecs.umich.edu // Check if this matches the default range 2395245Sgblack@eecs.umich.edu if (dest_id == -1) { 2405904Sgblack@eecs.umich.edu for (iter = defaultRange.begin(); iter != defaultRange.end(); iter++) { 2415904Sgblack@eecs.umich.edu if (*iter == addr) { 2425245Sgblack@eecs.umich.edu DPRINTF(Bus, " found addr %#llx on default\n", addr); 2435245Sgblack@eecs.umich.edu return defaultPort; 2445245Sgblack@eecs.umich.edu } 2455245Sgblack@eecs.umich.edu } 2465895Sgblack@eecs.umich.edu panic("Unable to find destination for addr: %#llx", addr); 2475895Sgblack@eecs.umich.edu } 2485895Sgblack@eecs.umich.edu 2495895Sgblack@eecs.umich.edu 2505245Sgblack@eecs.umich.edu // we shouldn't be sending this back to where it came from 2515245Sgblack@eecs.umich.edu assert(dest_id != id); 2525245Sgblack@eecs.umich.edu 2535245Sgblack@eecs.umich.edu return interfaces[dest_id]; 2545245Sgblack@eecs.umich.edu} 2555245Sgblack@eecs.umich.edu 2565245Sgblack@eecs.umich.edustd::vector<int> 2575245Sgblack@eecs.umich.eduBus::findSnoopPorts(Addr addr, int id) 2585245Sgblack@eecs.umich.edu{ 2595245Sgblack@eecs.umich.edu int i = 0; 2605245Sgblack@eecs.umich.edu AddrRangeIter iter; 2615245Sgblack@eecs.umich.edu std::vector<int> ports; 2625245Sgblack@eecs.umich.edu 2635245Sgblack@eecs.umich.edu while (i < portSnoopList.size()) 2645245Sgblack@eecs.umich.edu { 2655245Sgblack@eecs.umich.edu if (portSnoopList[i].range == addr && portSnoopList[i].portId != id) { 2665895Sgblack@eecs.umich.edu //Careful to not overlap ranges 2675895Sgblack@eecs.umich.edu //or snoop will be called more than once on the port 2685245Sgblack@eecs.umich.edu ports.push_back(portSnoopList[i].portId); 2695245Sgblack@eecs.umich.edu DPRINTF(Bus, " found snoop addr %#llx on device%d\n", addr, 2705904Sgblack@eecs.umich.edu portSnoopList[i].portId); 2715904Sgblack@eecs.umich.edu } 2725245Sgblack@eecs.umich.edu i++; 2735245Sgblack@eecs.umich.edu } 2745245Sgblack@eecs.umich.edu return ports; 2755245Sgblack@eecs.umich.edu} 2765895Sgblack@eecs.umich.edu 2775895Sgblack@eecs.umich.eduvoid 2785895Sgblack@eecs.umich.eduBus::atomicSnoop(Packet *pkt) 2795895Sgblack@eecs.umich.edu{ 2805245Sgblack@eecs.umich.edu std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); 2815245Sgblack@eecs.umich.edu 2825245Sgblack@eecs.umich.edu while (!ports.empty()) 2835245Sgblack@eecs.umich.edu { 2845245Sgblack@eecs.umich.edu interfaces[ports.back()]->sendAtomic(pkt); 2855245Sgblack@eecs.umich.edu ports.pop_back(); 2865904Sgblack@eecs.umich.edu } 2875904Sgblack@eecs.umich.edu} 2885245Sgblack@eecs.umich.edu 2895245Sgblack@eecs.umich.eduvoid 2905245Sgblack@eecs.umich.eduBus::functionalSnoop(Packet *pkt) 2915245Sgblack@eecs.umich.edu{ 2925895Sgblack@eecs.umich.edu std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); 2935895Sgblack@eecs.umich.edu 2945895Sgblack@eecs.umich.edu while (!ports.empty()) 2955895Sgblack@eecs.umich.edu { 2965245Sgblack@eecs.umich.edu interfaces[ports.back()]->sendFunctional(pkt); 2975245Sgblack@eecs.umich.edu ports.pop_back(); 2985245Sgblack@eecs.umich.edu } 2995245Sgblack@eecs.umich.edu} 3005245Sgblack@eecs.umich.edu 3015245Sgblack@eecs.umich.edubool 3025895Sgblack@eecs.umich.eduBus::timingSnoop(Packet *pkt) 3035895Sgblack@eecs.umich.edu{ 3045245Sgblack@eecs.umich.edu std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); 3055245Sgblack@eecs.umich.edu bool success = true; 3065245Sgblack@eecs.umich.edu 3075245Sgblack@eecs.umich.edu while (!ports.empty() && success) 3085245Sgblack@eecs.umich.edu { 3095736Snate@binkert.org success = interfaces[ports.back()]->sendTiming(pkt); 3105736Snate@binkert.org ports.pop_back(); 3115245Sgblack@eecs.umich.edu } 3125245Sgblack@eecs.umich.edu 3135245Sgblack@eecs.umich.edu return success; 3145245Sgblack@eecs.umich.edu} 3155245Sgblack@eecs.umich.edu 3165245Sgblack@eecs.umich.edu 3175245Sgblack@eecs.umich.edu/** Function called by the port when the bus is receiving a Atomic 3185245Sgblack@eecs.umich.edu * transaction.*/ 3195245Sgblack@eecs.umich.eduTick 3205245Sgblack@eecs.umich.eduBus::recvAtomic(Packet *pkt) 3215245Sgblack@eecs.umich.edu{ 3225245Sgblack@eecs.umich.edu DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n", 3235245Sgblack@eecs.umich.edu pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); 3245245Sgblack@eecs.umich.edu assert(pkt->getDest() == Packet::Broadcast); 3255245Sgblack@eecs.umich.edu atomicSnoop(pkt); 3265245Sgblack@eecs.umich.edu return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt); 3275895Sgblack@eecs.umich.edu} 3285245Sgblack@eecs.umich.edu 3295245Sgblack@eecs.umich.edu/** Function called by the port when the bus is receiving a Functional 3305895Sgblack@eecs.umich.edu * transaction.*/ 3315895Sgblack@eecs.umich.eduvoid 3326023Snate@binkert.orgBus::recvFunctional(Packet *pkt) 3335245Sgblack@eecs.umich.edu{ 3345245Sgblack@eecs.umich.edu DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", 3355245Sgblack@eecs.umich.edu pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); 3365895Sgblack@eecs.umich.edu assert(pkt->getDest() == Packet::Broadcast); 3375895Sgblack@eecs.umich.edu functionalSnoop(pkt); 3386023Snate@binkert.org findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt); 3395895Sgblack@eecs.umich.edu} 3405245Sgblack@eecs.umich.edu 3415245Sgblack@eecs.umich.edu/** Function called by the port when the bus is receiving a status change.*/ 3425245Sgblack@eecs.umich.eduvoid 3435245Sgblack@eecs.umich.eduBus::recvStatusChange(Port::Status status, int id) 3445245Sgblack@eecs.umich.edu{ 3455245Sgblack@eecs.umich.edu AddrRangeList ranges; 3465245Sgblack@eecs.umich.edu AddrRangeList snoops; 3475245Sgblack@eecs.umich.edu int x; 3485245Sgblack@eecs.umich.edu AddrRangeIter iter; 3495245Sgblack@eecs.umich.edu 3505245Sgblack@eecs.umich.edu assert(status == Port::RangeChange && 3515245Sgblack@eecs.umich.edu "The other statuses need to be implemented."); 3525245Sgblack@eecs.umich.edu 3535895Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id); 3545245Sgblack@eecs.umich.edu 3555245Sgblack@eecs.umich.edu if (id == defaultId) { 3565245Sgblack@eecs.umich.edu defaultRange.clear(); 3575245Sgblack@eecs.umich.edu defaultPort->getPeerAddressRanges(ranges, snoops); 3585245Sgblack@eecs.umich.edu assert(snoops.size() == 0); 3595245Sgblack@eecs.umich.edu for(iter = ranges.begin(); iter != ranges.end(); iter++) { 3605245Sgblack@eecs.umich.edu defaultRange.push_back(*iter); 3615895Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", 3625245Sgblack@eecs.umich.edu iter->start, iter->end); 3635245Sgblack@eecs.umich.edu } 3645245Sgblack@eecs.umich.edu } else { 3655245Sgblack@eecs.umich.edu 3665245Sgblack@eecs.umich.edu assert((id < interfaces.size() && id >= 0) || id == -1); 3675245Sgblack@eecs.umich.edu Port *port = interfaces[id]; 3685245Sgblack@eecs.umich.edu std::vector<DevMap>::iterator portIter; 3695245Sgblack@eecs.umich.edu std::vector<DevMap>::iterator snoopIter; 3705245Sgblack@eecs.umich.edu 3715245Sgblack@eecs.umich.edu // Clean out any previously existent ids 3725895Sgblack@eecs.umich.edu for (portIter = portList.begin(); portIter != portList.end(); ) { 3735245Sgblack@eecs.umich.edu if (portIter->portId == id) 3745245Sgblack@eecs.umich.edu portIter = portList.erase(portIter); 3755245Sgblack@eecs.umich.edu else 3765245Sgblack@eecs.umich.edu portIter++; 3775245Sgblack@eecs.umich.edu } 3785245Sgblack@eecs.umich.edu 3795736Snate@binkert.org for (snoopIter = portSnoopList.begin(); snoopIter != portSnoopList.end(); ) { 3805736Snate@binkert.org if (snoopIter->portId == id) 3815736Snate@binkert.org snoopIter = portSnoopList.erase(snoopIter); 3825736Snate@binkert.org else 3835245Sgblack@eecs.umich.edu snoopIter++; 3845245Sgblack@eecs.umich.edu } 3855245Sgblack@eecs.umich.edu 3865245Sgblack@eecs.umich.edu port->getPeerAddressRanges(ranges, snoops); 3875897Sgblack@eecs.umich.edu 3885897Sgblack@eecs.umich.edu for(iter = snoops.begin(); iter != snoops.end(); iter++) { 3895895Sgblack@eecs.umich.edu DevMap dm; 3905897Sgblack@eecs.umich.edu dm.portId = id; 3915245Sgblack@eecs.umich.edu dm.range = *iter; 3925895Sgblack@eecs.umich.edu 3935245Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "Adding snoop range %#llx - %#llx for id %d\n", 3945245Sgblack@eecs.umich.edu dm.range.start, dm.range.end, id); 3955245Sgblack@eecs.umich.edu portSnoopList.push_back(dm); 3965897Sgblack@eecs.umich.edu } 3975895Sgblack@eecs.umich.edu 3985245Sgblack@eecs.umich.edu for(iter = ranges.begin(); iter != ranges.end(); iter++) { 3995245Sgblack@eecs.umich.edu DevMap dm; 4005245Sgblack@eecs.umich.edu dm.portId = id; 4015245Sgblack@eecs.umich.edu dm.range = *iter; 4025245Sgblack@eecs.umich.edu 4035245Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", 4045245Sgblack@eecs.umich.edu dm.range.start, dm.range.end, id); 4055895Sgblack@eecs.umich.edu portList.push_back(dm); 4065245Sgblack@eecs.umich.edu } 4075245Sgblack@eecs.umich.edu } 4085245Sgblack@eecs.umich.edu DPRINTF(MMU, "port list has %d entries\n", portList.size()); 4095895Sgblack@eecs.umich.edu 4105245Sgblack@eecs.umich.edu // tell all our peers that our address range has changed. 4115245Sgblack@eecs.umich.edu // Don't tell the device that caused this change, it already knows 4125245Sgblack@eecs.umich.edu for (x = 0; x < interfaces.size(); x++) 4135245Sgblack@eecs.umich.edu if (x != id) 4145245Sgblack@eecs.umich.edu interfaces[x]->sendStatusChange(Port::RangeChange); 4155245Sgblack@eecs.umich.edu 4165245Sgblack@eecs.umich.edu if (id != defaultId && defaultPort) 4175245Sgblack@eecs.umich.edu defaultPort->sendStatusChange(Port::RangeChange); 4185245Sgblack@eecs.umich.edu} 4195245Sgblack@eecs.umich.edu 4205245Sgblack@eecs.umich.eduvoid 4215245Sgblack@eecs.umich.eduBus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) 4225897Sgblack@eecs.umich.edu{ 4235897Sgblack@eecs.umich.edu std::vector<DevMap>::iterator portIter; 4245897Sgblack@eecs.umich.edu AddrRangeIter dflt_iter; 4255897Sgblack@eecs.umich.edu bool subset; 4265245Sgblack@eecs.umich.edu 4275245Sgblack@eecs.umich.edu resp.clear(); 4285245Sgblack@eecs.umich.edu snoop.clear(); 4295245Sgblack@eecs.umich.edu 4305897Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, "received address range request, returning:\n"); 4315897Sgblack@eecs.umich.edu 4325245Sgblack@eecs.umich.edu for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end(); 4335895Sgblack@eecs.umich.edu dflt_iter++) { 4345245Sgblack@eecs.umich.edu resp.push_back(*dflt_iter); 4355245Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n",dflt_iter->start, 4365245Sgblack@eecs.umich.edu dflt_iter->end); 4375245Sgblack@eecs.umich.edu } 4385245Sgblack@eecs.umich.edu for (portIter = portList.begin(); portIter != portList.end(); portIter++) { 4395245Sgblack@eecs.umich.edu subset = false; 4405245Sgblack@eecs.umich.edu for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end(); 4415245Sgblack@eecs.umich.edu dflt_iter++) { 4425245Sgblack@eecs.umich.edu if ((portIter->range.start < dflt_iter->start && 4435245Sgblack@eecs.umich.edu portIter->range.end >= dflt_iter->start) || 4445895Sgblack@eecs.umich.edu (portIter->range.start < dflt_iter->end && 4455895Sgblack@eecs.umich.edu portIter->range.end >= dflt_iter->end)) 4465895Sgblack@eecs.umich.edu fatal("Devices can not set ranges that itersect the default set\ 4475895Sgblack@eecs.umich.edu but are not a subset of the default set.\n"); 4485895Sgblack@eecs.umich.edu if (portIter->range.start >= dflt_iter->start && 4495895Sgblack@eecs.umich.edu portIter->range.end <= dflt_iter->end) { 4505895Sgblack@eecs.umich.edu subset = true; 4515895Sgblack@eecs.umich.edu DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n", 4525895Sgblack@eecs.umich.edu portIter->range.start, portIter->range.end); 4536023Snate@binkert.org } 4545895Sgblack@eecs.umich.edu } 4555895Sgblack@eecs.umich.edu if (portIter->portId != id && !subset) { 4565895Sgblack@eecs.umich.edu resp.push_back(portIter->range); 4576023Snate@binkert.org DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", 4585895Sgblack@eecs.umich.edu portIter->range.start, portIter->range.end); 4595895Sgblack@eecs.umich.edu } 4606023Snate@binkert.org } 4615895Sgblack@eecs.umich.edu} 4625245Sgblack@eecs.umich.edu 4635245Sgblack@eecs.umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus) 4645245Sgblack@eecs.umich.edu 4655245Sgblack@eecs.umich.edu Param<int> bus_id; 4665897Sgblack@eecs.umich.edu Param<int> clock; 4675245Sgblack@eecs.umich.edu Param<int> width; 4685245Sgblack@eecs.umich.edu 4695245Sgblack@eecs.umich.eduEND_DECLARE_SIM_OBJECT_PARAMS(Bus) 4705245Sgblack@eecs.umich.edu 4715245Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(Bus) 4725245Sgblack@eecs.umich.edu INIT_PARAM(bus_id, "a globally unique bus id"), 4735245Sgblack@eecs.umich.edu INIT_PARAM(clock, "bus clock speed"), 4745245Sgblack@eecs.umich.edu INIT_PARAM(width, "width of the bus (bits)") 4755245Sgblack@eecs.umich.eduEND_INIT_SIM_OBJECT_PARAMS(Bus) 4765245Sgblack@eecs.umich.edu 4775245Sgblack@eecs.umich.eduCREATE_SIM_OBJECT(Bus) 4785245Sgblack@eecs.umich.edu{ 4795245Sgblack@eecs.umich.edu return new Bus(getInstanceName(), bus_id, clock, width); 4805245Sgblack@eecs.umich.edu} 4815245Sgblack@eecs.umich.edu 4825245Sgblack@eecs.umich.eduREGISTER_SIM_OBJECT("Bus", Bus) 4835245Sgblack@eecs.umich.edu