coherent_xbar.cc revision 2568
16145SN/A/* 28683SN/A * Copyright (c) 2006 The Regents of The University of Michigan 310973Sdavid.hashe@amd.com * All rights reserved. 46145SN/A * 56145SN/A * Redistribution and use in source and binary forms, with or without 66145SN/A * modification, are permitted provided that the following conditions are 76145SN/A * met: redistributions of source code must retain the above copyright 86145SN/A * notice, this list of conditions and the following disclaimer; 96145SN/A * redistributions in binary form must reproduce the above copyright 106145SN/A * notice, this list of conditions and the following disclaimer in the 116145SN/A * documentation and/or other materials provided with the distribution; 126145SN/A * neither the name of the copyright holders nor the names of its 136145SN/A * contributors may be used to endorse or promote products derived from 146145SN/A * this software without specific prior written permission. 156145SN/A * 166145SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176145SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186145SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196145SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206145SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216145SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226145SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236145SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246145SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256145SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266145SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276145SN/A */ 286145SN/A 296145SN/A/** 3010441Snilay@cs.wisc.edu * @file Definition of a bus object. 3110441Snilay@cs.wisc.edu */ 326145SN/A 337055SN/A 346145SN/A#include "base/trace.hh" 356145SN/A#include "mem/bus.hh" 367039SN/A#include "sim/builder.hh" 379104SN/A 3810301Snilay@cs.wisc.edu/** Get the ranges of anyone that we are connected to. */ 399105SN/Avoid 408174SN/ABus::init() 417039SN/A{ 427039SN/A std::vector<Port*>::iterator intIter; 437039SN/A for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) 4410970Sdavid.hashe@amd.com (*intIter)->sendStatusChange(Port::RangeChange); 4510301Snilay@cs.wisc.edu} 4610301Snilay@cs.wisc.edu 477039SN/A 487039SN/A/** Function called by the port when the bus is recieving a Timing 496145SN/A * transaction.*/ 507039SN/Abool 517039SN/ABus::recvTiming(Packet &pkt, int id) 527039SN/A{ 536876SN/A return findPort(pkt.addr, id)->sendTiming(pkt); 547039SN/A} 557039SN/A 566145SN/APort * 577039SN/ABus::findPort(Addr addr, int id) 586145SN/A{ 5911049Snilay@cs.wisc.edu /* An interval tree would be a better way to do this. --ali. */ 6011049Snilay@cs.wisc.edu int dest_id = -1; 6111049Snilay@cs.wisc.edu int i = 0; 6211049Snilay@cs.wisc.edu bool found = false; 6311049Snilay@cs.wisc.edu 6411049Snilay@cs.wisc.edu while (i < portList.size() && !found) 6511049Snilay@cs.wisc.edu { 6611049Snilay@cs.wisc.edu if (portList[i].range == addr) { 6711049Snilay@cs.wisc.edu dest_id = portList[i].portId; 687039SN/A found = true; 6911025Snilay@cs.wisc.edu DPRINTF(Bus, "Found Addr: %llx on device %d\n", addr, dest_id); 706145SN/A } 717039SN/A i++; 727039SN/A } 737039SN/A if (dest_id == -1) 7411025Snilay@cs.wisc.edu panic("Unable to find destination for addr: %llx", addr); 756145SN/A 767039SN/A // we shouldn't be sending this back to where it came from 7711025Snilay@cs.wisc.edu assert(dest_id != id); 7810974Sdavid.hashe@amd.com 7911025Snilay@cs.wisc.edu return interfaces[dest_id]; 8010974Sdavid.hashe@amd.com} 8110974Sdavid.hashe@amd.com 8210974Sdavid.hashe@amd.com/** Function called by the port when the bus is recieving a Atomic 8311025Snilay@cs.wisc.edu * transaction.*/ 848193SN/ATick 8510974Sdavid.hashe@amd.comBus::recvAtomic(Packet &pkt, int id) 868193SN/A{ 876145SN/A return findPort(pkt.addr, id)->sendAtomic(pkt); 887039SN/A} 8911025Snilay@cs.wisc.edu 906145SN/A/** Function called by the port when the bus is recieving a Functional 917039SN/A * transaction.*/ 9211025Snilay@cs.wisc.eduvoid 936145SN/ABus::recvFunctional(Packet &pkt, int id) 947039SN/A{ 9511025Snilay@cs.wisc.edu findPort(pkt.addr, id)->sendFunctional(pkt); 9611025Snilay@cs.wisc.edu} 976145SN/A 9810969Sdavid.hashe@amd.com/** Function called by the port when the bus is recieving a status change.*/ 9910969Sdavid.hashe@amd.comvoid 10010969Sdavid.hashe@amd.comBus::recvStatusChange(Port::Status status, int id) 10111061Snilay@cs.wisc.edu{ 10211061Snilay@cs.wisc.edu DPRINTF(Bus, "Bus %d recieved status change from device id %d\n", 1036285SN/A busId, id); 1047039SN/A assert(status == Port::RangeChange && 1058683SN/A "The other statuses need to be implemented."); 1066145SN/A 1077039SN/A assert(id < interfaces.size() && id >= 0); 10811025Snilay@cs.wisc.edu int x; 1096145SN/A Port *port = interfaces[id]; 11011059Snilay@cs.wisc.edu AddrRangeList ranges; 11111059Snilay@cs.wisc.edu AddrRangeList snoops; 11211059Snilay@cs.wisc.edu AddrRangeIter iter; 11311059Snilay@cs.wisc.edu std::vector<DevMap>::iterator portIter; 11411059Snilay@cs.wisc.edu 11511025Snilay@cs.wisc.edu // Clean out any previously existent ids 11611025Snilay@cs.wisc.edu for (portIter = portList.begin(); portIter != portList.end(); ) { 11711025Snilay@cs.wisc.edu if (portIter->portId == id) 1189692SN/A portIter = portList.erase(portIter); 1197039SN/A else 1207055SN/A portIter++; 1217055SN/A } 1226145SN/A 1239692SN/A port->getPeerAddressRanges(ranges, snoops); 12411025Snilay@cs.wisc.edu 12511025Snilay@cs.wisc.edu // not dealing with snooping yet either 1266374SN/A assert(snoops.size() == 0); 1279692SN/A for(iter = ranges.begin(); iter != ranges.end(); iter++) { 1289692SN/A DevMap dm; 1299692SN/A dm.portId = id; 1309692SN/A dm.range = *iter; 1319692SN/A 1329692SN/A DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start, 1339692SN/A dm.range.end, id); 1349692SN/A portList.push_back(dm); 1359692SN/A } 1369692SN/A DPRINTF(MMU, "port list has %d entries\n", portList.size()); 1379104SN/A 1389104SN/A // tell all our peers that our address range has changed. 1399104SN/A // Don't tell the device that caused this change, it already knows 1409104SN/A for (x = 0; x < interfaces.size(); x++) 1419104SN/A if (x != id) 1429104SN/A interfaces[x]->sendStatusChange(Port::RangeChange); 1439105SN/A} 1449105SN/A 1459692SN/Avoid 14610973Sdavid.hashe@amd.comBus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) 14710973Sdavid.hashe@amd.com{ 14811025Snilay@cs.wisc.edu std::vector<DevMap>::iterator portIter; 14910973Sdavid.hashe@amd.com 1507039SN/A resp.clear(); 1517039SN/A snoop.clear(); 15211061Snilay@cs.wisc.edu 1536145SN/A DPRINTF(Bus, "Bus id %d recieved address range request returning\n", 1547039SN/A busId); 1557039SN/A for (portIter = portList.begin(); portIter != portList.end(); portIter++) { 15611061Snilay@cs.wisc.edu if (portIter->portId != id) { 15711061Snilay@cs.wisc.edu resp.push_back(portIter->range); 1586145SN/A DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start, 1597039SN/A portIter->range.end); 1607039SN/A } 1617039SN/A } 1626145SN/A} 1637039SN/A 1647039SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus) 1657039SN/A 1666285SN/A Param<int> bus_id; 1677039SN/A 1687039SN/AEND_DECLARE_SIM_OBJECT_PARAMS(Bus) 16911025Snilay@cs.wisc.edu 1707454SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(Bus) 1716145SN/A INIT_PARAM(bus_id, "a globally unique bus id") 1727039SN/AEND_INIT_SIM_OBJECT_PARAMS(Bus) 1736145SN/A 1749105SN/ACREATE_SIM_OBJECT(Bus) 1759105SN/A{ 1769105SN/A return new Bus(getInstanceName(), bus_id); 1777039SN/A} 1787039SN/A 1797039SN/AREGISTER_SIM_OBJECT("Bus", Bus) 1807039SN/A