xbar.cc revision 2640
1/* 2 * Copyright (c) 2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/** 30 * @file Definition of a bus object. 31 */ 32 33 34#include "base/trace.hh" 35#include "mem/bus.hh" 36#include "sim/builder.hh" 37 38Port * 39Bus::getPort(const std::string &if_name) 40{ 41 // if_name ignored? forced to be empty? 42 int id = interfaces.size(); 43 BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id); 44 interfaces.push_back(bp); 45 return bp; 46} 47 48/** Get the ranges of anyone that we are connected to. */ 49void 50Bus::init() 51{ 52 std::vector<Port*>::iterator intIter; 53 for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) 54 (*intIter)->sendStatusChange(Port::RangeChange); 55} 56 57 58/** Function called by the port when the bus is recieving a Timing 59 * transaction.*/ 60bool 61Bus::recvTiming(Packet *pkt) 62{ 63 Port *port; 64 if (pkt->dest == Packet::Broadcast) { 65 port = findPort(pkt->addr, pkt->src); 66 } else { 67 assert(pkt->dest >= 0 && pkt->dest < interfaces.size()); 68 assert(pkt->dest != pkt->src); // catch infinite loops 69 port = interfaces[pkt->dest]; 70 } 71 return port->sendTiming(pkt); 72} 73 74Port * 75Bus::findPort(Addr addr, int id) 76{ 77 /* An interval tree would be a better way to do this. --ali. */ 78 int dest_id = -1; 79 int i = 0; 80 bool found = false; 81 82 while (i < portList.size() && !found) 83 { 84 if (portList[i].range == addr) { 85 dest_id = portList[i].portId; 86 found = true; 87 DPRINTF(Bus, "Found Addr: %llx on device %d\n", addr, dest_id); 88 } 89 i++; 90 } 91 if (dest_id == -1) 92 panic("Unable to find destination for addr: %llx", addr); 93 94 // we shouldn't be sending this back to where it came from 95 assert(dest_id != id); 96 97 return interfaces[dest_id]; 98} 99 100/** Function called by the port when the bus is recieving a Atomic 101 * transaction.*/ 102Tick 103Bus::recvAtomic(Packet *pkt) 104{ 105 assert(pkt->dest == Packet::Broadcast); 106 return findPort(pkt->addr, pkt->src)->sendAtomic(pkt); 107} 108 109/** Function called by the port when the bus is recieving a Functional 110 * transaction.*/ 111void 112Bus::recvFunctional(Packet *pkt) 113{ 114 assert(pkt->dest == Packet::Broadcast); 115 findPort(pkt->addr, pkt->src)->sendFunctional(pkt); 116} 117 118/** Function called by the port when the bus is recieving a status change.*/ 119void 120Bus::recvStatusChange(Port::Status status, int id) 121{ 122 DPRINTF(Bus, "Bus %d recieved status change from device id %d\n", 123 busId, id); 124 assert(status == Port::RangeChange && 125 "The other statuses need to be implemented."); 126 127 assert(id < interfaces.size() && id >= 0); 128 int x; 129 Port *port = interfaces[id]; 130 AddrRangeList ranges; 131 AddrRangeList snoops; 132 AddrRangeIter iter; 133 std::vector<DevMap>::iterator portIter; 134 135 // Clean out any previously existent ids 136 for (portIter = portList.begin(); portIter != portList.end(); ) { 137 if (portIter->portId == id) 138 portIter = portList.erase(portIter); 139 else 140 portIter++; 141 } 142 143 port->getPeerAddressRanges(ranges, snoops); 144 145 // not dealing with snooping yet either 146 assert(snoops.size() == 0); 147 for(iter = ranges.begin(); iter != ranges.end(); iter++) { 148 DevMap dm; 149 dm.portId = id; 150 dm.range = *iter; 151 152 DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start, 153 dm.range.end, id); 154 portList.push_back(dm); 155 } 156 DPRINTF(MMU, "port list has %d entries\n", portList.size()); 157 158 // tell all our peers that our address range has changed. 159 // Don't tell the device that caused this change, it already knows 160 for (x = 0; x < interfaces.size(); x++) 161 if (x != id) 162 interfaces[x]->sendStatusChange(Port::RangeChange); 163} 164 165void 166Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) 167{ 168 std::vector<DevMap>::iterator portIter; 169 170 resp.clear(); 171 snoop.clear(); 172 173 DPRINTF(Bus, "Bus id %d recieved address range request returning\n", 174 busId); 175 for (portIter = portList.begin(); portIter != portList.end(); portIter++) { 176 if (portIter->portId != id) { 177 resp.push_back(portIter->range); 178 DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start, 179 portIter->range.end); 180 } 181 } 182} 183 184BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus) 185 186 Param<int> bus_id; 187 188END_DECLARE_SIM_OBJECT_PARAMS(Bus) 189 190BEGIN_INIT_SIM_OBJECT_PARAMS(Bus) 191 INIT_PARAM(bus_id, "a globally unique bus id") 192END_INIT_SIM_OBJECT_PARAMS(Bus) 193 194CREATE_SIM_OBJECT(Bus) 195{ 196 return new Bus(getInstanceName(), bus_id); 197} 198 199REGISTER_SIM_OBJECT("Bus", Bus) 200