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 * Authors: Ali Saidi 30 * Steve Reinhardt 31 */ 32 33/** 34 * @file 35 * Definition of a simple bus bridge without buffering. 36 */ 37 38#include <algorithm> 39
| 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 * Authors: Ali Saidi 30 * Steve Reinhardt 31 */ 32 33/** 34 * @file 35 * Definition of a simple bus bridge without buffering. 36 */ 37 38#include <algorithm> 39
|
| 40#include "base/range_ops.hh"
|
40#include "base/trace.hh" 41#include "mem/bridge.hh" 42#include "params/Bridge.hh" 43 44Bridge::BridgePort::BridgePort(const std::string &_name, 45 Bridge *_bridge, BridgePort *_otherPort, 46 int _delay, int _nack_delay, int _req_limit,
| 41#include "base/trace.hh" 42#include "mem/bridge.hh" 43#include "params/Bridge.hh" 44 45Bridge::BridgePort::BridgePort(const std::string &_name, 46 Bridge *_bridge, BridgePort *_otherPort, 47 int _delay, int _nack_delay, int _req_limit,
|
47 int _resp_limit, bool fix_partial_write)
| 48 int _resp_limit, 49 std::vector<Range<Addr> > filter_ranges)
|
48 : Port(_name), bridge(_bridge), otherPort(_otherPort),
| 50 : Port(_name), bridge(_bridge), otherPort(_otherPort),
|
49 delay(_delay), nackDelay(_nack_delay), fixPartialWrite(fix_partial_write),
| 51 delay(_delay), nackDelay(_nack_delay), filterRanges(filter_ranges),
|
50 outstandingResponses(0), queuedRequests(0), inRetry(false), 51 reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this) 52{ 53} 54 55Bridge::Bridge(Params *p) 56 : MemObject(p->name), 57 portA(p->name + "-portA", this, &portB, p->delay, p->nack_delay,
| 52 outstandingResponses(0), queuedRequests(0), inRetry(false), 53 reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this) 54{ 55} 56 57Bridge::Bridge(Params *p) 58 : MemObject(p->name), 59 portA(p->name + "-portA", this, &portB, p->delay, p->nack_delay,
|
58 p->req_size_a, p->resp_size_a, p->fix_partial_write_a),
| 60 p->req_size_a, p->resp_size_a, p->filter_ranges_a),
|
59 portB(p->name + "-portB", this, &portA, p->delay, p->nack_delay,
| 61 portB(p->name + "-portB", this, &portA, p->delay, p->nack_delay,
|
60 p->req_size_b, p->resp_size_b, p->fix_partial_write_b),
| 62 p->req_size_b, p->resp_size_b, p->filter_ranges_b),
|
61 ackWrites(p->write_ack), _params(p) 62{ 63 if (ackWrites) 64 panic("No support for acknowledging writes\n"); 65} 66 67Port * 68Bridge::getPort(const std::string &if_name, int idx) 69{ 70 BridgePort *port; 71 72 if (if_name == "side_a") 73 port = &portA; 74 else if (if_name == "side_b") 75 port = &portB; 76 else 77 return NULL; 78 79 if (port->getPeer() != NULL) 80 panic("bridge side %s already connected to.", if_name); 81 return port; 82} 83 84 85void 86Bridge::init() 87{ 88 // Make sure that both sides are connected to. 89 if (portA.getPeer() == NULL || portB.getPeer() == NULL) 90 fatal("Both ports of bus bridge are not connected to a bus.\n"); 91 92 if (portA.peerBlockSize() != portB.peerBlockSize()) 93 fatal("Busses don't have the same block size... Not supported.\n"); 94} 95 96bool 97Bridge::BridgePort::respQueueFull() 98{ 99 assert(outstandingResponses >= 0 && outstandingResponses <= respQueueLimit); 100 return outstandingResponses >= respQueueLimit; 101} 102 103bool 104Bridge::BridgePort::reqQueueFull() 105{ 106 assert(queuedRequests >= 0 && queuedRequests <= reqQueueLimit); 107 return queuedRequests >= reqQueueLimit; 108} 109 110/** Function called by the port when the bus is receiving a Timing 111 * transaction.*/ 112bool 113Bridge::BridgePort::recvTiming(PacketPtr pkt) 114{ 115 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", 116 pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 117 118 DPRINTF(BusBridge, "Local queue size: %d outreq: %d outresp: %d\n", 119 sendQueue.size(), queuedRequests, outstandingResponses); 120 DPRINTF(BusBridge, "Remove queue size: %d outreq: %d outresp: %d\n", 121 otherPort->sendQueue.size(), otherPort->queuedRequests, 122 otherPort->outstandingResponses); 123 124 if (pkt->isRequest() && otherPort->reqQueueFull() && !pkt->wasNacked()) { 125 DPRINTF(BusBridge, "Remote queue full, nacking\n"); 126 nackRequest(pkt); 127 return true; 128 } 129 130 if (pkt->needsResponse() && !pkt->wasNacked()) 131 if (respQueueFull()) { 132 DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n"); 133 DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n", 134 sendQueue.size(), queuedRequests, outstandingResponses); 135 nackRequest(pkt); 136 return true; 137 } else { 138 DPRINTF(BusBridge, "Request Needs response, reserving space\n"); 139 ++outstandingResponses; 140 } 141 142 otherPort->queueForSendTiming(pkt); 143 144 return true; 145} 146 147void 148Bridge::BridgePort::nackRequest(PacketPtr pkt) 149{ 150 // Nack the packet 151 pkt->setNacked(); 152 pkt->setDest(pkt->getSrc()); 153 154 //put it on the list to send 155 Tick readyTime = curTick + nackDelay; 156 PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true); 157 158 // nothing on the list, add it and we're done 159 if (sendQueue.empty()) { 160 assert(!sendEvent.scheduled()); 161 sendEvent.schedule(readyTime); 162 sendQueue.push_back(buf); 163 return; 164 } 165 166 assert(sendEvent.scheduled() || inRetry); 167 168 // does it go at the end? 169 if (readyTime >= sendQueue.back()->ready) { 170 sendQueue.push_back(buf); 171 return; 172 } 173 174 // ok, somewhere in the middle, fun 175 std::list<PacketBuffer*>::iterator i = sendQueue.begin(); 176 std::list<PacketBuffer*>::iterator end = sendQueue.end(); 177 std::list<PacketBuffer*>::iterator begin = sendQueue.begin(); 178 bool done = false; 179 180 while (i != end && !done) { 181 if (readyTime < (*i)->ready) { 182 if (i == begin) 183 sendEvent.reschedule(readyTime); 184 sendQueue.insert(i,buf); 185 done = true; 186 } 187 i++; 188 } 189 assert(done); 190} 191 192 193void 194Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) 195{ 196 if (pkt->isResponse() || pkt->wasNacked()) { 197 // This is a response for a request we forwarded earlier. The 198 // corresponding PacketBuffer should be stored in the packet's 199 // senderState field. 200 PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState); 201 assert(buf != NULL); 202 // set up new packet dest & senderState based on values saved 203 // from original request 204 buf->fixResponse(pkt); 205 206 // Check if this packet was expecting a response and it's a nacked 207 // packet, in which case we will never being seeing it 208 if (buf->expectResponse && pkt->wasNacked()) 209 --outstandingResponses; 210 211 DPRINTF(BusBridge, "response, new dest %d\n", pkt->getDest()); 212 delete buf; 213 } 214 215 216 if (pkt->isRequest() && !pkt->wasNacked()) { 217 ++queuedRequests; 218 } 219 220 221 222 Tick readyTime = curTick + delay; 223 PacketBuffer *buf = new PacketBuffer(pkt, readyTime); 224 225 // If we're about to put this packet at the head of the queue, we 226 // need to schedule an event to do the transmit. Otherwise there 227 // should already be an event scheduled for sending the head 228 // packet. 229 if (sendQueue.empty()) { 230 sendEvent.schedule(readyTime); 231 } 232 sendQueue.push_back(buf); 233} 234 235void 236Bridge::BridgePort::trySend() 237{ 238 assert(!sendQueue.empty()); 239 240 PacketBuffer *buf = sendQueue.front(); 241 242 assert(buf->ready <= curTick); 243 244 PacketPtr pkt = buf->pkt; 245
| 63 ackWrites(p->write_ack), _params(p) 64{ 65 if (ackWrites) 66 panic("No support for acknowledging writes\n"); 67} 68 69Port * 70Bridge::getPort(const std::string &if_name, int idx) 71{ 72 BridgePort *port; 73 74 if (if_name == "side_a") 75 port = &portA; 76 else if (if_name == "side_b") 77 port = &portB; 78 else 79 return NULL; 80 81 if (port->getPeer() != NULL) 82 panic("bridge side %s already connected to.", if_name); 83 return port; 84} 85 86 87void 88Bridge::init() 89{ 90 // Make sure that both sides are connected to. 91 if (portA.getPeer() == NULL || portB.getPeer() == NULL) 92 fatal("Both ports of bus bridge are not connected to a bus.\n"); 93 94 if (portA.peerBlockSize() != portB.peerBlockSize()) 95 fatal("Busses don't have the same block size... Not supported.\n"); 96} 97 98bool 99Bridge::BridgePort::respQueueFull() 100{ 101 assert(outstandingResponses >= 0 && outstandingResponses <= respQueueLimit); 102 return outstandingResponses >= respQueueLimit; 103} 104 105bool 106Bridge::BridgePort::reqQueueFull() 107{ 108 assert(queuedRequests >= 0 && queuedRequests <= reqQueueLimit); 109 return queuedRequests >= reqQueueLimit; 110} 111 112/** Function called by the port when the bus is receiving a Timing 113 * transaction.*/ 114bool 115Bridge::BridgePort::recvTiming(PacketPtr pkt) 116{ 117 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", 118 pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 119 120 DPRINTF(BusBridge, "Local queue size: %d outreq: %d outresp: %d\n", 121 sendQueue.size(), queuedRequests, outstandingResponses); 122 DPRINTF(BusBridge, "Remove queue size: %d outreq: %d outresp: %d\n", 123 otherPort->sendQueue.size(), otherPort->queuedRequests, 124 otherPort->outstandingResponses); 125 126 if (pkt->isRequest() && otherPort->reqQueueFull() && !pkt->wasNacked()) { 127 DPRINTF(BusBridge, "Remote queue full, nacking\n"); 128 nackRequest(pkt); 129 return true; 130 } 131 132 if (pkt->needsResponse() && !pkt->wasNacked()) 133 if (respQueueFull()) { 134 DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n"); 135 DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n", 136 sendQueue.size(), queuedRequests, outstandingResponses); 137 nackRequest(pkt); 138 return true; 139 } else { 140 DPRINTF(BusBridge, "Request Needs response, reserving space\n"); 141 ++outstandingResponses; 142 } 143 144 otherPort->queueForSendTiming(pkt); 145 146 return true; 147} 148 149void 150Bridge::BridgePort::nackRequest(PacketPtr pkt) 151{ 152 // Nack the packet 153 pkt->setNacked(); 154 pkt->setDest(pkt->getSrc()); 155 156 //put it on the list to send 157 Tick readyTime = curTick + nackDelay; 158 PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true); 159 160 // nothing on the list, add it and we're done 161 if (sendQueue.empty()) { 162 assert(!sendEvent.scheduled()); 163 sendEvent.schedule(readyTime); 164 sendQueue.push_back(buf); 165 return; 166 } 167 168 assert(sendEvent.scheduled() || inRetry); 169 170 // does it go at the end? 171 if (readyTime >= sendQueue.back()->ready) { 172 sendQueue.push_back(buf); 173 return; 174 } 175 176 // ok, somewhere in the middle, fun 177 std::list<PacketBuffer*>::iterator i = sendQueue.begin(); 178 std::list<PacketBuffer*>::iterator end = sendQueue.end(); 179 std::list<PacketBuffer*>::iterator begin = sendQueue.begin(); 180 bool done = false; 181 182 while (i != end && !done) { 183 if (readyTime < (*i)->ready) { 184 if (i == begin) 185 sendEvent.reschedule(readyTime); 186 sendQueue.insert(i,buf); 187 done = true; 188 } 189 i++; 190 } 191 assert(done); 192} 193 194 195void 196Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) 197{ 198 if (pkt->isResponse() || pkt->wasNacked()) { 199 // This is a response for a request we forwarded earlier. The 200 // corresponding PacketBuffer should be stored in the packet's 201 // senderState field. 202 PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState); 203 assert(buf != NULL); 204 // set up new packet dest & senderState based on values saved 205 // from original request 206 buf->fixResponse(pkt); 207 208 // Check if this packet was expecting a response and it's a nacked 209 // packet, in which case we will never being seeing it 210 if (buf->expectResponse && pkt->wasNacked()) 211 --outstandingResponses; 212 213 DPRINTF(BusBridge, "response, new dest %d\n", pkt->getDest()); 214 delete buf; 215 } 216 217 218 if (pkt->isRequest() && !pkt->wasNacked()) { 219 ++queuedRequests; 220 } 221 222 223 224 Tick readyTime = curTick + delay; 225 PacketBuffer *buf = new PacketBuffer(pkt, readyTime); 226 227 // If we're about to put this packet at the head of the queue, we 228 // need to schedule an event to do the transmit. Otherwise there 229 // should already be an event scheduled for sending the head 230 // packet. 231 if (sendQueue.empty()) { 232 sendEvent.schedule(readyTime); 233 } 234 sendQueue.push_back(buf); 235} 236 237void 238Bridge::BridgePort::trySend() 239{ 240 assert(!sendQueue.empty()); 241 242 PacketBuffer *buf = sendQueue.front(); 243 244 assert(buf->ready <= curTick); 245 246 PacketPtr pkt = buf->pkt; 247
|
246 // Ugly! @todo When multilevel coherence works this will be removed 247 if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite && 248 !pkt->wasNacked()) { 249 PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq, 250 Packet::Broadcast); 251 funcPkt->dataStatic(pkt->getPtr<uint8_t>()); 252 sendFunctional(funcPkt); 253 pkt->cmd = MemCmd::WriteReq; 254 delete funcPkt; 255 } 256
| |
257 DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", 258 buf->origSrc, pkt->getDest(), pkt->getAddr()); 259 260 bool wasReq = pkt->isRequest(); 261 bool wasNacked = pkt->wasNacked(); 262 263 if (sendTiming(pkt)) { 264 // send successful 265 sendQueue.pop_front(); 266 buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it 267 268 if (buf->expectResponse) { 269 // Must wait for response 270 DPRINTF(BusBridge, " successful: awaiting response (%d)\n", 271 outstandingResponses); 272 } else { 273 // no response expected... deallocate packet buffer now. 274 DPRINTF(BusBridge, " successful: no response expected\n"); 275 delete buf; 276 } 277 278 if (!wasNacked) { 279 if (wasReq) 280 --queuedRequests; 281 else 282 --outstandingResponses; 283 } 284 285 // If there are more packets to send, schedule event to try again. 286 if (!sendQueue.empty()) { 287 buf = sendQueue.front(); 288 DPRINTF(BusBridge, "Scheduling next send\n"); 289 sendEvent.schedule(std::max(buf->ready, curTick + 1)); 290 } 291 } else { 292 DPRINTF(BusBridge, " unsuccessful\n"); 293 inRetry = true; 294 } 295 DPRINTF(BusBridge, "trySend: queue size: %d outreq: %d outstanding resp: %d\n", 296 sendQueue.size(), queuedRequests, outstandingResponses); 297} 298 299 300void 301Bridge::BridgePort::recvRetry() 302{ 303 inRetry = false; 304 Tick nextReady = sendQueue.front()->ready; 305 if (nextReady <= curTick) 306 trySend(); 307 else 308 sendEvent.schedule(nextReady); 309} 310 311/** Function called by the port when the bus is receiving a Atomic 312 * transaction.*/ 313Tick 314Bridge::BridgePort::recvAtomic(PacketPtr pkt) 315{
| 248 DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", 249 buf->origSrc, pkt->getDest(), pkt->getAddr()); 250 251 bool wasReq = pkt->isRequest(); 252 bool wasNacked = pkt->wasNacked(); 253 254 if (sendTiming(pkt)) { 255 // send successful 256 sendQueue.pop_front(); 257 buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it 258 259 if (buf->expectResponse) { 260 // Must wait for response 261 DPRINTF(BusBridge, " successful: awaiting response (%d)\n", 262 outstandingResponses); 263 } else { 264 // no response expected... deallocate packet buffer now. 265 DPRINTF(BusBridge, " successful: no response expected\n"); 266 delete buf; 267 } 268 269 if (!wasNacked) { 270 if (wasReq) 271 --queuedRequests; 272 else 273 --outstandingResponses; 274 } 275 276 // If there are more packets to send, schedule event to try again. 277 if (!sendQueue.empty()) { 278 buf = sendQueue.front(); 279 DPRINTF(BusBridge, "Scheduling next send\n"); 280 sendEvent.schedule(std::max(buf->ready, curTick + 1)); 281 } 282 } else { 283 DPRINTF(BusBridge, " unsuccessful\n"); 284 inRetry = true; 285 } 286 DPRINTF(BusBridge, "trySend: queue size: %d outreq: %d outstanding resp: %d\n", 287 sendQueue.size(), queuedRequests, outstandingResponses); 288} 289 290 291void 292Bridge::BridgePort::recvRetry() 293{ 294 inRetry = false; 295 Tick nextReady = sendQueue.front()->ready; 296 if (nextReady <= curTick) 297 trySend(); 298 else 299 sendEvent.schedule(nextReady); 300} 301 302/** Function called by the port when the bus is receiving a Atomic 303 * transaction.*/ 304Tick 305Bridge::BridgePort::recvAtomic(PacketPtr pkt) 306{
|
316 // fix partial atomic writes... similar to the timing code that does the 317 // same... will be removed once our code gets this right 318 if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite) { 319 320 PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq, 321 Packet::Broadcast); 322 funcPkt->dataStatic(pkt->getPtr<uint8_t>()); 323 otherPort->sendFunctional(funcPkt); 324 delete funcPkt; 325 pkt->cmd = MemCmd::WriteReq; 326 }
| |
327 return delay + otherPort->sendAtomic(pkt); 328} 329 330/** Function called by the port when the bus is receiving a Functional 331 * transaction.*/ 332void 333Bridge::BridgePort::recvFunctional(PacketPtr pkt) 334{ 335 std::list<PacketBuffer*>::iterator i; 336 337 for (i = sendQueue.begin(); i != sendQueue.end(); ++i) { 338 if (pkt->checkFunctional((*i)->pkt)) 339 return; 340 } 341 342 // fall through if pkt still not satisfied 343 otherPort->sendFunctional(pkt); 344} 345 346/** Function called by the port when the bus is receiving a status change.*/ 347void 348Bridge::BridgePort::recvStatusChange(Port::Status status) 349{ 350 otherPort->sendStatusChange(status); 351} 352 353void 354Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, 355 bool &snoop) 356{ 357 otherPort->getPeerAddressRanges(resp, snoop);
| 307 return delay + otherPort->sendAtomic(pkt); 308} 309 310/** Function called by the port when the bus is receiving a Functional 311 * transaction.*/ 312void 313Bridge::BridgePort::recvFunctional(PacketPtr pkt) 314{ 315 std::list<PacketBuffer*>::iterator i; 316 317 for (i = sendQueue.begin(); i != sendQueue.end(); ++i) { 318 if (pkt->checkFunctional((*i)->pkt)) 319 return; 320 } 321 322 // fall through if pkt still not satisfied 323 otherPort->sendFunctional(pkt); 324} 325 326/** Function called by the port when the bus is receiving a status change.*/ 327void 328Bridge::BridgePort::recvStatusChange(Port::Status status) 329{ 330 otherPort->sendStatusChange(status); 331} 332 333void 334Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, 335 bool &snoop) 336{ 337 otherPort->getPeerAddressRanges(resp, snoop);
|
| 338 FilterRangeList(filterRanges, resp);
|
358 // we don't allow snooping across bridges 359 snoop = false; 360} 361 362Bridge * 363BridgeParams::create() 364{ 365 return new Bridge(this); 366}
| 339 // we don't allow snooping across bridges 340 snoop = false; 341} 342 343Bridge * 344BridgeParams::create() 345{ 346 return new Bridge(this); 347}
|