gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
bridge.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2013, 2015 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2006 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *
40  * Authors: Ali Saidi
41  * Steve Reinhardt
42  * Andreas Hansson
43  */
44 
51 #include "mem/bridge.hh"
52 
53 #include "base/trace.hh"
54 #include "debug/Bridge.hh"
55 #include "params/Bridge.hh"
56 
58  Bridge& _bridge,
59  BridgeMasterPort& _masterPort,
60  Cycles _delay, int _resp_limit,
61  std::vector<AddrRange> _ranges)
62  : SlavePort(_name, &_bridge), bridge(_bridge), masterPort(_masterPort),
63  delay(_delay), ranges(_ranges.begin(), _ranges.end()),
64  outstandingResponses(0), retryReq(false),
65  respQueueLimit(_resp_limit), sendEvent(*this)
66 {
67 }
68 
70  Bridge& _bridge,
71  BridgeSlavePort& _slavePort,
72  Cycles _delay, int _req_limit)
73  : MasterPort(_name, &_bridge), bridge(_bridge), slavePort(_slavePort),
74  delay(_delay), reqQueueLimit(_req_limit), sendEvent(*this)
75 {
76 }
77 
79  : MemObject(p),
80  slavePort(p->name + ".slave", *this, masterPort,
81  ticksToCycles(p->delay), p->resp_size, p->ranges),
82  masterPort(p->name + ".master", *this, slavePort,
83  ticksToCycles(p->delay), p->req_size)
84 {
85 }
86 
88 Bridge::getMasterPort(const std::string &if_name, PortID idx)
89 {
90  if (if_name == "master")
91  return masterPort;
92  else
93  // pass it along to our super class
94  return MemObject::getMasterPort(if_name, idx);
95 }
96 
98 Bridge::getSlavePort(const std::string &if_name, PortID idx)
99 {
100  if (if_name == "slave")
101  return slavePort;
102  else
103  // pass it along to our super class
104  return MemObject::getSlavePort(if_name, idx);
105 }
106 
107 void
109 {
110  // make sure both sides are connected and have the same block size
112  fatal("Both ports of a bridge must be connected.\n");
113 
114  // notify the master side of our address ranges
116 }
117 
118 bool
120 {
122 }
123 
124 bool
126 {
127  return transmitList.size() == reqQueueLimit;
128 }
129 
130 bool
132 {
133  // all checks are done when the request is accepted on the slave
134  // side, so we are guaranteed to have space for the response
135  DPRINTF(Bridge, "recvTimingResp: %s addr 0x%x\n",
136  pkt->cmdString(), pkt->getAddr());
137 
138  DPRINTF(Bridge, "Request queue size: %d\n", transmitList.size());
139 
140  // technically the packet only reaches us after the header delay,
141  // and typically we also need to deserialise any payload (unless
142  // the two sides of the bridge are synchronous)
143  Tick receive_delay = pkt->headerDelay + pkt->payloadDelay;
144  pkt->headerDelay = pkt->payloadDelay = 0;
145 
146  slavePort.schedTimingResp(pkt, bridge.clockEdge(delay) +
147  receive_delay);
148 
149  return true;
150 }
151 
152 bool
154 {
155  DPRINTF(Bridge, "recvTimingReq: %s addr 0x%x\n",
156  pkt->cmdString(), pkt->getAddr());
157 
158  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
159  "is responding");
160 
161  // we should not get a new request after committing to retry the
162  // current one, but unfortunately the CPU violates this rule, so
163  // simply ignore it for now
164  if (retryReq)
165  return false;
166 
167  DPRINTF(Bridge, "Response queue size: %d outresp: %d\n",
168  transmitList.size(), outstandingResponses);
169 
170  // if the request queue is full then there is no hope
171  if (masterPort.reqQueueFull()) {
172  DPRINTF(Bridge, "Request queue full\n");
173  retryReq = true;
174  } else {
175  // look at the response queue if we expect to see a response
176  bool expects_response = pkt->needsResponse();
177  if (expects_response) {
178  if (respQueueFull()) {
179  DPRINTF(Bridge, "Response queue full\n");
180  retryReq = true;
181  } else {
182  // ok to send the request with space for the response
183  DPRINTF(Bridge, "Reserving space for response\n");
184  assert(outstandingResponses != respQueueLimit);
185  ++outstandingResponses;
186 
187  // no need to set retryReq to false as this is already the
188  // case
189  }
190  }
191 
192  if (!retryReq) {
193  // technically the packet only reaches us after the header
194  // delay, and typically we also need to deserialise any
195  // payload (unless the two sides of the bridge are
196  // synchronous)
197  Tick receive_delay = pkt->headerDelay + pkt->payloadDelay;
198  pkt->headerDelay = pkt->payloadDelay = 0;
199 
200  masterPort.schedTimingReq(pkt, bridge.clockEdge(delay) +
201  receive_delay);
202  }
203  }
204 
205  // remember that we are now stalling a packet and that we have to
206  // tell the sending master to retry once space becomes available,
207  // we make no distinction whether the stalling is due to the
208  // request queue or response queue being full
209  return !retryReq;
210 }
211 
212 void
214 {
215  if (retryReq) {
216  DPRINTF(Bridge, "Request waiting for retry, now retrying\n");
217  retryReq = false;
218  sendRetryReq();
219  }
220 }
221 
222 void
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 (transmitList.empty()) {
230  bridge.schedule(sendEvent, when);
231  }
232 
233  assert(transmitList.size() != reqQueueLimit);
234 
235  transmitList.emplace_back(pkt, when);
236 }
237 
238 
239 void
241 {
242  // If we're about to put this packet at the head of the queue, we
243  // need to schedule an event to do the transmit. Otherwise there
244  // should already be an event scheduled for sending the head
245  // packet.
246  if (transmitList.empty()) {
247  bridge.schedule(sendEvent, when);
248  }
249 
250  transmitList.emplace_back(pkt, when);
251 }
252 
253 void
255 {
256  assert(!transmitList.empty());
257 
258  DeferredPacket req = transmitList.front();
259 
260  assert(req.tick <= curTick());
261 
262  PacketPtr pkt = req.pkt;
263 
264  DPRINTF(Bridge, "trySend request addr 0x%x, queue size %d\n",
265  pkt->getAddr(), transmitList.size());
266 
267  if (sendTimingReq(pkt)) {
268  // send successful
269  transmitList.pop_front();
270  DPRINTF(Bridge, "trySend request successful\n");
271 
272  // If there are more packets to send, schedule event to try again.
273  if (!transmitList.empty()) {
274  DeferredPacket next_req = transmitList.front();
275  DPRINTF(Bridge, "Scheduling next send\n");
276  bridge.schedule(sendEvent, std::max(next_req.tick,
277  bridge.clockEdge()));
278  }
279 
280  // if we have stalled a request due to a full request queue,
281  // then send a retry at this point, also note that if the
282  // request we stalled was waiting for the response queue
283  // rather than the request queue we might stall it again
285  }
286 
287  // if the send failed, then we try again once we receive a retry,
288  // and therefore there is no need to take any action
289 }
290 
291 void
293 {
294  assert(!transmitList.empty());
295 
296  DeferredPacket resp = transmitList.front();
297 
298  assert(resp.tick <= curTick());
299 
300  PacketPtr pkt = resp.pkt;
301 
302  DPRINTF(Bridge, "trySend response addr 0x%x, outstanding %d\n",
303  pkt->getAddr(), outstandingResponses);
304 
305  if (sendTimingResp(pkt)) {
306  // send successful
307  transmitList.pop_front();
308  DPRINTF(Bridge, "trySend response successful\n");
309 
310  assert(outstandingResponses != 0);
311  --outstandingResponses;
312 
313  // If there are more packets to send, schedule event to try again.
314  if (!transmitList.empty()) {
315  DeferredPacket next_resp = transmitList.front();
316  DPRINTF(Bridge, "Scheduling next send\n");
317  bridge.schedule(sendEvent, std::max(next_resp.tick,
318  bridge.clockEdge()));
319  }
320 
321  // if there is space in the request queue and we were stalling
322  // a request, it will definitely be possible to accept it now
323  // since there is guaranteed space in the response queue
324  if (!masterPort.reqQueueFull() && retryReq) {
325  DPRINTF(Bridge, "Request waiting for retry, now retrying\n");
326  retryReq = false;
327  sendRetryReq();
328  }
329  }
330 
331  // if the send failed, then we try again once we receive a retry,
332  // and therefore there is no need to take any action
333 }
334 
335 void
337 {
338  trySendTiming();
339 }
340 
341 void
343 {
344  trySendTiming();
345 }
346 
347 Tick
349 {
350  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
351  "is responding");
352 
353  return delay * bridge.clockPeriod() + masterPort.sendAtomic(pkt);
354 }
355 
356 void
358 {
359  pkt->pushLabel(name());
360 
361  // check the response queue
362  for (auto i = transmitList.begin(); i != transmitList.end(); ++i) {
363  if (pkt->checkFunctional((*i).pkt)) {
364  pkt->makeResponse();
365  return;
366  }
367  }
368 
369  // also check the master port's request queue
370  if (masterPort.checkFunctional(pkt)) {
371  return;
372  }
373 
374  pkt->popLabel();
375 
376  // fall through if pkt still not satisfied
378 }
379 
380 bool
382 {
383  bool found = false;
384  auto i = transmitList.begin();
385 
386  while (i != transmitList.end() && !found) {
387  if (pkt->checkFunctional((*i).pkt)) {
388  pkt->makeResponse();
389  found = true;
390  }
391  ++i;
392  }
393 
394  return found;
395 }
396 
399 {
400  return ranges;
401 }
402 
403 Bridge *
404 BridgeParams::create()
405 {
406  return new Bridge(this);
407 }
A MasterPort is a specialisation of a BaseMasterPort, which implements the default protocol for the t...
Definition: port.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:212
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
BridgeSlavePort(const std::string &_name, Bridge &_bridge, BridgeMasterPort &_masterPort, Cycles _delay, int _resp_limit, std::vector< AddrRange > _ranges)
Constructor for the BridgeSlavePort.
Definition: bridge.cc:57
Declaration of a memory-mapped bridge that connects a master and a slave through a request and respon...
Bitfield< 7 > i
Definition: miscregs.hh:1378
unsigned int outstandingResponses
Counter to track the outstanding responses.
Definition: bridge.hh:130
Cycles ticksToCycles(Tick t) const
Tick recvAtomic(PacketPtr pkt)
When receiving a Atomic requestfrom the peer port, pass it to the bridge.
Definition: bridge.cc:348
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: bridge.cc:108
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
Definition: bridge.cc:88
panic_if(!root,"Invalid expression\n")
void recvRespRetry()
When receiving a retry request from the peer port, pass it to the bridge.
Definition: bridge.cc:342
A SlavePort is a specialisation of a port.
Definition: port.hh:331
BridgeParams Params
Definition: bridge.hh:328
virtual BaseSlavePort & getSlavePort(const std::string &if_name, PortID idx=InvalidPortID)
Get a slave port with a given name and index.
Definition: mem_object.cc:58
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1160
A BaseSlavePort is a protocol-agnostic slave port, responsible only for the structural connection to ...
Definition: port.hh:139
bool recvTimingResp(PacketPtr pkt)
When receiving a timing request from the peer port, pass it to the bridge.
Definition: bridge.cc:131
void recvReqRetry()
When receiving a retry request from the peer port, pass it to the bridge.
Definition: bridge.cc:336
Tick curTick()
The current simulated tick.
Definition: core.hh:47
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:340
uint64_t Tick
Tick count type.
Definition: types.hh:63
BridgeMasterPort masterPort
Master port of the bridge.
Definition: bridge.hh:317
BridgeSlavePort slavePort
Slave port of the bridge.
Definition: bridge.hh:314
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1170
bool respQueueFull() const
Is this side blocked from accepting new response packets.
Definition: bridge.cc:119
void retryStalledReq()
Retry any stalled request that we have failed to accept at an earlier point in time.
Definition: bridge.cc:213
#define fatal(...)
Definition: misc.hh:163
bool recvTimingReq(PacketPtr pkt)
When receiving a timing request from the peer port, pass it to the bridge.
Definition: bridge.cc:153
BridgeMasterPort(const std::string &_name, Bridge &_bridge, BridgeSlavePort &_slavePort, Cycles _delay, int _req_limit)
Constructor for the BridgeMasterPort.
Definition: bridge.cc:69
bool needsResponse() const
Definition: packet.hh:516
bool reqQueueFull() const
Is this side blocked from accepting new request packets.
Definition: bridge.cc:125
A deferred packet stores a packet along with its scheduled transmission time.
Definition: bridge.hh:81
bool cacheResponding() const
Definition: packet.hh:558
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:358
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
The port on the side that receives requests and sends responses.
Definition: bridge.hh:102
const Tick tick
Definition: bridge.hh:86
Bridge(Params *p)
Definition: bridge.cc:78
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:410
bool checkFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Definition: packet.hh:1115
bool isConnected() const
Definition: port.cc:84
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition: packet.hh:845
bool checkFunctional(PacketPtr pkt)
Check a functional request against the packets in our request queue.
Definition: bridge.cc:381
virtual const std::string name() const
Definition: sim_object.hh:117
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:497
The MemObject class extends the ClockedObject with accessor functions to get its master and slave por...
Definition: mem_object.hh:60
A BaseMasterPort is a protocol-agnostic master port, responsible only for the structural connection t...
Definition: port.hh:115
void schedTimingReq(PacketPtr pkt, Tick when)
Queue a request packet to be sent out later and also schedule a send if necessary.
Definition: bridge.cc:223
void trySendTiming()
Handle send event, scheduled when the packet at the head of the response queue is ready to transmit (...
Definition: bridge.cc:292
bool isConnected() const
Definition: port.cc:110
AddrRangeList getAddrRanges() const
When receiving a address range request the peer port, pass it to the bridge.
Definition: bridge.cc:398
unsigned int respQueueLimit
Max queue size for reserved responses.
Definition: bridge.hh:136
A bridge is used to interface two different crossbars (or in general a memory-mapped master and slave...
Definition: bridge.hh:73
void trySendTiming()
Handle send event, scheduled when the packet at the head of the outbound queue is ready to transmit (...
Definition: bridge.cc:254
Port on the side that forwards requests and receives responses.
Definition: bridge.hh:223
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:181
void schedTimingResp(PacketPtr pkt, Tick when)
Queue a response packet to be sent out later and also schedule a send if necessary.
Definition: bridge.cc:240
virtual BaseSlavePort & getSlavePort(const std::string &if_name, PortID idx=InvalidPortID)
Get a slave port with a given name and index.
Definition: bridge.cc:98
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time...
Definition: port.cc:166
Bitfield< 0 > p
void recvFunctional(PacketPtr pkt)
When receiving a Functional request from the peer port, pass it to the bridge.
Definition: bridge.cc:357
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
Definition: mem_object.cc:52
void sendFunctional(PacketPtr pkt)
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.cc:173
Addr getAddr() const
Definition: packet.hh:639

Generated on Fri Jun 9 2017 13:03:48 for gem5 by doxygen 1.8.6