xbar.cc revision 2640
16019Shines@cs.fsu.edu/* 27399SAli.Saidi@ARM.com * Copyright (c) 2006 The Regents of The University of Michigan 37399SAli.Saidi@ARM.com * All rights reserved. 47399SAli.Saidi@ARM.com * 57399SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67399SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77399SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87399SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97399SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107399SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117399SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127399SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137399SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 146019Shines@cs.fsu.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu */ 286019Shines@cs.fsu.edu 296019Shines@cs.fsu.edu/** 306019Shines@cs.fsu.edu * @file Definition of a bus object. 316019Shines@cs.fsu.edu */ 326019Shines@cs.fsu.edu 336019Shines@cs.fsu.edu 346019Shines@cs.fsu.edu#include "base/trace.hh" 356019Shines@cs.fsu.edu#include "mem/bus.hh" 366019Shines@cs.fsu.edu#include "sim/builder.hh" 376019Shines@cs.fsu.edu 386019Shines@cs.fsu.eduPort * 396019Shines@cs.fsu.eduBus::getPort(const std::string &if_name) 407399SAli.Saidi@ARM.com{ 416019Shines@cs.fsu.edu // if_name ignored? forced to be empty? 426019Shines@cs.fsu.edu int id = interfaces.size(); 436019Shines@cs.fsu.edu BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id); 446019Shines@cs.fsu.edu interfaces.push_back(bp); 456019Shines@cs.fsu.edu return bp; 466019Shines@cs.fsu.edu} 476019Shines@cs.fsu.edu 486019Shines@cs.fsu.edu/** Get the ranges of anyone that we are connected to. */ 496019Shines@cs.fsu.eduvoid 506019Shines@cs.fsu.eduBus::init() 516019Shines@cs.fsu.edu{ 526019Shines@cs.fsu.edu std::vector<Port*>::iterator intIter; 536019Shines@cs.fsu.edu for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) 546116Snate@binkert.org (*intIter)->sendStatusChange(Port::RangeChange); 557678Sgblack@eecs.umich.edu} 566019Shines@cs.fsu.edu 576019Shines@cs.fsu.edu 586019Shines@cs.fsu.edu/** Function called by the port when the bus is recieving a Timing 596019Shines@cs.fsu.edu * transaction.*/ 606019Shines@cs.fsu.edubool 616019Shines@cs.fsu.eduBus::recvTiming(Packet *pkt) 627404SAli.Saidi@ARM.com{ 637404SAli.Saidi@ARM.com Port *port; 646019Shines@cs.fsu.edu if (pkt->dest == Packet::Broadcast) { 656019Shines@cs.fsu.edu port = findPort(pkt->addr, pkt->src); 667294Sgblack@eecs.umich.edu } else { 677294Sgblack@eecs.umich.edu assert(pkt->dest >= 0 && pkt->dest < interfaces.size()); 687639Sgblack@eecs.umich.edu assert(pkt->dest != pkt->src); // catch infinite loops 697294Sgblack@eecs.umich.edu port = interfaces[pkt->dest]; 707294Sgblack@eecs.umich.edu } 717294Sgblack@eecs.umich.edu return port->sendTiming(pkt); 727294Sgblack@eecs.umich.edu} 737294Sgblack@eecs.umich.edu 747639Sgblack@eecs.umich.eduPort * 757639Sgblack@eecs.umich.eduBus::findPort(Addr addr, int id) 767294Sgblack@eecs.umich.edu{ 777639Sgblack@eecs.umich.edu /* An interval tree would be a better way to do this. --ali. */ 787404SAli.Saidi@ARM.com int dest_id = -1; 797639Sgblack@eecs.umich.edu int i = 0; 807294Sgblack@eecs.umich.edu bool found = false; 817294Sgblack@eecs.umich.edu 827294Sgblack@eecs.umich.edu while (i < portList.size() && !found) 837639Sgblack@eecs.umich.edu { 847294Sgblack@eecs.umich.edu if (portList[i].range == addr) { 856019Shines@cs.fsu.edu dest_id = portList[i].portId; 866019Shines@cs.fsu.edu found = true; 877404SAli.Saidi@ARM.com DPRINTF(Bus, "Found Addr: %llx on device %d\n", addr, dest_id); 886019Shines@cs.fsu.edu } 897406SAli.Saidi@ARM.com i++; 907436Sdam.sunwoo@arm.com } 917436Sdam.sunwoo@arm.com if (dest_id == -1) 927406SAli.Saidi@ARM.com panic("Unable to find destination for addr: %llx", addr); 937404SAli.Saidi@ARM.com 947406SAli.Saidi@ARM.com // we shouldn't be sending this back to where it came from 956019Shines@cs.fsu.edu assert(dest_id != id); 967694SAli.Saidi@ARM.com 977694SAli.Saidi@ARM.com return interfaces[dest_id]; 987694SAli.Saidi@ARM.com} 997694SAli.Saidi@ARM.com 1007694SAli.Saidi@ARM.com/** Function called by the port when the bus is recieving a Atomic 1017694SAli.Saidi@ARM.com * transaction.*/ 1027694SAli.Saidi@ARM.comTick 1036019Shines@cs.fsu.eduBus::recvAtomic(Packet *pkt) 1047399SAli.Saidi@ARM.com{ 1057734SAli.Saidi@ARM.com assert(pkt->dest == Packet::Broadcast); 1067734SAli.Saidi@ARM.com return findPort(pkt->addr, pkt->src)->sendAtomic(pkt); 1077734SAli.Saidi@ARM.com} 1087734SAli.Saidi@ARM.com 1097734SAli.Saidi@ARM.com/** Function called by the port when the bus is recieving a Functional 1107734SAli.Saidi@ARM.com * transaction.*/ 1117734SAli.Saidi@ARM.comvoid 1127734SAli.Saidi@ARM.comBus::recvFunctional(Packet *pkt) 1137734SAli.Saidi@ARM.com{ 1147734SAli.Saidi@ARM.com assert(pkt->dest == Packet::Broadcast); 1157734SAli.Saidi@ARM.com findPort(pkt->addr, pkt->src)->sendFunctional(pkt); 1167734SAli.Saidi@ARM.com} 1177734SAli.Saidi@ARM.com 1187734SAli.Saidi@ARM.com/** Function called by the port when the bus is recieving a status change.*/ 1197734SAli.Saidi@ARM.comvoid 1207734SAli.Saidi@ARM.comBus::recvStatusChange(Port::Status status, int id) 1217734SAli.Saidi@ARM.com{ 1227734SAli.Saidi@ARM.com DPRINTF(Bus, "Bus %d recieved status change from device id %d\n", 1237734SAli.Saidi@ARM.com busId, id); 1247734SAli.Saidi@ARM.com assert(status == Port::RangeChange && 1256019Shines@cs.fsu.edu "The other statuses need to be implemented."); 1266019Shines@cs.fsu.edu 1276019Shines@cs.fsu.edu assert(id < interfaces.size() && id >= 0); 1286019Shines@cs.fsu.edu int x; 1297697SAli.Saidi@ARM.com Port *port = interfaces[id]; 1307404SAli.Saidi@ARM.com AddrRangeList ranges; 1316019Shines@cs.fsu.edu AddrRangeList snoops; 1326019Shines@cs.fsu.edu AddrRangeIter iter; 1336019Shines@cs.fsu.edu std::vector<DevMap>::iterator portIter; 1346019Shines@cs.fsu.edu 1356019Shines@cs.fsu.edu // Clean out any previously existent ids 1366019Shines@cs.fsu.edu for (portIter = portList.begin(); portIter != portList.end(); ) { 1376019Shines@cs.fsu.edu if (portIter->portId == id) 1387404SAli.Saidi@ARM.com portIter = portList.erase(portIter); 1397404SAli.Saidi@ARM.com else 1407404SAli.Saidi@ARM.com portIter++; 1416019Shines@cs.fsu.edu } 1427404SAli.Saidi@ARM.com 1437404SAli.Saidi@ARM.com port->getPeerAddressRanges(ranges, snoops); 1447404SAli.Saidi@ARM.com 1457404SAli.Saidi@ARM.com // not dealing with snooping yet either 1467404SAli.Saidi@ARM.com assert(snoops.size() == 0); 1477404SAli.Saidi@ARM.com for(iter = ranges.begin(); iter != ranges.end(); iter++) { 1487404SAli.Saidi@ARM.com DevMap dm; 1497404SAli.Saidi@ARM.com dm.portId = id; 1507404SAli.Saidi@ARM.com dm.range = *iter; 1517404SAli.Saidi@ARM.com 1527404SAli.Saidi@ARM.com DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start, 1537404SAli.Saidi@ARM.com dm.range.end, id); 1547404SAli.Saidi@ARM.com portList.push_back(dm); 1557404SAli.Saidi@ARM.com } 1567404SAli.Saidi@ARM.com DPRINTF(MMU, "port list has %d entries\n", portList.size()); 1577404SAli.Saidi@ARM.com 1587404SAli.Saidi@ARM.com // tell all our peers that our address range has changed. 1597404SAli.Saidi@ARM.com // Don't tell the device that caused this change, it already knows 1607406SAli.Saidi@ARM.com for (x = 0; x < interfaces.size(); x++) 1617406SAli.Saidi@ARM.com if (x != id) 1627404SAli.Saidi@ARM.com interfaces[x]->sendStatusChange(Port::RangeChange); 1637404SAli.Saidi@ARM.com} 1647404SAli.Saidi@ARM.com 1656019Shines@cs.fsu.eduvoid 1666019Shines@cs.fsu.eduBus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) 1677404SAli.Saidi@ARM.com{ 1686019Shines@cs.fsu.edu std::vector<DevMap>::iterator portIter; 1696019Shines@cs.fsu.edu 1706019Shines@cs.fsu.edu resp.clear(); 1716019Shines@cs.fsu.edu snoop.clear(); 1727694SAli.Saidi@ARM.com 1737694SAli.Saidi@ARM.com DPRINTF(Bus, "Bus id %d recieved address range request returning\n", 1747694SAli.Saidi@ARM.com busId); 1757694SAli.Saidi@ARM.com for (portIter = portList.begin(); portIter != portList.end(); portIter++) { 1767694SAli.Saidi@ARM.com if (portIter->portId != id) { 1777694SAli.Saidi@ARM.com resp.push_back(portIter->range); 1787694SAli.Saidi@ARM.com DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start, 1797694SAli.Saidi@ARM.com portIter->range.end); 1807694SAli.Saidi@ARM.com } 1817694SAli.Saidi@ARM.com } 1827436Sdam.sunwoo@arm.com} 1837436Sdam.sunwoo@arm.com 1847436Sdam.sunwoo@arm.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus) 1857436Sdam.sunwoo@arm.com 1867436Sdam.sunwoo@arm.com Param<int> bus_id; 1877436Sdam.sunwoo@arm.com 1887436Sdam.sunwoo@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(Bus) 1897436Sdam.sunwoo@arm.com 1907436Sdam.sunwoo@arm.comBEGIN_INIT_SIM_OBJECT_PARAMS(Bus) 1917436Sdam.sunwoo@arm.com INIT_PARAM(bus_id, "a globally unique bus id") 1927436Sdam.sunwoo@arm.comEND_INIT_SIM_OBJECT_PARAMS(Bus) 1937436Sdam.sunwoo@arm.com 1947436Sdam.sunwoo@arm.comCREATE_SIM_OBJECT(Bus) 1957404SAli.Saidi@ARM.com{ 1967404SAli.Saidi@ARM.com return new Bus(getInstanceName(), bus_id); 1977404SAli.Saidi@ARM.com} 1987404SAli.Saidi@ARM.com 1997404SAli.Saidi@ARM.comREGISTER_SIM_OBJECT("Bus", Bus) 2007404SAli.Saidi@ARM.com