xbar.cc revision 2640
17404SAli.Saidi@ARM.com/* 211938Snikos.nikoleris@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 297404SAli.Saidi@ARM.com/** 307404SAli.Saidi@ARM.com * @file Definition of a bus object. 317404SAli.Saidi@ARM.com */ 327404SAli.Saidi@ARM.com 337404SAli.Saidi@ARM.com 347404SAli.Saidi@ARM.com#include "base/trace.hh" 357404SAli.Saidi@ARM.com#include "mem/bus.hh" 367404SAli.Saidi@ARM.com#include "sim/builder.hh" 377404SAli.Saidi@ARM.com 3810037SARM gem5 DevelopersPort * 397404SAli.Saidi@ARM.comBus::getPort(const std::string &if_name) 4010873Sandreas.sandberg@arm.com{ 417404SAli.Saidi@ARM.com // if_name ignored? forced to be empty? 4210474Sandreas.hansson@arm.com int id = interfaces.size(); 4310474Sandreas.hansson@arm.com BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id); 447404SAli.Saidi@ARM.com interfaces.push_back(bp); 4510037SARM gem5 Developers return bp; 4610037SARM gem5 Developers} 477404SAli.Saidi@ARM.com 487728SAli.Saidi@ARM.com/** Get the ranges of anyone that we are connected to. */ 497404SAli.Saidi@ARM.comvoid 508245Snate@binkert.orgBus::init() 519152Satgutier@umich.edu{ 528245Snate@binkert.org std::vector<Port*>::iterator intIter; 538245Snate@binkert.org for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) 5410873Sandreas.sandberg@arm.com (*intIter)->sendStatusChange(Port::RangeChange); 557748SAli.Saidi@ARM.com} 567404SAli.Saidi@ARM.com 577404SAli.Saidi@ARM.com 587404SAli.Saidi@ARM.com/** Function called by the port when the bus is recieving a Timing 597404SAli.Saidi@ARM.com * transaction.*/ 6010913Sandreas.sandberg@arm.combool 6110717Sandreas.hansson@arm.comBus::recvTiming(Packet *pkt) 6210717Sandreas.hansson@arm.com{ 6310717Sandreas.hansson@arm.com Port *port; 649258SAli.Saidi@ARM.com if (pkt->dest == Packet::Broadcast) { 6510621SCurtis.Dunham@arm.com port = findPort(pkt->addr, pkt->src); 6610621SCurtis.Dunham@arm.com } else { 6712086Sspwilson2@wisc.edu assert(pkt->dest >= 0 && pkt->dest < interfaces.size()); 6812086Sspwilson2@wisc.edu assert(pkt->dest != pkt->src); // catch infinite loops 6912086Sspwilson2@wisc.edu port = interfaces[pkt->dest]; 7012086Sspwilson2@wisc.edu } 7112086Sspwilson2@wisc.edu return port->sendTiming(pkt); 7212086Sspwilson2@wisc.edu} 7311588SCurtis.Dunham@arm.com 7411588SCurtis.Dunham@arm.comPort * 7512086Sspwilson2@wisc.eduBus::findPort(Addr addr, int id) 767439Sdam.sunwoo@arm.com{ 777576SAli.Saidi@ARM.com /* An interval tree would be a better way to do this. --ali. */ 7810037SARM gem5 Developers int dest_id = -1; 7910037SARM gem5 Developers int i = 0; 8010037SARM gem5 Developers bool found = false; 8110717Sandreas.hansson@arm.com 8210037SARM gem5 Developers while (i < portList.size() && !found) 8310037SARM gem5 Developers { 8410037SARM gem5 Developers if (portList[i].range == addr) { 8510037SARM gem5 Developers dest_id = portList[i].portId; 8610037SARM gem5 Developers found = true; 8710037SARM gem5 Developers DPRINTF(Bus, "Found Addr: %llx on device %d\n", addr, dest_id); 8810037SARM gem5 Developers } 8910037SARM gem5 Developers i++; 9010037SARM gem5 Developers } 9110037SARM gem5 Developers if (dest_id == -1) 9210037SARM gem5 Developers panic("Unable to find destination for addr: %llx", addr); 9310037SARM gem5 Developers 947439Sdam.sunwoo@arm.com // we shouldn't be sending this back to where it came from 957404SAli.Saidi@ARM.com assert(dest_id != id); 967404SAli.Saidi@ARM.com 977404SAli.Saidi@ARM.com return interfaces[dest_id]; 987404SAli.Saidi@ARM.com} 997404SAli.Saidi@ARM.com 1007404SAli.Saidi@ARM.com/** Function called by the port when the bus is recieving a Atomic 10110717Sandreas.hansson@arm.com * transaction.*/ 10210717Sandreas.hansson@arm.comTick 10310717Sandreas.hansson@arm.comBus::recvAtomic(Packet *pkt) 10410717Sandreas.hansson@arm.com{ 10510717Sandreas.hansson@arm.com assert(pkt->dest == Packet::Broadcast); 10610717Sandreas.hansson@arm.com return findPort(pkt->addr, pkt->src)->sendAtomic(pkt); 10710717Sandreas.hansson@arm.com} 10810717Sandreas.hansson@arm.com 10910717Sandreas.hansson@arm.com/** Function called by the port when the bus is recieving a Functional 11010717Sandreas.hansson@arm.com * transaction.*/ 11110717Sandreas.hansson@arm.comvoid 11210717Sandreas.hansson@arm.comBus::recvFunctional(Packet *pkt) 11310717Sandreas.hansson@arm.com{ 11410717Sandreas.hansson@arm.com assert(pkt->dest == Packet::Broadcast); 11510717Sandreas.hansson@arm.com findPort(pkt->addr, pkt->src)->sendFunctional(pkt); 11610717Sandreas.hansson@arm.com} 11710717Sandreas.hansson@arm.com 11810717Sandreas.hansson@arm.com/** Function called by the port when the bus is recieving a status change.*/ 11910717Sandreas.hansson@arm.comvoid 12010717Sandreas.hansson@arm.comBus::recvStatusChange(Port::Status status, int id) 12110717Sandreas.hansson@arm.com{ 12210717Sandreas.hansson@arm.com DPRINTF(Bus, "Bus %d recieved status change from device id %d\n", 12310717Sandreas.hansson@arm.com busId, id); 12410717Sandreas.hansson@arm.com assert(status == Port::RangeChange && 12510717Sandreas.hansson@arm.com "The other statuses need to be implemented."); 12610717Sandreas.hansson@arm.com 12710717Sandreas.hansson@arm.com assert(id < interfaces.size() && id >= 0); 12810717Sandreas.hansson@arm.com int x; 12910717Sandreas.hansson@arm.com Port *port = interfaces[id]; 13010537Sandreas.hansson@arm.com AddrRangeList ranges; 13110537Sandreas.hansson@arm.com AddrRangeList snoops; 13210537Sandreas.hansson@arm.com AddrRangeIter iter; 13310537Sandreas.hansson@arm.com std::vector<DevMap>::iterator portIter; 13410537Sandreas.hansson@arm.com 13510537Sandreas.hansson@arm.com // Clean out any previously existent ids 13610537Sandreas.hansson@arm.com for (portIter = portList.begin(); portIter != portList.end(); ) { 13710537Sandreas.hansson@arm.com if (portIter->portId == id) 13810537Sandreas.hansson@arm.com portIter = portList.erase(portIter); 13910037SARM gem5 Developers else 14010037SARM gem5 Developers portIter++; 14110037SARM gem5 Developers } 1429152Satgutier@umich.edu 1439152Satgutier@umich.edu port->getPeerAddressRanges(ranges, snoops); 1449152Satgutier@umich.edu 14510913Sandreas.sandberg@arm.com // not dealing with snooping yet either 14611588SCurtis.Dunham@arm.com assert(snoops.size() == 0); 14711588SCurtis.Dunham@arm.com for(iter = ranges.begin(); iter != ranges.end(); iter++) { 1489152Satgutier@umich.edu DevMap dm; 14910913Sandreas.sandberg@arm.com dm.portId = id; 1509152Satgutier@umich.edu dm.range = *iter; 15110913Sandreas.sandberg@arm.com 1529152Satgutier@umich.edu DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start, 1539152Satgutier@umich.edu dm.range.end, id); 1549152Satgutier@umich.edu portList.push_back(dm); 15510913Sandreas.sandberg@arm.com } 15610913Sandreas.sandberg@arm.com DPRINTF(MMU, "port list has %d entries\n", portList.size()); 1577404SAli.Saidi@ARM.com 15810037SARM gem5 Developers // tell all our peers that our address range has changed. 1599152Satgutier@umich.edu // Don't tell the device that caused this change, it already knows 16010037SARM gem5 Developers for (x = 0; x < interfaces.size(); x++) 16110037SARM gem5 Developers if (x != id) 16210037SARM gem5 Developers interfaces[x]->sendStatusChange(Port::RangeChange); 16310037SARM gem5 Developers} 16410037SARM gem5 Developers 16510037SARM gem5 Developersvoid 16610037SARM gem5 DevelopersBus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) 16710037SARM gem5 Developers{ 1689152Satgutier@umich.edu std::vector<DevMap>::iterator portIter; 16910913Sandreas.sandberg@arm.com 17010037SARM gem5 Developers resp.clear(); 17110037SARM gem5 Developers snoop.clear(); 17210913Sandreas.sandberg@arm.com 1737733SAli.Saidi@ARM.com DPRINTF(Bus, "Bus id %d recieved address range request returning\n", 1747404SAli.Saidi@ARM.com busId); 1757404SAli.Saidi@ARM.com for (portIter = portList.begin(); portIter != portList.end(); portIter++) { 1767748SAli.Saidi@ARM.com if (portIter->portId != id) { 1779342SAndreas.Sandberg@arm.com resp.push_back(portIter->range); 1787748SAli.Saidi@ARM.com DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start, 1799524SAndreas.Sandberg@ARM.com portIter->range.end); 1809152Satgutier@umich.edu } 1819152Satgutier@umich.edu } 18210621SCurtis.Dunham@arm.com} 1837748SAli.Saidi@ARM.com 1847748SAli.Saidi@ARM.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus) 1857748SAli.Saidi@ARM.com 1867404SAli.Saidi@ARM.com Param<int> bus_id; 18710037SARM gem5 Developers 18810037SARM gem5 DevelopersEND_DECLARE_SIM_OBJECT_PARAMS(Bus) 18910037SARM gem5 Developers 19011580SDylan.Johnson@ARM.comBEGIN_INIT_SIM_OBJECT_PARAMS(Bus) 19111580SDylan.Johnson@ARM.com INIT_PARAM(bus_id, "a globally unique bus id") 1927404SAli.Saidi@ARM.comEND_INIT_SIM_OBJECT_PARAMS(Bus) 1938733Sgeoffrey.blake@arm.com 19410621SCurtis.Dunham@arm.comCREATE_SIM_OBJECT(Bus) 19510621SCurtis.Dunham@arm.com{ 19610109SGeoffrey.Blake@arm.com return new Bus(getInstanceName(), bus_id); 19710037SARM gem5 Developers} 19810109SGeoffrey.Blake@arm.com 1997439Sdam.sunwoo@arm.comREGISTER_SIM_OBJECT("Bus", Bus) 2007439Sdam.sunwoo@arm.com