bridge.cc revision 2568
1 2/* 3 * Copyright (c) 2006 The Regents of The University of Michigan 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30/** 31 * @file Definition of a simple bus bridge without buffering. 32 */ 33 34 35#include "base/trace.hh" 36#include "mem/bridge.hh" 37#include "sim/builder.hh" 38 39void 40Bridge::init() 41{ 42 // Make sure that both sides are connected to. 43 if (sideA == NULL || sideB == NULL) 44 panic("Both ports of bus bridge are not connected to a bus.\n"); 45} 46 47 48/** Function called by the port when the bus is recieving a Timing 49 * transaction.*/ 50bool 51Bridge::recvTiming(Packet &pkt, Side id) 52{ 53 if (blockedA && id == SideA) 54 return false; 55 if (blockedB && id == SideB) 56 return false; 57 58 if (delay) { 59 if (!sendEvent.scheduled()) 60 sendEvent.schedule(curTick + delay); 61 if (id == SideA) { 62 inboundA.push_back(std::make_pair<Packet*, Tick>(&pkt, curTick)); 63 blockCheck(SideA); 64 } else { 65 inboundB.push_back(std::make_pair<Packet*, Tick>(&pkt, curTick)); 66 blockCheck(SideB); 67 } 68 } else { 69 if (id == SideB) { 70 sideA->sendPkt(pkt); 71 blockCheck(SideB); 72 } else { 73 sideB->sendPkt(pkt); 74 blockCheck(SideA); 75 } 76 } 77 return true; 78 79} 80 81void 82Bridge::blockCheck(Side id) 83{ 84 /* Check that we still have buffer space available. */ 85 if (id == SideB) { 86 if (sideA->numQueued() + inboundB.size() >= queueSizeA && !blockedB) { 87 sideB->sendStatusChange(Port::Blocked); 88 blockedB = true; 89 } else if (sideA->numQueued() + inboundB.size() < queueSizeA && blockedB) { 90 sideB->sendStatusChange(Port::Unblocked); 91 blockedB = false; 92 } 93 } else { 94 if (sideB->numQueued() + inboundA.size() >= queueSizeB && !blockedA) { 95 sideA->sendStatusChange(Port::Blocked); 96 blockedA = true; 97 } else if (sideB->numQueued() + inboundA.size() < queueSizeB && blockedA) { 98 sideA->sendStatusChange(Port::Unblocked); 99 blockedA = false; 100 } 101 } 102} 103 104void Bridge::timerEvent() 105{ 106 Tick t = 0; 107 108 assert(inboundA.size() || inboundB.size()); 109 if (inboundA.size()) { 110 while (inboundA.front().second <= curTick + delay){ 111 sideB->sendPkt(inboundA.front()); 112 inboundA.pop_front(); 113 } 114 if (inboundA.size()) 115 t = inboundA.front().second + delay; 116 } 117 if (inboundB.size()) { 118 while (inboundB.front().second <= curTick + delay){ 119 sideB->sendPkt(inboundA.front()); 120 inboundB.pop_front(); 121 } 122 if (inboundB.size()) 123 if (t == 0) 124 t = inboundB.front().second + delay; 125 else 126 t = std::min(t,inboundB.front().second + delay); 127 } else { 128 panic("timerEvent() called but nothing to do?"); 129 } 130 131 if (t != 0) 132 sendEvent.schedule(t); 133} 134 135 136void 137Bridge::BridgePort::sendPkt(Packet &pkt) 138{ 139 if (!sendTiming(pkt)) 140 outbound.push_back(std::make_pair<Packet*,Tick>(&pkt, curTick)); 141} 142 143void 144Bridge::BridgePort::sendPkt(std::pair<Packet*, Tick> p) 145{ 146 if (!sendTiming(*p.first)) 147 outbound.push_back(p); 148} 149 150 151Packet * 152Bridge::BridgePort::recvRetry() 153{ 154 Packet *pkt; 155 assert(outbound.size() > 0); 156 assert(outbound.front().second >= curTick + bridge->delay); 157 pkt = outbound.front().first; 158 outbound.pop_front(); 159 bridge->blockCheck(side); 160 return pkt; 161} 162 163/** Function called by the port when the bus is recieving a Atomic 164 * transaction.*/ 165Tick 166Bridge::recvAtomic(Packet &pkt, Side id) 167{ 168 pkt.time += delay; 169 170 if (id == SideA) 171 return sideB->sendAtomic(pkt); 172 else 173 return sideA->sendAtomic(pkt); 174} 175 176/** Function called by the port when the bus is recieving a Functional 177 * transaction.*/ 178void 179Bridge::recvFunctional(Packet &pkt, Side id) 180{ 181 pkt.time += delay; 182 std::list<std::pair<Packet*, Tick> >::iterator i; 183 bool pktContinue = true; 184 185 for(i = inboundA.begin(); i != inboundA.end(); ++i) { 186 if (pkt.intersect(i->first)) { 187 pktContinue &= fixPacket(pkt, *i->first); 188 } 189 } 190 191 for(i = inboundB.begin(); i != inboundB.end(); ++i) { 192 if (pkt.intersect(i->first)) { 193 pktContinue &= fixPacket(pkt, *i->first); 194 } 195 } 196 197 for(i = sideA->outbound.begin(); i != sideA->outbound.end(); ++i) { 198 if (pkt.intersect(i->first)) { 199 pktContinue &= fixPacket(pkt, *i->first); 200 } 201 } 202 203 for(i = sideB->outbound.begin(); i != sideB->outbound.end(); ++i) { 204 if (pkt.intersect(i->first)) { 205 pktContinue &= fixPacket(pkt, *i->first); 206 } 207 } 208 209 if (pktContinue) { 210 if (id == SideA) 211 sideB->sendFunctional(pkt); 212 else 213 sideA->sendFunctional(pkt); 214 } 215} 216 217/** Function called by the port when the bus is recieving a status change.*/ 218void 219Bridge::recvStatusChange(Port::Status status, Side id) 220{ 221 if (status == Port::Blocked || status == Port::Unblocked) 222 return ; 223 224 if (id == SideA) 225 sideB->sendStatusChange(status); 226 else 227 sideA->sendStatusChange(status); 228} 229 230void 231Bridge::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id) 232{ 233 if (id == SideA) 234 sideB->getPeerAddressRanges(resp, snoop); 235 else 236 sideA->getPeerAddressRanges(resp, snoop); 237} 238 239BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge) 240 241 Param<int> queue_size_a; 242 Param<int> queue_size_b; 243 Param<Tick> delay; 244 Param<bool> write_ack; 245 246END_DECLARE_SIM_OBJECT_PARAMS(Bridge) 247 248BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge) 249 250 INIT_PARAM(queue_size_a, "The size of the queue for data coming into side a"), 251 INIT_PARAM(queue_size_b, "The size of the queue for data coming into side b"), 252 INIT_PARAM(delay, "The miminum delay to cross this bridge"), 253 INIT_PARAM(write_ack, "Acknowledge any writes that are received.") 254 255END_INIT_SIM_OBJECT_PARAMS(Bridge) 256 257CREATE_SIM_OBJECT(Bridge) 258{ 259 return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay, 260 write_ack); 261} 262 263REGISTER_SIM_OBJECT("Bridge", Bridge) 264