bridge.cc (4432:5e55857abb01) | bridge.cc (4433:4722c6787f69) |
---|---|
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 --- 33 unchanged lines hidden (view full) --- 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) 48 : Port(_name), bridge(_bridge), otherPort(_otherPort), 49 delay(_delay), fixPartialWrite(fix_partial_write), | 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 --- 33 unchanged lines hidden (view full) --- 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) 48 : Port(_name), bridge(_bridge), otherPort(_otherPort), 49 delay(_delay), fixPartialWrite(fix_partial_write), |
50 outstandingResponses(0), queueLimit(_queueLimit), sendEvent(this) | 50 outstandingResponses(0), queuedRequests(0), 51 queueLimit(_queueLimit), sendEvent(this) |
51{ 52} 53 54Bridge::Bridge(const std::string &n, int qsa, int qsb, 55 Tick _delay, int write_ack, bool fix_partial_write_a, 56 bool fix_partial_write_b) 57 : MemObject(n), 58 portA(n + "-portA", this, &portB, _delay, qsa, fix_partial_write_a), --- 28 unchanged lines hidden (view full) --- 87 // Make sure that both sides are connected to. 88 if (portA.getPeer() == NULL || portB.getPeer() == NULL) 89 fatal("Both ports of bus bridge are not connected to a bus.\n"); 90 91 if (portA.peerBlockSize() != portB.peerBlockSize()) 92 fatal("Busses don't have the same block size... Not supported.\n"); 93} 94 | 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), --- 28 unchanged lines hidden (view full) --- 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::queueFull() 98{ 99 // use >= here because sendQueue could get larger because of 100 // nacks getting inserted 101 return queuedRequests + outstandingResponses >= queueLimit; 102} |
|
95 96/** Function called by the port when the bus is receiving a Timing 97 * transaction.*/ 98bool 99Bridge::BridgePort::recvTiming(PacketPtr pkt) 100{ | 103 104/** Function called by the port when the bus is receiving a Timing 105 * transaction.*/ 106bool 107Bridge::BridgePort::recvTiming(PacketPtr pkt) 108{ |
101 if (pkt->flags & SNOOP_COMMIT) { 102 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", | 109 if (!(pkt->flags & SNOOP_COMMIT)) 110 return true; 111 112 113 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", |
103 pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 104 | 114 pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 115 |
105 return otherPort->queueForSendTiming(pkt); | 116 if (pkt->isRequest() && otherPort->queueFull()) { 117 DPRINTF(BusBridge, "Remote queue full, nacking\n"); 118 nackRequest(pkt); 119 return true; |
106 } | 120 } |
107 else { 108 // Else it's just a snoop, properly return if we are blocking 109 return !queueFull(); | 121 122 if (pkt->needsResponse() && pkt->result != Packet::Nacked) 123 if (queueFull()) { 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; 132 } 133 134 otherPort->queueForSendTiming(pkt); 135 136 return true; 137} 138 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 147 Tick readyTime = curTick + delay; 148 PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true); 149 if (sendQueue.empty()) { 150 sendEvent.schedule(readyTime); |
110 } | 151 } |
152 sendQueue.push_back(buf); |
|
111} 112 113 | 153} 154 155 |
114bool | 156void |
115Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) 116{ | 157Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) 158{ |
117 if (queueFull()) { 118 DPRINTF(BusBridge, "Queue full, returning false\n"); 119 return false; 120 } 121 122 if (pkt->isResponse()) { | 159 if (pkt->isResponse() || pkt->result == Packet::Nacked) { |
123 // This is a response for a request we forwarded earlier. The 124 // corresponding PacketBuffer should be stored in the packet's 125 // senderState field. 126 PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState); 127 assert(buf != NULL); 128 // set up new packet dest & senderState based on values saved 129 // from original request 130 buf->fixResponse(pkt); | 160 // This is a response for a request we forwarded earlier. The 161 // corresponding PacketBuffer should be stored in the packet's 162 // senderState field. 163 PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState); 164 assert(buf != NULL); 165 // set up new packet dest & senderState based on values saved 166 // from original request 167 buf->fixResponse(pkt); |
168 169 // Check if this packet was expecting a response (this is either it or 170 // its a nacked packet and we won't be seeing that response) 171 if (buf->expectResponse) 172 --outstandingResponses; 173 174 |
|
131 DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n", 132 pkt->senderState, buf); 133 DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest()); 134 delete buf; 135 } 136 137 Tick readyTime = curTick + delay; 138 PacketBuffer *buf = new PacketBuffer(pkt, readyTime); 139 DPRINTF(BusBridge, "old sender state: %#X, new sender state: %#X\n", 140 buf->origSenderState, buf); 141 142 // If we're about to put this packet at the head of the queue, we 143 // need to schedule an event to do the transmit. Otherwise there 144 // should already be an event scheduled for sending the head 145 // packet. 146 if (sendQueue.empty()) { 147 sendEvent.schedule(readyTime); 148 } | 175 DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n", 176 pkt->senderState, buf); 177 DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest()); 178 delete buf; 179 } 180 181 Tick readyTime = curTick + delay; 182 PacketBuffer *buf = new PacketBuffer(pkt, readyTime); 183 DPRINTF(BusBridge, "old sender state: %#X, new sender state: %#X\n", 184 buf->origSenderState, buf); 185 186 // If we're about to put this packet at the head of the queue, we 187 // need to schedule an event to do the transmit. Otherwise there 188 // should already be an event scheduled for sending the head 189 // packet. 190 if (sendQueue.empty()) { 191 sendEvent.schedule(readyTime); 192 } |
149 | 193 ++queuedRequests; |
150 sendQueue.push_back(buf); | 194 sendQueue.push_back(buf); |
151 152 return true; | |
153} 154 155void 156Bridge::BridgePort::trySend() 157{ 158 assert(!sendQueue.empty()); 159 160 bool was_full = queueFull(); 161 int pbs = peerBlockSize(); 162 163 PacketBuffer *buf = sendQueue.front(); 164 165 assert(buf->ready <= curTick); 166 167 PacketPtr pkt = buf->pkt; 168 169 pkt->flags &= ~SNOOP_COMMIT; //CLear it if it was set 170 171 if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite && | 195} 196 197void 198Bridge::BridgePort::trySend() 199{ 200 assert(!sendQueue.empty()); 201 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 211 pkt->flags &= ~SNOOP_COMMIT; //CLear it if it was set 212 213 if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite && |
172 pkt->getOffset(pbs) && pkt->getSize() != pbs) { | 214 pkt->result != Packet::Nacked && pkt->getOffset(pbs) && 215 pkt->getSize() != pbs) { |
173 buf->partialWriteFix(this); 174 pkt = buf->pkt; 175 } 176 177 DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", 178 buf->origSrc, pkt->getDest(), pkt->getAddr()); 179 180 181 if (sendTiming(pkt)) { 182 // send successful 183 sendQueue.pop_front(); 184 buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it 185 186 if (buf->expectResponse) { | 216 buf->partialWriteFix(this); 217 pkt = buf->pkt; 218 } 219 220 DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", 221 buf->origSrc, pkt->getDest(), pkt->getAddr()); 222 223 224 if (sendTiming(pkt)) { 225 // send successful 226 sendQueue.pop_front(); 227 buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it 228 229 if (buf->expectResponse) { |
187 // Must wait for response. We just need to count outstanding 188 // responses (in case we want to cap them); PacketBuffer 189 // pointer will be recovered on response. 190 ++outstandingResponses; | 230 // Must wait for response |
191 DPRINTF(BusBridge, " successful: awaiting response (%d)\n", 192 outstandingResponses); 193 } else { 194 // no response expected... deallocate packet buffer now. 195 DPRINTF(BusBridge, " successful: no response expected\n"); 196 delete buf; 197 } 198 | 231 DPRINTF(BusBridge, " successful: awaiting response (%d)\n", 232 outstandingResponses); 233 } else { 234 // no response expected... deallocate packet buffer now. 235 DPRINTF(BusBridge, " successful: no response expected\n"); 236 delete buf; 237 } 238 |
239 if (!buf->nacked) 240 --queuedRequests; 241 |
|
199 // If there are more packets to send, schedule event to try again. 200 if (!sendQueue.empty()) { 201 buf = sendQueue.front(); | 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"); |
|
202 sendEvent.schedule(std::max(buf->ready, curTick + 1)); 203 } 204 // Let things start sending again | 246 sendEvent.schedule(std::max(buf->ready, curTick + 1)); 247 } 248 // Let things start sending again |
205 if (was_full) { | 249 if (was_full && !queueFull()) { |
206 DPRINTF(BusBridge, "Queue was full, sending retry\n"); 207 otherPort->sendRetry(); 208 } 209 210 } else { 211 DPRINTF(BusBridge, " unsuccessful\n"); 212 buf->undoPartialWriteFix(); 213 } | 250 DPRINTF(BusBridge, "Queue was full, sending retry\n"); 251 otherPort->sendRetry(); 252 } 253 254 } else { 255 DPRINTF(BusBridge, " unsuccessful\n"); 256 buf->undoPartialWriteFix(); 257 } |
258 DPRINTF(BusBridge, "trySend: queue size: %d outreq: %d outstanding resp: %d\n", 259 sendQueue.size(), queuedRequests, outstandingResponses); |
|
214} 215 216 217void 218Bridge::BridgePort::recvRetry() 219{ 220 trySend(); 221} --- 63 unchanged lines hidden (view full) --- 285 286CREATE_SIM_OBJECT(Bridge) 287{ 288 return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay, 289 write_ack, fix_partial_write_a, fix_partial_write_b); 290} 291 292REGISTER_SIM_OBJECT("Bridge", Bridge) | 260} 261 262 263void 264Bridge::BridgePort::recvRetry() 265{ 266 trySend(); 267} --- 63 unchanged lines hidden (view full) --- 331 332CREATE_SIM_OBJECT(Bridge) 333{ 334 return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay, 335 write_ack, fix_partial_write_a, fix_partial_write_b); 336} 337 338REGISTER_SIM_OBJECT("Bridge", Bridge) |
339 |
|