xbar.cc revision 3252
17404SAli.Saidi@ARM.com/* 210324SCurtis.Dunham@arm.com * Copyright (c) 2006 The Regents of The University of Michigan 37404SAli.Saidi@ARM.com * All rights reserved. 47404SAli.Saidi@ARM.com * 57404SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67404SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77404SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97404SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117404SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127404SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137404SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 147404SAli.Saidi@ARM.com * this software without specific prior written permission. 157404SAli.Saidi@ARM.com * 167404SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177404SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187404SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197404SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207404SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217404SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227404SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237404SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247404SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257404SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267404SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277404SAli.Saidi@ARM.com * 287404SAli.Saidi@ARM.com * Authors: Ali Saidi 297404SAli.Saidi@ARM.com */ 307404SAli.Saidi@ARM.com 317404SAli.Saidi@ARM.com/** 327404SAli.Saidi@ARM.com * @file 337404SAli.Saidi@ARM.com * Definition of a bus object. 347404SAli.Saidi@ARM.com */ 357404SAli.Saidi@ARM.com 367404SAli.Saidi@ARM.com 377404SAli.Saidi@ARM.com#include "base/misc.hh" 3810037SARM gem5 Developers#include "base/trace.hh" 397404SAli.Saidi@ARM.com#include "mem/bus.hh" 407404SAli.Saidi@ARM.com#include "sim/builder.hh" 4110474Sandreas.hansson@arm.com 4210474Sandreas.hansson@arm.comPort * 437404SAli.Saidi@ARM.comBus::getPort(const std::string &if_name, int idx) 4410037SARM gem5 Developers{ 4510037SARM gem5 Developers if (if_name == "default") 467404SAli.Saidi@ARM.com if (defaultPort == NULL) { 477404SAli.Saidi@ARM.com defaultPort = new BusPort(csprintf("%s-default",name()), this, 487728SAli.Saidi@ARM.com defaultId); 497404SAli.Saidi@ARM.com return defaultPort; 508245Snate@binkert.org } else 519152Satgutier@umich.edu fatal("Default port already set\n"); 528245Snate@binkert.org 538245Snate@binkert.org // if_name ignored? forced to be empty? 547748SAli.Saidi@ARM.com int id = interfaces.size(); 557404SAli.Saidi@ARM.com BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id); 567404SAli.Saidi@ARM.com interfaces.push_back(bp); 577404SAli.Saidi@ARM.com return bp; 587404SAli.Saidi@ARM.com} 5910037SARM gem5 Developers 6010037SARM gem5 Developers/** Get the ranges of anyone other buses that we are connected to. */ 6110037SARM gem5 Developersvoid 629258SAli.Saidi@ARM.comBus::init() 6310621SCurtis.Dunham@arm.com{ 6410621SCurtis.Dunham@arm.com std::vector<BusPort*>::iterator intIter; 6510037SARM gem5 Developers 6610037SARM gem5 Developers for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) 6710037SARM gem5 Developers (*intIter)->sendStatusChange(Port::RangeChange); 6810037SARM gem5 Developers} 697439Sdam.sunwoo@arm.com 707576SAli.Saidi@ARM.comBus::BusFreeEvent::BusFreeEvent(Bus *_bus) : Event(&mainEventQueue), bus(_bus) 7110037SARM gem5 Developers{} 7210037SARM gem5 Developers 7310037SARM gem5 Developersvoid Bus::BusFreeEvent::process() 7410037SARM gem5 Developers{ 7510037SARM gem5 Developers bus->recvRetry(-1); 7610037SARM gem5 Developers} 7710037SARM gem5 Developers 7810037SARM gem5 Developersconst char * Bus::BusFreeEvent::description() 7910037SARM gem5 Developers{ 8010037SARM gem5 Developers return "bus became available"; 8110037SARM gem5 Developers} 8210037SARM gem5 Developers 8310037SARM gem5 Developersvoid Bus::occupyBus(PacketPtr pkt) 8410037SARM gem5 Developers{ 8510037SARM gem5 Developers //Bring tickNextIdle up to the present tick 8610037SARM gem5 Developers //There is some potential ambiguity where a cycle starts, which might make 8710037SARM gem5 Developers //a difference when devices are acting right around a cycle boundary. Using 887439Sdam.sunwoo@arm.com //a < allows things which happen exactly on a cycle boundary to take up only 897404SAli.Saidi@ARM.com //the following cycle. Anthing that happens later will have to "wait" for 907404SAli.Saidi@ARM.com //the end of that cycle, and then start using the bus after that. 917404SAli.Saidi@ARM.com while (tickNextIdle < curTick) 927404SAli.Saidi@ARM.com tickNextIdle += clock; 937404SAli.Saidi@ARM.com 947404SAli.Saidi@ARM.com // The packet will be sent. Figure out how long it occupies the bus, and 9510537Sandreas.hansson@arm.com // how much of that time is for the first "word", aka bus width. 9610537Sandreas.hansson@arm.com int numCycles = 0; 9710537Sandreas.hansson@arm.com // Requests need one cycle to send an address 9810537Sandreas.hansson@arm.com if (pkt->isRequest()) 9910537Sandreas.hansson@arm.com numCycles++; 10010537Sandreas.hansson@arm.com else if (pkt->isResponse() || pkt->hasData()) { 10110537Sandreas.hansson@arm.com // If a packet has data, it needs ceil(size/width) cycles to send it 10210537Sandreas.hansson@arm.com // We're using the "adding instead of dividing" trick again here 10310537Sandreas.hansson@arm.com if (pkt->hasData()) { 10410037SARM gem5 Developers int dataSize = pkt->getSize(); 10510037SARM gem5 Developers for (int transmitted = 0; transmitted < dataSize; 10610037SARM gem5 Developers transmitted += width) { 1079152Satgutier@umich.edu numCycles++; 1089152Satgutier@umich.edu } 1099152Satgutier@umich.edu } else { 11010037SARM gem5 Developers // If the packet didn't have data, it must have been a response. 1119152Satgutier@umich.edu // Those use the bus for one cycle to send their data. 1129342SAndreas.Sandberg@arm.com numCycles++; 1139152Satgutier@umich.edu } 1149342SAndreas.Sandberg@arm.com } 1159342SAndreas.Sandberg@arm.com 1169152Satgutier@umich.edu // The first word will be delivered after the current tick, the delivery 1179152Satgutier@umich.edu // of the address if any, and one bus cycle to deliver the data 1189152Satgutier@umich.edu pkt->firstWordTime = 1197748SAli.Saidi@ARM.com tickNextIdle + 1209342SAndreas.Sandberg@arm.com pkt->isRequest() ? clock : 0 + 1217404SAli.Saidi@ARM.com clock; 1229342SAndreas.Sandberg@arm.com 1239152Satgutier@umich.edu //Advance it numCycles bus cycles. 12410037SARM gem5 Developers //XXX Should this use the repeated addition trick as well? 1259152Satgutier@umich.edu tickNextIdle += (numCycles * clock); 12610037SARM gem5 Developers if (!busIdle.scheduled()) { 12710037SARM gem5 Developers busIdle.schedule(tickNextIdle); 12810037SARM gem5 Developers } else { 12910037SARM gem5 Developers busIdle.reschedule(tickNextIdle); 13010037SARM gem5 Developers } 13110037SARM gem5 Developers DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n", 13210037SARM gem5 Developers curTick, tickNextIdle); 13310037SARM gem5 Developers 1349342SAndreas.Sandberg@arm.com // The bus will become idle once the current packet is delivered. 1359342SAndreas.Sandberg@arm.com pkt->finishTime = tickNextIdle; 1369152Satgutier@umich.edu} 1379152Satgutier@umich.edu 1389152Satgutier@umich.edu/** Function called by the port when the bus is receiving a Timing 1399152Satgutier@umich.edu * transaction.*/ 14010037SARM gem5 Developersbool 14110037SARM gem5 DevelopersBus::recvTiming(Packet *pkt) 14210037SARM gem5 Developers{ 1439152Satgutier@umich.edu Port *port; 14410037SARM gem5 Developers DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n", 14510037SARM gem5 Developers pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); 1467733SAli.Saidi@ARM.com 1477404SAli.Saidi@ARM.com BusPort *pktPort = interfaces[pkt->getSrc()]; 1487404SAli.Saidi@ARM.com 1497748SAli.Saidi@ARM.com // If the bus is busy, or other devices are in line ahead of the current 1509342SAndreas.Sandberg@arm.com // one, put this device on the retry list. 1517748SAli.Saidi@ARM.com if (tickNextIdle > curTick || 1529342SAndreas.Sandberg@arm.com (retryList.size() && (!inRetry || pktPort != retryList.front()))) { 1539524SAndreas.Sandberg@ARM.com addToRetryList(pktPort); 1549152Satgutier@umich.edu return false; 1559152Satgutier@umich.edu } 15610621SCurtis.Dunham@arm.com 1577748SAli.Saidi@ARM.com short dest = pkt->getDest(); 1587748SAli.Saidi@ARM.com if (dest == Packet::Broadcast) { 1597748SAli.Saidi@ARM.com if (timingSnoop(pkt)) { 1609294Sandreas.hansson@arm.com pkt->flags |= SNOOP_COMMIT; 1619294Sandreas.hansson@arm.com bool success = timingSnoop(pkt); 1627404SAli.Saidi@ARM.com assert(success); 1637404SAli.Saidi@ARM.com if (pkt->flags & SATISFIED) { 1648922Swilliam.wang@arm.com //Cache-Cache transfer occuring 1657404SAli.Saidi@ARM.com if (inRetry) { 1668922Swilliam.wang@arm.com retryList.front()->onRetryList(false); 1677404SAli.Saidi@ARM.com retryList.pop_front(); 1687404SAli.Saidi@ARM.com inRetry = false; 1697404SAli.Saidi@ARM.com } 17010037SARM gem5 Developers occupyBus(pkt); 17110037SARM gem5 Developers return true; 17210037SARM gem5 Developers } 17310037SARM gem5 Developers port = findPort(pkt->getAddr(), pkt->getSrc()); 1747404SAli.Saidi@ARM.com } else { 1758733Sgeoffrey.blake@arm.com //Snoop didn't succeed 17610621SCurtis.Dunham@arm.com addToRetryList(pktPort); 17710621SCurtis.Dunham@arm.com return false; 17810109SGeoffrey.Blake@arm.com } 17910037SARM gem5 Developers } else { 18010109SGeoffrey.Blake@arm.com assert(dest >= 0 && dest < interfaces.size()); 1817439Sdam.sunwoo@arm.com assert(dest != pkt->getSrc()); // catch infinite loops 1827439Sdam.sunwoo@arm.com port = interfaces[dest]; 1837439Sdam.sunwoo@arm.com } 1847439Sdam.sunwoo@arm.com 1857404SAli.Saidi@ARM.com occupyBus(pkt); 1867439Sdam.sunwoo@arm.com 1877439Sdam.sunwoo@arm.com if (port->sendTiming(pkt)) { 18810109SGeoffrey.Blake@arm.com // Packet was successfully sent. Return true. 18910109SGeoffrey.Blake@arm.com // Also take care of retries 19010109SGeoffrey.Blake@arm.com if (inRetry) { 19110109SGeoffrey.Blake@arm.com DPRINTF(Bus, "Remove retry from list %i\n", retryList.front()); 19210109SGeoffrey.Blake@arm.com retryList.front()->onRetryList(false); 19310109SGeoffrey.Blake@arm.com retryList.pop_front(); 19410109SGeoffrey.Blake@arm.com inRetry = false; 19510109SGeoffrey.Blake@arm.com } 1968202SAli.Saidi@ARM.com return true; 1978202SAli.Saidi@ARM.com } 1988202SAli.Saidi@ARM.com 1998202SAli.Saidi@ARM.com // Packet not successfully sent. Leave or put it on the retry list. 2008202SAli.Saidi@ARM.com DPRINTF(Bus, "Adding a retry to RETRY list %i\n", pktPort); 2018202SAli.Saidi@ARM.com addToRetryList(pktPort); 2028202SAli.Saidi@ARM.com return false; 20310037SARM gem5 Developers} 20410621SCurtis.Dunham@arm.com 20510474Sandreas.hansson@arm.comvoid 2068202SAli.Saidi@ARM.comBus::recvRetry(int id) 2077439Sdam.sunwoo@arm.com{ 20810621SCurtis.Dunham@arm.com DPRINTF(Bus, "Received a retry\n"); 2097439Sdam.sunwoo@arm.com // If there's anything waiting... 21010621SCurtis.Dunham@arm.com if (retryList.size()) { 2117439Sdam.sunwoo@arm.com //retryingPort = retryList.front(); 21210037SARM gem5 Developers inRetry = true; 21310037SARM gem5 Developers DPRINTF(Bus, "Sending a retry\n"); 2147439Sdam.sunwoo@arm.com retryList.front()->sendRetry(); 2157439Sdam.sunwoo@arm.com // If inRetry is still true, sendTiming wasn't called 2167439Sdam.sunwoo@arm.com if (inRetry) 21710037SARM gem5 Developers { 21810037SARM gem5 Developers retryList.front()->onRetryList(false); 21910037SARM gem5 Developers retryList.pop_front(); 2207439Sdam.sunwoo@arm.com inRetry = false; 2218733Sgeoffrey.blake@arm.com 2227439Sdam.sunwoo@arm.com //Bring tickNextIdle up to the present 22310037SARM gem5 Developers while (tickNextIdle < curTick) 22410037SARM gem5 Developers tickNextIdle += clock; 22510037SARM gem5 Developers 2267404SAli.Saidi@ARM.com //Burn a cycle for the missed grant. 2277436Sdam.sunwoo@arm.com tickNextIdle += clock; 2287436Sdam.sunwoo@arm.com 22910037SARM gem5 Developers if (!busIdle.scheduled()) { 23010037SARM gem5 Developers busIdle.schedule(tickNextIdle); 23110037SARM gem5 Developers } else { 23210037SARM gem5 Developers busIdle.reschedule(tickNextIdle); 23310037SARM gem5 Developers } 23410037SARM gem5 Developers } 23510037SARM gem5 Developers } 23610037SARM gem5 Developers} 23710037SARM gem5 Developers 23810037SARM gem5 DevelopersPort * 23910037SARM gem5 DevelopersBus::findPort(Addr addr, int id) 24010037SARM gem5 Developers{ 24110324SCurtis.Dunham@arm.com /* An interval tree would be a better way to do this. --ali. */ 24210037SARM gem5 Developers int dest_id = -1; 24310037SARM gem5 Developers int i = 0; 24410037SARM gem5 Developers bool found = false; 24510037SARM gem5 Developers AddrRangeIter iter; 24610037SARM gem5 Developers 24710324SCurtis.Dunham@arm.com while (i < portList.size() && !found) 24810037SARM gem5 Developers { 24910037SARM gem5 Developers if (portList[i].range == addr) { 25010037SARM gem5 Developers dest_id = portList[i].portId; 25110037SARM gem5 Developers found = true; 25210324SCurtis.Dunham@arm.com DPRINTF(Bus, " found addr %#llx on device %d\n", addr, dest_id); 25310037SARM gem5 Developers } 25410037SARM gem5 Developers i++; 25510037SARM gem5 Developers } 25610037SARM gem5 Developers 25710037SARM gem5 Developers // Check if this matches the default range 25810037SARM gem5 Developers if (dest_id == -1) { 25910037SARM gem5 Developers for (iter = defaultRange.begin(); iter != defaultRange.end(); iter++) { 26010037SARM gem5 Developers if (*iter == addr) { 26110037SARM gem5 Developers DPRINTF(Bus, " found addr %#llx on default\n", addr); 26210037SARM gem5 Developers return defaultPort; 26310037SARM gem5 Developers } 26410037SARM gem5 Developers } 26510037SARM gem5 Developers panic("Unable to find destination for addr: %#llx", addr); 26610037SARM gem5 Developers } 2677439Sdam.sunwoo@arm.com 2687439Sdam.sunwoo@arm.com 2697439Sdam.sunwoo@arm.com // we shouldn't be sending this back to where it came from 2707439Sdam.sunwoo@arm.com assert(dest_id != id); 2717439Sdam.sunwoo@arm.com 27210621SCurtis.Dunham@arm.com return interfaces[dest_id]; 27310621SCurtis.Dunham@arm.com} 27410037SARM gem5 Developers 27510037SARM gem5 Developersstd::vector<int> 27610037SARM gem5 DevelopersBus::findSnoopPorts(Addr addr, int id) 27710037SARM gem5 Developers{ 27810037SARM gem5 Developers int i = 0; 27910037SARM gem5 Developers AddrRangeIter iter; 28010037SARM gem5 Developers std::vector<int> ports; 2817728SAli.Saidi@ARM.com 28210037SARM gem5 Developers while (i < portSnoopList.size()) 28310037SARM gem5 Developers { 28410037SARM gem5 Developers if (portSnoopList[i].range == addr && portSnoopList[i].portId != id) { 28510037SARM gem5 Developers //Careful to not overlap ranges 28610037SARM gem5 Developers //or snoop will be called more than once on the port 28710037SARM gem5 Developers ports.push_back(portSnoopList[i].portId); 28810037SARM gem5 Developers// DPRINTF(Bus, " found snoop addr %#llx on device%d\n", addr, 28910037SARM gem5 Developers// portSnoopList[i].portId); 29010037SARM gem5 Developers } 29110037SARM gem5 Developers i++; 29210037SARM gem5 Developers } 29310621SCurtis.Dunham@arm.com return ports; 29410621SCurtis.Dunham@arm.com} 29510621SCurtis.Dunham@arm.com 29610621SCurtis.Dunham@arm.comvoid 29710037SARM gem5 DevelopersBus::atomicSnoop(Packet *pkt) 29810037SARM gem5 Developers{ 29910037SARM gem5 Developers std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); 30010109SGeoffrey.Blake@arm.com 30110037SARM gem5 Developers while (!ports.empty()) 30210109SGeoffrey.Blake@arm.com { 30310037SARM gem5 Developers interfaces[ports.back()]->sendAtomic(pkt); 30410109SGeoffrey.Blake@arm.com ports.pop_back(); 30510037SARM gem5 Developers } 30610109SGeoffrey.Blake@arm.com} 30710109SGeoffrey.Blake@arm.com 30810109SGeoffrey.Blake@arm.comvoid 30910109SGeoffrey.Blake@arm.comBus::functionalSnoop(Packet *pkt) 31010109SGeoffrey.Blake@arm.com{ 31110109SGeoffrey.Blake@arm.com std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); 31210109SGeoffrey.Blake@arm.com 31310109SGeoffrey.Blake@arm.com while (!ports.empty()) 31410109SGeoffrey.Blake@arm.com { 31510037SARM gem5 Developers interfaces[ports.back()]->sendFunctional(pkt); 3167728SAli.Saidi@ARM.com ports.pop_back(); 3178067SAli.Saidi@ARM.com } 3187728SAli.Saidi@ARM.com} 3197728SAli.Saidi@ARM.com 32010621SCurtis.Dunham@arm.combool 3217728SAli.Saidi@ARM.comBus::timingSnoop(Packet *pkt) 3227728SAli.Saidi@ARM.com{ 32310621SCurtis.Dunham@arm.com std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); 32410037SARM gem5 Developers bool success = true; 32510037SARM gem5 Developers 32610037SARM gem5 Developers while (!ports.empty() && success) 32710037SARM gem5 Developers { 32810037SARM gem5 Developers success = interfaces[ports.back()]->sendTiming(pkt); 32910037SARM gem5 Developers ports.pop_back(); 3307728SAli.Saidi@ARM.com } 3317728SAli.Saidi@ARM.com 3327728SAli.Saidi@ARM.com return success; 3337728SAli.Saidi@ARM.com} 3347728SAli.Saidi@ARM.com 3357728SAli.Saidi@ARM.com 3367728SAli.Saidi@ARM.com/** Function called by the port when the bus is receiving a Atomic 3377728SAli.Saidi@ARM.com * transaction.*/ 3387728SAli.Saidi@ARM.comTick 3397728SAli.Saidi@ARM.comBus::recvAtomic(Packet *pkt) 34010621SCurtis.Dunham@arm.com{ 3417728SAli.Saidi@ARM.com DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n", 3429258SAli.Saidi@ARM.com pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); 34310037SARM gem5 Developers assert(pkt->getDest() == Packet::Broadcast); 34410037SARM gem5 Developers atomicSnoop(pkt); 34510037SARM gem5 Developers return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt); 34610037SARM gem5 Developers} 34710037SARM gem5 Developers 34810037SARM gem5 Developers/** Function called by the port when the bus is receiving a Functional 3499535Smrinmoy.ghosh@arm.com * transaction.*/ 35010037SARM gem5 Developersvoid 35110037SARM gem5 DevelopersBus::recvFunctional(Packet *pkt) 35210037SARM gem5 Developers{ 35310037SARM gem5 Developers DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", 3549258SAli.Saidi@ARM.com pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); 3559535Smrinmoy.ghosh@arm.com assert(pkt->getDest() == Packet::Broadcast); 3569535Smrinmoy.ghosh@arm.com functionalSnoop(pkt); 3579535Smrinmoy.ghosh@arm.com findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt); 3589535Smrinmoy.ghosh@arm.com} 3599535Smrinmoy.ghosh@arm.com 3609535Smrinmoy.ghosh@arm.com/** Function called by the port when the bus is receiving a status change.*/ 3619258SAli.Saidi@ARM.comvoid 3629258SAli.Saidi@ARM.comBus::recvStatusChange(Port::Status status, int id) 3639258SAli.Saidi@ARM.com{ 36410579SAndrew.Bardsley@arm.com AddrRangeList ranges; 36510579SAndrew.Bardsley@arm.com AddrRangeList snoops; 36610579SAndrew.Bardsley@arm.com int x; 36710037SARM gem5 Developers AddrRangeIter iter; 36810579SAndrew.Bardsley@arm.com 36910037SARM gem5 Developers assert(status == Port::RangeChange && 37010579SAndrew.Bardsley@arm.com "The other statuses need to be implemented."); 37110037SARM gem5 Developers 37210579SAndrew.Bardsley@arm.com DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id); 37310579SAndrew.Bardsley@arm.com 37410579SAndrew.Bardsley@arm.com if (id == defaultId) { 37510579SAndrew.Bardsley@arm.com defaultRange.clear(); 37610579SAndrew.Bardsley@arm.com defaultPort->getPeerAddressRanges(ranges, snoops); 37710579SAndrew.Bardsley@arm.com assert(snoops.size() == 0); 37810579SAndrew.Bardsley@arm.com for(iter = ranges.begin(); iter != ranges.end(); iter++) { 37910579SAndrew.Bardsley@arm.com defaultRange.push_back(*iter); 3809258SAli.Saidi@ARM.com DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", 3819258SAli.Saidi@ARM.com iter->start, iter->end); 3829258SAli.Saidi@ARM.com } 3839258SAli.Saidi@ARM.com } else { 3849258SAli.Saidi@ARM.com 3859258SAli.Saidi@ARM.com assert((id < interfaces.size() && id >= 0) || id == -1); 3869258SAli.Saidi@ARM.com Port *port = interfaces[id]; 3879258SAli.Saidi@ARM.com std::vector<DevMap>::iterator portIter; 3889258SAli.Saidi@ARM.com std::vector<DevMap>::iterator snoopIter; 3899535Smrinmoy.ghosh@arm.com 3909258SAli.Saidi@ARM.com // Clean out any previously existent ids 3919258SAli.Saidi@ARM.com for (portIter = portList.begin(); portIter != portList.end(); ) { 39210621SCurtis.Dunham@arm.com if (portIter->portId == id) 3939258SAli.Saidi@ARM.com portIter = portList.erase(portIter); 39410037SARM gem5 Developers else 39510037SARM gem5 Developers portIter++; 3969258SAli.Saidi@ARM.com } 3979535Smrinmoy.ghosh@arm.com 3989535Smrinmoy.ghosh@arm.com for (snoopIter = portSnoopList.begin(); snoopIter != portSnoopList.end(); ) { 39910474Sandreas.hansson@arm.com if (snoopIter->portId == id) 40010474Sandreas.hansson@arm.com snoopIter = portSnoopList.erase(snoopIter); 40110474Sandreas.hansson@arm.com else 4029535Smrinmoy.ghosh@arm.com snoopIter++; 4039535Smrinmoy.ghosh@arm.com } 40410621SCurtis.Dunham@arm.com 40510037SARM gem5 Developers port->getPeerAddressRanges(ranges, snoops); 40610037SARM gem5 Developers 40710037SARM gem5 Developers for(iter = snoops.begin(); iter != snoops.end(); iter++) { 4089535Smrinmoy.ghosh@arm.com DevMap dm; 4099258SAli.Saidi@ARM.com dm.portId = id; 4109258SAli.Saidi@ARM.com dm.range = *iter; 4119258SAli.Saidi@ARM.com 4129258SAli.Saidi@ARM.com DPRINTF(BusAddrRanges, "Adding snoop range %#llx - %#llx for id %d\n", 4139258SAli.Saidi@ARM.com dm.range.start, dm.range.end, id); 4149535Smrinmoy.ghosh@arm.com portSnoopList.push_back(dm); 4159258SAli.Saidi@ARM.com } 41610037SARM gem5 Developers 41710037SARM gem5 Developers for(iter = ranges.begin(); iter != ranges.end(); iter++) { 41810037SARM gem5 Developers DevMap dm; 4199535Smrinmoy.ghosh@arm.com dm.portId = id; 4209535Smrinmoy.ghosh@arm.com dm.range = *iter; 4219258SAli.Saidi@ARM.com 4229535Smrinmoy.ghosh@arm.com DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", 4239258SAli.Saidi@ARM.com dm.range.start, dm.range.end, id); 42410621SCurtis.Dunham@arm.com portList.push_back(dm); 4259258SAli.Saidi@ARM.com } 42610621SCurtis.Dunham@arm.com } 4279258SAli.Saidi@ARM.com DPRINTF(MMU, "port list has %d entries\n", portList.size()); 4289258SAli.Saidi@ARM.com 4297728SAli.Saidi@ARM.com // tell all our peers that our address range has changed. 4307728SAli.Saidi@ARM.com // Don't tell the device that caused this change, it already knows 4317728SAli.Saidi@ARM.com for (x = 0; x < interfaces.size(); x++) 4327728SAli.Saidi@ARM.com if (x != id) 4337728SAli.Saidi@ARM.com interfaces[x]->sendStatusChange(Port::RangeChange); 4347404SAli.Saidi@ARM.com 4357404SAli.Saidi@ARM.com if (id != defaultId && defaultPort) 4367404SAli.Saidi@ARM.com defaultPort->sendStatusChange(Port::RangeChange); 43710037SARM gem5 Developers} 4387404SAli.Saidi@ARM.com 43910037SARM gem5 Developersvoid 44010037SARM gem5 DevelopersBus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) 44110037SARM gem5 Developers{ 4427406SAli.Saidi@ARM.com std::vector<DevMap>::iterator portIter; 44310621SCurtis.Dunham@arm.com AddrRangeIter dflt_iter; 44410621SCurtis.Dunham@arm.com bool subset; 44510037SARM gem5 Developers 44610037SARM gem5 Developers resp.clear(); 4477406SAli.Saidi@ARM.com snoop.clear(); 44810037SARM gem5 Developers 44910037SARM gem5 Developers DPRINTF(BusAddrRanges, "received address range request, returning:\n"); 45010037SARM gem5 Developers 45110474Sandreas.hansson@arm.com for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end(); 45210474Sandreas.hansson@arm.com dflt_iter++) { 45310474Sandreas.hansson@arm.com resp.push_back(*dflt_iter); 45410474Sandreas.hansson@arm.com DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n",dflt_iter->start, 45510474Sandreas.hansson@arm.com dflt_iter->end); 45610037SARM gem5 Developers } 45710474Sandreas.hansson@arm.com for (portIter = portList.begin(); portIter != portList.end(); portIter++) { 45810474Sandreas.hansson@arm.com subset = false; 45910474Sandreas.hansson@arm.com for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end(); 46010474Sandreas.hansson@arm.com dflt_iter++) { 46110474Sandreas.hansson@arm.com if ((portIter->range.start < dflt_iter->start && 46210037SARM gem5 Developers portIter->range.end >= dflt_iter->start) || 46310037SARM gem5 Developers (portIter->range.start < dflt_iter->end && 46410037SARM gem5 Developers portIter->range.end >= dflt_iter->end)) 4657404SAli.Saidi@ARM.com fatal("Devices can not set ranges that itersect the default set\ 4667406SAli.Saidi@ARM.com but are not a subset of the default set.\n"); 46710037SARM gem5 Developers if (portIter->range.start >= dflt_iter->start && 46810037SARM gem5 Developers portIter->range.end <= dflt_iter->end) { 46910037SARM gem5 Developers subset = true; 47010474Sandreas.hansson@arm.com DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n", 47110474Sandreas.hansson@arm.com portIter->range.start, portIter->range.end); 47210474Sandreas.hansson@arm.com } 47310474Sandreas.hansson@arm.com } 47410474Sandreas.hansson@arm.com if (portIter->portId != id && !subset) { 47510037SARM gem5 Developers resp.push_back(portIter->range); 47610474Sandreas.hansson@arm.com DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", 47710474Sandreas.hansson@arm.com portIter->range.start, portIter->range.end); 47810474Sandreas.hansson@arm.com } 47910474Sandreas.hansson@arm.com } 48010474Sandreas.hansson@arm.com} 48110037SARM gem5 Developers 48210037SARM gem5 DevelopersBEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus) 48310037SARM gem5 Developers 48410037SARM gem5 Developers Param<int> bus_id; 4857404SAli.Saidi@ARM.com Param<int> clock; 4867404SAli.Saidi@ARM.com Param<int> width; 48710037SARM gem5 Developers 48810037SARM gem5 DevelopersEND_DECLARE_SIM_OBJECT_PARAMS(Bus) 48910037SARM gem5 Developers 49010037SARM gem5 DevelopersBEGIN_INIT_SIM_OBJECT_PARAMS(Bus) 4917404SAli.Saidi@ARM.com INIT_PARAM(bus_id, "a globally unique bus id"), 4927404SAli.Saidi@ARM.com INIT_PARAM(clock, "bus clock speed"), 4937439Sdam.sunwoo@arm.com INIT_PARAM(width, "width of the bus (bits)") 49410037SARM gem5 DevelopersEND_INIT_SIM_OBJECT_PARAMS(Bus) 49510037SARM gem5 Developers 49610037SARM gem5 DevelopersCREATE_SIM_OBJECT(Bus) 4977439Sdam.sunwoo@arm.com{ 49810037SARM gem5 Developers return new Bus(getInstanceName(), bus_id, clock, width); 4997579Sminkyu.jeong@arm.com} 5007728SAli.Saidi@ARM.com 5017728SAli.Saidi@ARM.comREGISTER_SIM_OBJECT("Bus", Bus) 5027579Sminkyu.jeong@arm.com