bridge.cc (4762:c94e103c83ad) | bridge.cc (4870:fcc39d001154) |
---|---|
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 --- 25 unchanged lines hidden (view full) --- 34 * @file 35 * Definition of a simple bus bridge without buffering. 36 */ 37 38#include <algorithm> 39 40#include "base/trace.hh" 41#include "mem/bridge.hh" | 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 --- 25 unchanged lines hidden (view full) --- 34 * @file 35 * Definition of a simple bus bridge without buffering. 36 */ 37 38#include <algorithm> 39 40#include "base/trace.hh" 41#include "mem/bridge.hh" |
42#include "params/Bridge.hh" | 42#include "sim/builder.hh" |
43 44Bridge::BridgePort::BridgePort(const std::string &_name, 45 Bridge *_bridge, BridgePort *_otherPort, 46 int _delay, int _nack_delay, int _req_limit, 47 int _resp_limit, bool fix_partial_write) 48 : Port(_name), bridge(_bridge), otherPort(_otherPort), 49 delay(_delay), nackDelay(_nack_delay), fixPartialWrite(fix_partial_write), 50 outstandingResponses(0), queuedRequests(0), inRetry(false), --- 56 unchanged lines hidden (view full) --- 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{ | 43 44Bridge::BridgePort::BridgePort(const std::string &_name, 45 Bridge *_bridge, BridgePort *_otherPort, 46 int _delay, int _nack_delay, int _req_limit, 47 int _resp_limit, bool fix_partial_write) 48 : Port(_name), bridge(_bridge), otherPort(_otherPort), 49 delay(_delay), nackDelay(_nack_delay), fixPartialWrite(fix_partial_write), 50 outstandingResponses(0), queuedRequests(0), inRetry(false), --- 56 unchanged lines hidden (view full) --- 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 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 122 DPRINTF(BusBridge, "Local queue size: %d outreq: %d outresp: %d\n", 123 sendQueue.size(), queuedRequests, outstandingResponses); 124 DPRINTF(BusBridge, "Remove queue size: %d outreq: %d outresp: %d\n", 125 otherPort->sendQueue.size(), otherPort->queuedRequests, 126 otherPort->outstandingResponses); 127 | 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 |
128 if (pkt->isRequest() && otherPort->reqQueueFull() && pkt->result != 129 Packet::Nacked) { | 124 if (pkt->isRequest() && otherPort->reqQueueFull() && !pkt->wasNacked()) { |
130 DPRINTF(BusBridge, "Remote queue full, nacking\n"); 131 nackRequest(pkt); 132 return true; 133 } 134 | 125 DPRINTF(BusBridge, "Remote queue full, nacking\n"); 126 nackRequest(pkt); 127 return true; 128 } 129 |
135 if (pkt->needsResponse() && pkt->result != Packet::Nacked) | 130 if (pkt->needsResponse() && !pkt->wasNacked()) |
136 if (respQueueFull()) { 137 DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n"); 138 DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n", 139 sendQueue.size(), queuedRequests, outstandingResponses); 140 nackRequest(pkt); 141 return true; 142 } else { 143 DPRINTF(BusBridge, "Request Needs response, reserving space\n"); --- 4 unchanged lines hidden (view full) --- 148 149 return true; 150} 151 152void 153Bridge::BridgePort::nackRequest(PacketPtr pkt) 154{ 155 // Nack the packet | 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"); --- 4 unchanged lines hidden (view full) --- 143 144 return true; 145} 146 147void 148Bridge::BridgePort::nackRequest(PacketPtr pkt) 149{ 150 // Nack the packet |
156 pkt->result = Packet::Nacked; | 151 pkt->setNacked(); |
157 pkt->setDest(pkt->getSrc()); 158 159 //put it on the list to send 160 Tick readyTime = curTick + nackDelay; 161 PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true); 162 163 // nothing on the list, add it and we're done 164 if (sendQueue.empty()) { --- 28 unchanged lines hidden (view full) --- 193 } 194 assert(done); 195} 196 197 198void 199Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) 200{ | 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()) { --- 28 unchanged lines hidden (view full) --- 188 } 189 assert(done); 190} 191 192 193void 194Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) 195{ |
201 if (pkt->isResponse() || pkt->result == Packet::Nacked) { | 196 if (pkt->isResponse() || pkt->wasNacked()) { |
202 // This is a response for a request we forwarded earlier. The 203 // corresponding PacketBuffer should be stored in the packet's 204 // senderState field. 205 PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState); 206 assert(buf != NULL); 207 // set up new packet dest & senderState based on values saved 208 // from original request 209 buf->fixResponse(pkt); 210 211 // Check if this packet was expecting a response and it's a nacked 212 // packet, in which case we will never being seeing it | 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 |
213 if (buf->expectResponse && pkt->result == Packet::Nacked) | 208 if (buf->expectResponse && pkt->wasNacked()) |
214 --outstandingResponses; 215 | 209 --outstandingResponses; 210 |
216 DPRINTF(BusBridge, "response, new dest %d\n", pkt->getDest()); | 211 212 DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n", 213 pkt->senderState, buf); 214 DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest()); |
217 delete buf; 218 } 219 220 | 215 delete buf; 216 } 217 218 |
221 if (pkt->isRequest() && pkt->result != Packet::Nacked) { | 219 if (pkt->isRequest() && !pkt->wasNacked()) { |
222 ++queuedRequests; 223 } 224 225 226 227 Tick readyTime = curTick + delay; 228 PacketBuffer *buf = new PacketBuffer(pkt, readyTime); | 220 ++queuedRequests; 221 } 222 223 224 225 Tick readyTime = curTick + delay; 226 PacketBuffer *buf = new PacketBuffer(pkt, readyTime); |
227 DPRINTF(BusBridge, "old sender state: %#X, new sender state: %#X\n", 228 buf->origSenderState, buf); |
|
229 230 // If we're about to put this packet at the head of the queue, we 231 // need to schedule an event to do the transmit. Otherwise there 232 // should already be an event scheduled for sending the head 233 // packet. 234 if (sendQueue.empty()) { 235 sendEvent.schedule(readyTime); 236 } --- 6 unchanged lines hidden (view full) --- 243 assert(!sendQueue.empty()); 244 245 PacketBuffer *buf = sendQueue.front(); 246 247 assert(buf->ready <= curTick); 248 249 PacketPtr pkt = buf->pkt; 250 | 229 230 // If we're about to put this packet at the head of the queue, we 231 // need to schedule an event to do the transmit. Otherwise there 232 // should already be an event scheduled for sending the head 233 // packet. 234 if (sendQueue.empty()) { 235 sendEvent.schedule(readyTime); 236 } --- 6 unchanged lines hidden (view full) --- 243 assert(!sendQueue.empty()); 244 245 PacketBuffer *buf = sendQueue.front(); 246 247 assert(buf->ready <= curTick); 248 249 PacketPtr pkt = buf->pkt; 250 |
251 pkt->flags &= ~SNOOP_COMMIT; //CLear it if it was set 252 | |
253 // Ugly! @todo When multilevel coherence works this will be removed 254 if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite && | 251 // Ugly! @todo When multilevel coherence works this will be removed 252 if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite && |
255 pkt->result != Packet::Nacked) { | 253 !pkt->wasNacked()) { |
256 PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq, 257 Packet::Broadcast); 258 funcPkt->dataStatic(pkt->getPtr<uint8_t>()); 259 sendFunctional(funcPkt); 260 pkt->cmd = MemCmd::WriteReq; 261 delete funcPkt; 262 } 263 264 DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", 265 buf->origSrc, pkt->getDest(), pkt->getAddr()); 266 267 bool wasReq = pkt->isRequest(); | 254 PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq, 255 Packet::Broadcast); 256 funcPkt->dataStatic(pkt->getPtr<uint8_t>()); 257 sendFunctional(funcPkt); 258 pkt->cmd = MemCmd::WriteReq; 259 delete funcPkt; 260 } 261 262 DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", 263 buf->origSrc, pkt->getDest(), pkt->getAddr()); 264 265 bool wasReq = pkt->isRequest(); |
268 bool wasNacked = pkt->result == Packet::Nacked; | 266 bool wasNacked = pkt->wasNacked(); |
269 270 if (sendTiming(pkt)) { 271 // send successful 272 sendQueue.pop_front(); 273 buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it 274 275 if (buf->expectResponse) { 276 // Must wait for response --- 58 unchanged lines hidden (view full) --- 335} 336 337/** Function called by the port when the bus is receiving a Functional 338 * transaction.*/ 339void 340Bridge::BridgePort::recvFunctional(PacketPtr pkt) 341{ 342 std::list<PacketBuffer*>::iterator i; | 267 268 if (sendTiming(pkt)) { 269 // send successful 270 sendQueue.pop_front(); 271 buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it 272 273 if (buf->expectResponse) { 274 // Must wait for response --- 58 unchanged lines hidden (view full) --- 333} 334 335/** Function called by the port when the bus is receiving a Functional 336 * transaction.*/ 337void 338Bridge::BridgePort::recvFunctional(PacketPtr pkt) 339{ 340 std::list<PacketBuffer*>::iterator i; |
343 bool pktContinue = true; | |
344 345 for (i = sendQueue.begin(); i != sendQueue.end(); ++i) { | 341 342 for (i = sendQueue.begin(); i != sendQueue.end(); ++i) { |
346 if (pkt->intersect((*i)->pkt)) { 347 pktContinue &= fixPacket(pkt, (*i)->pkt); 348 } | 343 if (pkt->checkFunctional((*i)->pkt)) 344 return; |
349 } 350 | 345 } 346 |
351 if (pktContinue) { 352 otherPort->sendFunctional(pkt); 353 } | 347 // fall through if pkt still not satisfied 348 otherPort->sendFunctional(pkt); |
354} 355 356/** Function called by the port when the bus is receiving a status change.*/ 357void 358Bridge::BridgePort::recvStatusChange(Port::Status status) 359{ 360 otherPort->sendStatusChange(status); 361} 362 363void 364Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, 365 bool &snoop) 366{ 367 otherPort->getPeerAddressRanges(resp, snoop); 368} 369 | 349} 350 351/** Function called by the port when the bus is receiving a status change.*/ 352void 353Bridge::BridgePort::recvStatusChange(Port::Status status) 354{ 355 otherPort->sendStatusChange(status); 356} 357 358void 359Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, 360 bool &snoop) 361{ 362 otherPort->getPeerAddressRanges(resp, snoop); 363} 364 |
370Bridge * 371BridgeParams::create() | 365BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge) 366 367 Param<int> req_size_a; 368 Param<int> req_size_b; 369 Param<int> resp_size_a; 370 Param<int> resp_size_b; 371 Param<Tick> delay; 372 Param<Tick> nack_delay; 373 Param<bool> write_ack; 374 Param<bool> fix_partial_write_a; 375 Param<bool> fix_partial_write_b; 376 377END_DECLARE_SIM_OBJECT_PARAMS(Bridge) 378 379BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge) 380 381 INIT_PARAM(req_size_a, "The size of the queue for requests coming into side a"), 382 INIT_PARAM(req_size_b, "The size of the queue for requests coming into side b"), 383 INIT_PARAM(resp_size_a, "The size of the queue for responses coming into side a"), 384 INIT_PARAM(resp_size_b, "The size of the queue for responses coming into side b"), 385 INIT_PARAM(delay, "The miminum delay to cross this bridge"), 386 INIT_PARAM(nack_delay, "The minimum delay to nack a packet"), 387 INIT_PARAM(write_ack, "Acknowledge any writes that are received."), 388 INIT_PARAM(fix_partial_write_a, "Fixup any partial block writes that are received"), 389 INIT_PARAM(fix_partial_write_b, "Fixup any partial block writes that are received") 390 391END_INIT_SIM_OBJECT_PARAMS(Bridge) 392 393CREATE_SIM_OBJECT(Bridge) |
372{ | 394{ |
373 return new Bridge(this); | 395 Bridge::Params *p = new Bridge::Params; 396 p->name = getInstanceName(); 397 p->req_size_a = req_size_a; 398 p->req_size_b = req_size_b; 399 p->resp_size_a = resp_size_a; 400 p->resp_size_b = resp_size_b; 401 p->delay = delay; 402 p->nack_delay = nack_delay; 403 p->write_ack = write_ack; 404 p->fix_partial_write_a = fix_partial_write_a; 405 p->fix_partial_write_b = fix_partial_write_b; 406 return new Bridge(p); |
374} | 407} |
408 409REGISTER_SIM_OBJECT("Bridge", Bridge) 410 411 |
|