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