coherent_xbar.cc revision 2568
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 38/** Get the ranges of anyone that we are connected to. */ 39void 40Bus::init() 41{ 42 std::vector<Port*>::iterator intIter; 43 for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) 44 (*intIter)->sendStatusChange(Port::RangeChange); 45} 46 47 48/** Function called by the port when the bus is recieving a Timing 49 * transaction.*/ 50bool 51Bus::recvTiming(Packet &pkt, int id) 52{ 53 return findPort(pkt.addr, id)->sendTiming(pkt); 54} 55 56Port * 57Bus::findPort(Addr addr, int id) 58{ 59 /* An interval tree would be a better way to do this. --ali. */ 60 int dest_id = -1; 61 int i = 0; 62 bool found = false; 63 64 while (i < portList.size() && !found) 65 { 66 if (portList[i].range == addr) { 67 dest_id = portList[i].portId; 68 found = true; 69 DPRINTF(Bus, "Found Addr: %llx on device %d\n", addr, dest_id); 70 } 71 i++; 72 } 73 if (dest_id == -1) 74 panic("Unable to find destination for addr: %llx", addr); 75 76 // we shouldn't be sending this back to where it came from 77 assert(dest_id != id); 78 79 return interfaces[dest_id]; 80} 81 82/** Function called by the port when the bus is recieving a Atomic 83 * transaction.*/ 84Tick 85Bus::recvAtomic(Packet &pkt, int id) 86{ 87 return findPort(pkt.addr, id)->sendAtomic(pkt); 88} 89 90/** Function called by the port when the bus is recieving a Functional 91 * transaction.*/ 92void 93Bus::recvFunctional(Packet &pkt, int id) 94{ 95 findPort(pkt.addr, id)->sendFunctional(pkt); 96} 97 98/** Function called by the port when the bus is recieving a status change.*/ 99void 100Bus::recvStatusChange(Port::Status status, int id) 101{ 102 DPRINTF(Bus, "Bus %d recieved status change from device id %d\n", 103 busId, id); 104 assert(status == Port::RangeChange && 105 "The other statuses need to be implemented."); 106 107 assert(id < interfaces.size() && id >= 0); 108 int x; 109 Port *port = interfaces[id]; 110 AddrRangeList ranges; 111 AddrRangeList snoops; 112 AddrRangeIter iter; 113 std::vector<DevMap>::iterator portIter; 114 115 // Clean out any previously existent ids 116 for (portIter = portList.begin(); portIter != portList.end(); ) { 117 if (portIter->portId == id) 118 portIter = portList.erase(portIter); 119 else 120 portIter++; 121 } 122 123 port->getPeerAddressRanges(ranges, snoops); 124 125 // not dealing with snooping yet either 126 assert(snoops.size() == 0); 127 for(iter = ranges.begin(); iter != ranges.end(); iter++) { 128 DevMap dm; 129 dm.portId = id; 130 dm.range = *iter; 131 132 DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start, 133 dm.range.end, id); 134 portList.push_back(dm); 135 } 136 DPRINTF(MMU, "port list has %d entries\n", portList.size()); 137 138 // tell all our peers that our address range has changed. 139 // Don't tell the device that caused this change, it already knows 140 for (x = 0; x < interfaces.size(); x++) 141 if (x != id) 142 interfaces[x]->sendStatusChange(Port::RangeChange); 143} 144 145void 146Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) 147{ 148 std::vector<DevMap>::iterator portIter; 149 150 resp.clear(); 151 snoop.clear(); 152 153 DPRINTF(Bus, "Bus id %d recieved address range request returning\n", 154 busId); 155 for (portIter = portList.begin(); portIter != portList.end(); portIter++) { 156 if (portIter->portId != id) { 157 resp.push_back(portIter->range); 158 DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start, 159 portIter->range.end); 160 } 161 } 162} 163 164BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus) 165 166 Param<int> bus_id; 167 168END_DECLARE_SIM_OBJECT_PARAMS(Bus) 169 170BEGIN_INIT_SIM_OBJECT_PARAMS(Bus) 171 INIT_PARAM(bus_id, "a globally unique bus id") 172END_INIT_SIM_OBJECT_PARAMS(Bus) 173 174CREATE_SIM_OBJECT(Bus) 175{ 176 return new Bus(getInstanceName(), bus_id); 177} 178 179REGISTER_SIM_OBJECT("Bus", Bus) 180