bridge.cc (4433:4722c6787f69) | bridge.cc (4435:7da241055348) |
---|---|
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 --- 29 unchanged lines hidden (view full) --- 38#include <algorithm> 39 40#include "base/trace.hh" 41#include "mem/bridge.hh" 42#include "sim/builder.hh" 43 44Bridge::BridgePort::BridgePort(const std::string &_name, 45 Bridge *_bridge, BridgePort *_otherPort, | 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 --- 29 unchanged lines hidden (view full) --- 38#include <algorithm> 39 40#include "base/trace.hh" 41#include "mem/bridge.hh" 42#include "sim/builder.hh" 43 44Bridge::BridgePort::BridgePort(const std::string &_name, 45 Bridge *_bridge, BridgePort *_otherPort, |
46 int _delay, int _queueLimit, 47 bool fix_partial_write) | 46 int _delay, int _nack_delay, int _req_limit, 47 int _resp_limit, bool fix_partial_write) |
48 : Port(_name), bridge(_bridge), otherPort(_otherPort), | 48 : Port(_name), bridge(_bridge), otherPort(_otherPort), |
49 delay(_delay), fixPartialWrite(fix_partial_write), 50 outstandingResponses(0), queuedRequests(0), 51 queueLimit(_queueLimit), sendEvent(this) | 49 delay(_delay), nackDelay(_nack_delay), fixPartialWrite(fix_partial_write), 50 outstandingResponses(0), queuedRequests(0), inRetry(false), 51 reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this) |
52{ 53} 54 | 52{ 53} 54 |
55Bridge::Bridge(const std::string &n, int qsa, int qsb, 56 Tick _delay, int write_ack, bool fix_partial_write_a, 57 bool fix_partial_write_b) 58 : MemObject(n), 59 portA(n + "-portA", this, &portB, _delay, qsa, fix_partial_write_a), 60 portB(n + "-portB", this, &portA, _delay, qsa, fix_partial_write_b), 61 ackWrites(write_ack) | 55Bridge::Bridge(Params *p) 56 : MemObject(p->name), 57 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), 59 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), 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{ --- 19 unchanged lines hidden (view full) --- 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 | 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{ --- 19 unchanged lines hidden (view full) --- 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::queueFull() | 97Bridge::BridgePort::respQueueFull() |
98{ | 98{ |
99 // use >= here because sendQueue could get larger because of 100 // nacks getting inserted 101 return queuedRequests + outstandingResponses >= queueLimit; | 99 assert(outstandingResponses >= 0 && outstandingResponses <= respQueueLimit); 100 return outstandingResponses >= respQueueLimit; |
102} 103 | 101} 102 |
103bool 104Bridge::BridgePort::reqQueueFull() 105{ 106 assert(queuedRequests >= 0 && queuedRequests <= reqQueueLimit); 107 return queuedRequests >= reqQueueLimit; 108} 109 |
|
104/** Function called by the port when the bus is receiving a Timing 105 * transaction.*/ 106bool 107Bridge::BridgePort::recvTiming(PacketPtr pkt) 108{ 109 if (!(pkt->flags & SNOOP_COMMIT)) 110 return true; 111 112 113 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", 114 pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 115 | 110/** Function called by the port when the bus is receiving a Timing 111 * transaction.*/ 112bool 113Bridge::BridgePort::recvTiming(PacketPtr pkt) 114{ 115 if (!(pkt->flags & SNOOP_COMMIT)) 116 return true; 117 118 119 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", 120 pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 121 |
116 if (pkt->isRequest() && otherPort->queueFull()) { | 122 if (pkt->isRequest() && otherPort->reqQueueFull()) { |
117 DPRINTF(BusBridge, "Remote queue full, nacking\n"); 118 nackRequest(pkt); 119 return true; 120 } 121 122 if (pkt->needsResponse() && pkt->result != Packet::Nacked) | 123 DPRINTF(BusBridge, "Remote queue full, nacking\n"); 124 nackRequest(pkt); 125 return true; 126 } 127 128 if (pkt->needsResponse() && pkt->result != Packet::Nacked) |
123 if (queueFull()) { | 129 if (respQueueFull()) { |
124 DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n"); 125 DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n", 126 sendQueue.size(), queuedRequests, outstandingResponses); 127 nackRequest(pkt); 128 return true; 129 } else { 130 DPRINTF(BusBridge, "Request Needs response, reserving space\n"); 131 ++outstandingResponses; --- 7 unchanged lines hidden (view full) --- 139void 140Bridge::BridgePort::nackRequest(PacketPtr pkt) 141{ 142 // Nack the packet 143 pkt->result = Packet::Nacked; 144 pkt->setDest(pkt->getSrc()); 145 146 //put it on the list to send | 130 DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n"); 131 DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n", 132 sendQueue.size(), queuedRequests, outstandingResponses); 133 nackRequest(pkt); 134 return true; 135 } else { 136 DPRINTF(BusBridge, "Request Needs response, reserving space\n"); 137 ++outstandingResponses; --- 7 unchanged lines hidden (view full) --- 145void 146Bridge::BridgePort::nackRequest(PacketPtr pkt) 147{ 148 // Nack the packet 149 pkt->result = Packet::Nacked; 150 pkt->setDest(pkt->getSrc()); 151 152 //put it on the list to send |
147 Tick readyTime = curTick + delay; | 153 Tick readyTime = curTick + nackDelay; |
148 PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true); | 154 PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true); |
155 156 // nothing on the list, add it and we're done |
|
149 if (sendQueue.empty()) { | 157 if (sendQueue.empty()) { |
158 assert(!sendEvent.scheduled()); |
|
150 sendEvent.schedule(readyTime); | 159 sendEvent.schedule(readyTime); |
160 sendQueue.push_back(buf); 161 return; |
|
151 } | 162 } |
152 sendQueue.push_back(buf); | 163 164 assert(sendEvent.scheduled() || inRetry); 165 166 // does it go at the end? 167 if (readyTime >= sendQueue.back()->ready) { 168 sendQueue.push_back(buf); 169 return; 170 } 171 172 // ok, somewhere in the middle, fun 173 std::list<PacketBuffer*>::iterator i = sendQueue.begin(); 174 std::list<PacketBuffer*>::iterator end = sendQueue.end(); 175 std::list<PacketBuffer*>::iterator begin = sendQueue.begin(); 176 bool done = false; 177 178 while (i != end && !done) { 179 if (readyTime < (*i)->ready) { 180 if (i == begin) 181 sendEvent.reschedule(readyTime); 182 sendQueue.insert(i,buf); 183 done = true; 184 } 185 i++; 186 } 187 assert(done); |
153} 154 155 156void 157Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) 158{ 159 if (pkt->isResponse() || pkt->result == Packet::Nacked) { 160 // This is a response for a request we forwarded earlier. The --- 33 unchanged lines hidden (view full) --- 194 sendQueue.push_back(buf); 195} 196 197void 198Bridge::BridgePort::trySend() 199{ 200 assert(!sendQueue.empty()); 201 | 188} 189 190 191void 192Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) 193{ 194 if (pkt->isResponse() || pkt->result == Packet::Nacked) { 195 // This is a response for a request we forwarded earlier. The --- 33 unchanged lines hidden (view full) --- 229 sendQueue.push_back(buf); 230} 231 232void 233Bridge::BridgePort::trySend() 234{ 235 assert(!sendQueue.empty()); 236 |
202 bool was_full = queueFull(); | |
203 int pbs = peerBlockSize(); 204 205 PacketBuffer *buf = sendQueue.front(); 206 207 assert(buf->ready <= curTick); 208 209 PacketPtr pkt = buf->pkt; 210 --- 29 unchanged lines hidden (view full) --- 240 --queuedRequests; 241 242 // If there are more packets to send, schedule event to try again. 243 if (!sendQueue.empty()) { 244 buf = sendQueue.front(); 245 DPRINTF(BusBridge, "Scheduling next send\n"); 246 sendEvent.schedule(std::max(buf->ready, curTick + 1)); 247 } | 237 int pbs = peerBlockSize(); 238 239 PacketBuffer *buf = sendQueue.front(); 240 241 assert(buf->ready <= curTick); 242 243 PacketPtr pkt = buf->pkt; 244 --- 29 unchanged lines hidden (view full) --- 274 --queuedRequests; 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 } |
248 // Let things start sending again 249 if (was_full && !queueFull()) { 250 DPRINTF(BusBridge, "Queue was full, sending retry\n"); 251 otherPort->sendRetry(); 252 } 253 | |
254 } else { 255 DPRINTF(BusBridge, " unsuccessful\n"); 256 buf->undoPartialWriteFix(); | 282 } else { 283 DPRINTF(BusBridge, " unsuccessful\n"); 284 buf->undoPartialWriteFix(); |
285 inRetry = true; |
|
257 } 258 DPRINTF(BusBridge, "trySend: queue size: %d outreq: %d outstanding resp: %d\n", 259 sendQueue.size(), queuedRequests, outstandingResponses); 260} 261 262 263void 264Bridge::BridgePort::recvRetry() 265{ | 286 } 287 DPRINTF(BusBridge, "trySend: queue size: %d outreq: %d outstanding resp: %d\n", 288 sendQueue.size(), queuedRequests, outstandingResponses); 289} 290 291 292void 293Bridge::BridgePort::recvRetry() 294{ |
266 trySend(); | 295 inRetry = false; 296 Tick nextReady = sendQueue.front()->ready; 297 if (nextReady <= curTick) 298 trySend(); 299 else 300 sendEvent.schedule(nextReady); |
267} 268 269/** Function called by the port when the bus is receiving a Atomic 270 * transaction.*/ 271Tick 272Bridge::BridgePort::recvAtomic(PacketPtr pkt) 273{ 274 return otherPort->sendAtomic(pkt) + delay; --- 29 unchanged lines hidden (view full) --- 304Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, 305 AddrRangeList &snoop) 306{ 307 otherPort->getPeerAddressRanges(resp, snoop); 308} 309 310BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge) 311 | 301} 302 303/** Function called by the port when the bus is receiving a Atomic 304 * transaction.*/ 305Tick 306Bridge::BridgePort::recvAtomic(PacketPtr pkt) 307{ 308 return otherPort->sendAtomic(pkt) + delay; --- 29 unchanged lines hidden (view full) --- 338Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, 339 AddrRangeList &snoop) 340{ 341 otherPort->getPeerAddressRanges(resp, snoop); 342} 343 344BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge) 345 |
312 Param<int> queue_size_a; 313 Param<int> queue_size_b; | 346 Param<int> req_size_a; 347 Param<int> req_size_b; 348 Param<int> resp_size_a; 349 Param<int> resp_size_b; |
314 Param<Tick> delay; | 350 Param<Tick> delay; |
351 Param<Tick> nack_delay; |
|
315 Param<bool> write_ack; 316 Param<bool> fix_partial_write_a; 317 Param<bool> fix_partial_write_b; 318 319END_DECLARE_SIM_OBJECT_PARAMS(Bridge) 320 321BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge) 322 | 352 Param<bool> write_ack; 353 Param<bool> fix_partial_write_a; 354 Param<bool> fix_partial_write_b; 355 356END_DECLARE_SIM_OBJECT_PARAMS(Bridge) 357 358BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge) 359 |
323 INIT_PARAM(queue_size_a, "The size of the queue for data coming into side a"), 324 INIT_PARAM(queue_size_b, "The size of the queue for data coming into side b"), | 360 INIT_PARAM(req_size_a, "The size of the queue for requests coming into side a"), 361 INIT_PARAM(req_size_b, "The size of the queue for requests coming into side b"), 362 INIT_PARAM(resp_size_a, "The size of the queue for responses coming into side a"), 363 INIT_PARAM(resp_size_b, "The size of the queue for responses coming into side b"), |
325 INIT_PARAM(delay, "The miminum delay to cross this bridge"), | 364 INIT_PARAM(delay, "The miminum delay to cross this bridge"), |
365 INIT_PARAM(nack_delay, "The minimum delay to nack a packet"), |
|
326 INIT_PARAM(write_ack, "Acknowledge any writes that are received."), 327 INIT_PARAM(fix_partial_write_a, "Fixup any partial block writes that are received"), 328 INIT_PARAM(fix_partial_write_b, "Fixup any partial block writes that are received") 329 330END_INIT_SIM_OBJECT_PARAMS(Bridge) 331 332CREATE_SIM_OBJECT(Bridge) 333{ | 366 INIT_PARAM(write_ack, "Acknowledge any writes that are received."), 367 INIT_PARAM(fix_partial_write_a, "Fixup any partial block writes that are received"), 368 INIT_PARAM(fix_partial_write_b, "Fixup any partial block writes that are received") 369 370END_INIT_SIM_OBJECT_PARAMS(Bridge) 371 372CREATE_SIM_OBJECT(Bridge) 373{ |
334 return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay, 335 write_ack, fix_partial_write_a, fix_partial_write_b); | 374 Bridge::Params *p = new Bridge::Params; 375 p->name = getInstanceName(); 376 p->req_size_a = req_size_a; 377 p->req_size_b = req_size_b; 378 p->resp_size_a = resp_size_a; 379 p->resp_size_b = resp_size_b; 380 p->delay = delay; 381 p->nack_delay = nack_delay; 382 p->write_ack = write_ack; 383 p->fix_partial_write_a = fix_partial_write_a; 384 p->fix_partial_write_b = fix_partial_write_b; 385 return new Bridge(p); |
336} 337 338REGISTER_SIM_OBJECT("Bridge", Bridge) 339 | 386} 387 388REGISTER_SIM_OBJECT("Bridge", Bridge) 389 |