gem5  v22.1.0.0
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 
47 #include "mem/bridge.hh"
48 
49 #include "base/trace.hh"
50 #include "debug/Bridge.hh"
51 #include "params/Bridge.hh"
52 
53 namespace gem5
54 {
55 
57  Bridge& _bridge,
58  BridgeRequestPort& _memSidePort,
59  Cycles _delay, int _resp_limit,
60  std::vector<AddrRange> _ranges)
61  : ResponsePort(_name, &_bridge), bridge(_bridge),
62  memSidePort(_memSidePort), delay(_delay),
63  ranges(_ranges.begin(), _ranges.end()),
64  outstandingResponses(0), retryReq(false), respQueueLimit(_resp_limit),
65  sendEvent([this]{ trySendTiming(); }, _name)
66 {
67 }
68 
70  Bridge& _bridge,
71  BridgeResponsePort& _cpuSidePort,
72  Cycles _delay, int _req_limit)
73  : RequestPort(_name, &_bridge), bridge(_bridge),
74  cpuSidePort(_cpuSidePort),
75  delay(_delay), reqQueueLimit(_req_limit),
76  sendEvent([this]{ trySendTiming(); }, _name)
77 {
78 }
79 
81  : ClockedObject(p),
82  cpuSidePort(p.name + ".cpu_side_port", *this, memSidePort,
83  ticksToCycles(p.delay), p.resp_size, p.ranges),
84  memSidePort(p.name + ".mem_side_port", *this, cpuSidePort,
85  ticksToCycles(p.delay), p.req_size)
86 {
87 }
88 
89 Port &
90 Bridge::getPort(const std::string &if_name, PortID idx)
91 {
92  if (if_name == "mem_side_port")
93  return memSidePort;
94  else if (if_name == "cpu_side_port")
95  return cpuSidePort;
96  else
97  // pass it along to our super class
98  return ClockedObject::getPort(if_name, idx);
99 }
100 
101 void
103 {
104  // make sure both sides are connected and have the same block size
106  fatal("Both ports of a bridge must be connected.\n");
107 
108  // notify the request side of our address ranges
110 }
111 
112 bool
114 {
116 }
117 
118 bool
120 {
121  return transmitList.size() == reqQueueLimit;
122 }
123 
124 bool
126 {
127  // all checks are done when the request is accepted on the response
128  // side, so we are guaranteed to have space for the response
129  DPRINTF(Bridge, "recvTimingResp: %s addr 0x%x\n",
130  pkt->cmdString(), pkt->getAddr());
131 
132  DPRINTF(Bridge, "Request queue size: %d\n", transmitList.size());
133 
134  // technically the packet only reaches us after the header delay,
135  // and typically we also need to deserialise any payload (unless
136  // the two sides of the bridge are synchronous)
137  Tick receive_delay = pkt->headerDelay + pkt->payloadDelay;
138  pkt->headerDelay = pkt->payloadDelay = 0;
139 
140  cpuSidePort.schedTimingResp(pkt, bridge.clockEdge(delay) +
141  receive_delay);
142 
143  return true;
144 }
145 
146 bool
148 {
149  DPRINTF(Bridge, "recvTimingReq: %s addr 0x%x\n",
150  pkt->cmdString(), pkt->getAddr());
151 
152  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
153  "is responding");
154 
155  // we should not get a new request after committing to retry the
156  // current one, but unfortunately the CPU violates this rule, so
157  // simply ignore it for now
158  if (retryReq)
159  return false;
160 
161  DPRINTF(Bridge, "Response queue size: %d outresp: %d\n",
162  transmitList.size(), outstandingResponses);
163 
164  // if the request queue is full then there is no hope
165  if (memSidePort.reqQueueFull()) {
166  DPRINTF(Bridge, "Request queue full\n");
167  retryReq = true;
168  } else {
169  // look at the response queue if we expect to see a response
170  bool expects_response = pkt->needsResponse();
171  if (expects_response) {
172  if (respQueueFull()) {
173  DPRINTF(Bridge, "Response queue full\n");
174  retryReq = true;
175  } else {
176  // ok to send the request with space for the response
177  DPRINTF(Bridge, "Reserving space for response\n");
178  assert(outstandingResponses != respQueueLimit);
179  ++outstandingResponses;
180 
181  // no need to set retryReq to false as this is already the
182  // case
183  }
184  }
185 
186  if (!retryReq) {
187  // technically the packet only reaches us after the header
188  // delay, and typically we also need to deserialise any
189  // payload (unless the two sides of the bridge are
190  // synchronous)
191  Tick receive_delay = pkt->headerDelay + pkt->payloadDelay;
192  pkt->headerDelay = pkt->payloadDelay = 0;
193 
194  memSidePort.schedTimingReq(pkt, bridge.clockEdge(delay) +
195  receive_delay);
196  }
197  }
198 
199  // remember that we are now stalling a packet and that we have to
200  // tell the sending requestor to retry once space becomes available,
201  // we make no distinction whether the stalling is due to the
202  // request queue or response queue being full
203  return !retryReq;
204 }
205 
206 void
208 {
209  if (retryReq) {
210  DPRINTF(Bridge, "Request waiting for retry, now retrying\n");
211  retryReq = false;
212  sendRetryReq();
213  }
214 }
215 
216 void
218 {
219  // If we're about to put this packet at the head of the queue, we
220  // need to schedule an event to do the transmit. Otherwise there
221  // should already be an event scheduled for sending the head
222  // packet.
223  if (transmitList.empty()) {
224  bridge.schedule(sendEvent, when);
225  }
226 
227  assert(transmitList.size() != reqQueueLimit);
228 
229  transmitList.emplace_back(pkt, when);
230 }
231 
232 
233 void
235 {
236  // If we're about to put this packet at the head of the queue, we
237  // need to schedule an event to do the transmit. Otherwise there
238  // should already be an event scheduled for sending the head
239  // packet.
240  if (transmitList.empty()) {
241  bridge.schedule(sendEvent, when);
242  }
243 
244  transmitList.emplace_back(pkt, when);
245 }
246 
247 void
249 {
250  assert(!transmitList.empty());
251 
252  DeferredPacket req = transmitList.front();
253 
254  assert(req.tick <= curTick());
255 
256  PacketPtr pkt = req.pkt;
257 
258  DPRINTF(Bridge, "trySend request addr 0x%x, queue size %d\n",
259  pkt->getAddr(), transmitList.size());
260 
261  if (sendTimingReq(pkt)) {
262  // send successful
263  transmitList.pop_front();
264  DPRINTF(Bridge, "trySend request successful\n");
265 
266  // If there are more packets to send, schedule event to try again.
267  if (!transmitList.empty()) {
268  DeferredPacket next_req = transmitList.front();
269  DPRINTF(Bridge, "Scheduling next send\n");
270  bridge.schedule(sendEvent, std::max(next_req.tick,
271  bridge.clockEdge()));
272  }
273 
274  // if we have stalled a request due to a full request queue,
275  // then send a retry at this point, also note that if the
276  // request we stalled was waiting for the response queue
277  // rather than the request queue we might stall it again
279  }
280 
281  // if the send failed, then we try again once we receive a retry,
282  // and therefore there is no need to take any action
283 }
284 
285 void
287 {
288  assert(!transmitList.empty());
289 
290  DeferredPacket resp = transmitList.front();
291 
292  assert(resp.tick <= curTick());
293 
294  PacketPtr pkt = resp.pkt;
295 
296  DPRINTF(Bridge, "trySend response addr 0x%x, outstanding %d\n",
297  pkt->getAddr(), outstandingResponses);
298 
299  if (sendTimingResp(pkt)) {
300  // send successful
301  transmitList.pop_front();
302  DPRINTF(Bridge, "trySend response successful\n");
303 
304  assert(outstandingResponses != 0);
305  --outstandingResponses;
306 
307  // If there are more packets to send, schedule event to try again.
308  if (!transmitList.empty()) {
309  DeferredPacket next_resp = transmitList.front();
310  DPRINTF(Bridge, "Scheduling next send\n");
311  bridge.schedule(sendEvent, std::max(next_resp.tick,
312  bridge.clockEdge()));
313  }
314 
315  // if there is space in the request queue and we were stalling
316  // a request, it will definitely be possible to accept it now
317  // since there is guaranteed space in the response queue
318  if (!memSidePort.reqQueueFull() && retryReq) {
319  DPRINTF(Bridge, "Request waiting for retry, now retrying\n");
320  retryReq = false;
321  sendRetryReq();
322  }
323  }
324 
325  // if the send failed, then we try again once we receive a retry,
326  // and therefore there is no need to take any action
327 }
328 
329 void
331 {
332  trySendTiming();
333 }
334 
335 void
337 {
338  trySendTiming();
339 }
340 
341 Tick
343 {
344  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
345  "is responding");
346 
347  return delay * bridge.clockPeriod() + memSidePort.sendAtomic(pkt);
348 }
349 
350 void
352 {
353  pkt->pushLabel(name());
354 
355  // check the response queue
356  for (auto i = transmitList.begin(); i != transmitList.end(); ++i) {
357  if (pkt->trySatisfyFunctional((*i).pkt)) {
358  pkt->makeResponse();
359  return;
360  }
361  }
362 
363  // also check the request port's request queue
365  return;
366  }
367 
368  pkt->popLabel();
369 
370  // fall through if pkt still not satisfied
372 }
373 
374 bool
376 {
377  bool found = false;
378  auto i = transmitList.begin();
379 
380  while (i != transmitList.end() && !found) {
381  if (pkt->trySatisfyFunctional((*i).pkt)) {
382  pkt->makeResponse();
383  found = true;
384  }
385  ++i;
386  }
387 
388  return found;
389 }
390 
393 {
394  return ranges;
395 }
396 
397 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
Declaration of a memory-mapped bridge that connects a requestor and a responder through a request and...
Port on the side that forwards requests and receives responses.
Definition: bridge.hh:224
bool recvTimingResp(PacketPtr pkt)
When receiving a timing request from the peer port, pass it to the bridge.
Definition: bridge.cc:125
BridgeRequestPort(const std::string &_name, Bridge &_bridge, BridgeResponsePort &_cpuSidePort, Cycles _delay, int _req_limit)
Constructor for the BridgeRequestPort.
Definition: bridge.cc:69
bool trySatisfyFunctional(PacketPtr pkt)
Check a functional request against the packets in our request queue.
Definition: bridge.cc:375
bool reqQueueFull() const
Is this side blocked from accepting new request packets.
Definition: bridge.cc:119
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:217
void trySendTiming()
Handle send event, scheduled when the packet at the head of the outbound queue is ready to transmit (...
Definition: bridge.cc:248
void recvReqRetry()
When receiving a retry request from the peer port, pass it to the bridge.
Definition: bridge.cc:330
The port on the side that receives requests and sends responses.
Definition: bridge.hh:103
bool respQueueFull() const
Is this side blocked from accepting new response packets.
Definition: bridge.cc:113
Tick recvAtomic(PacketPtr pkt)
When receiving a Atomic requestfrom the peer port, pass it to the bridge.
Definition: bridge.cc:342
unsigned int respQueueLimit
Max queue size for reserved responses.
Definition: bridge.hh:136
void recvRespRetry()
When receiving a retry request from the peer port, pass it to the bridge.
Definition: bridge.cc:336
unsigned int outstandingResponses
Counter to track the outstanding responses.
Definition: bridge.hh:130
BridgeResponsePort(const std::string &_name, Bridge &_bridge, BridgeRequestPort &_memSidePort, Cycles _delay, int _resp_limit, std::vector< AddrRange > _ranges)
Constructor for the BridgeResponsePort.
Definition: bridge.cc:56
bool recvTimingReq(PacketPtr pkt)
When receiving a timing request from the peer port, pass it to the bridge.
Definition: bridge.cc:147
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:234
void recvFunctional(PacketPtr pkt)
When receiving a Functional request from the peer port, pass it to the bridge.
Definition: bridge.cc:351
AddrRangeList getAddrRanges() const
When receiving a address range request the peer port, pass it to the bridge.
Definition: bridge.cc:392
void retryStalledReq()
Retry any stalled request that we have failed to accept at an earlier point in time.
Definition: bridge.cc:207
void trySendTiming()
Handle send event, scheduled when the packet at the head of the response queue is ready to transmit (...
Definition: bridge.cc:286
A deferred packet stores a packet along with its scheduled transmission time.
Definition: bridge.hh:82
const PacketPtr pkt
Definition: bridge.hh:87
A bridge is used to interface two different crossbars (or in general a memory-mapped requestor and re...
Definition: bridge.hh:74
BridgeRequestPort memSidePort
Request port of the bridge.
Definition: bridge.hh:317
Bridge(const Params &p)
Definition: bridge.cc:80
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: bridge.cc:90
BridgeParams Params
Definition: bridge.hh:326
BridgeResponsePort cpuSidePort
Response port of the bridge.
Definition: bridge.hh:314
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: bridge.cc:102
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Cycles ticksToCycles(Tick t) const
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:79
const std::string _name
Definition: named.hh:41
virtual std::string name() const
Definition: named.hh:47
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
Addr getAddr() const
Definition: packet.hh:805
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1448
bool needsResponse() const
Definition: packet.hh:607
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:448
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:1059
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:430
bool trySatisfyFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Definition: packet.hh:1386
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:587
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1458
bool cacheResponding() const
Definition: packet.hh:657
Ports are used to interface objects to each other.
Definition: port.hh:62
bool isConnected() const
Is this port currently connected to a peer?
Definition: port.hh:133
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Definition: port.hh:79
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
Definition: port.hh:464
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.hh:485
A ResponsePort is a specialization of a port.
Definition: port.hh:270
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:296
STL vector class.
Definition: stl.hh:37
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:190
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:204
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Definition: sim_object.cc:126
Bitfield< 7 > i
Definition: misc_types.hh:67
void sendEvent(ThreadContext *tc)
Send an event (SEV) to a specific PE if there isn't already a pending event.
Definition: utility.cc:65
Bitfield< 54 > p
Definition: pagetable.hh:70
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:245
uint64_t Tick
Tick count type.
Definition: types.hh:58

Generated on Wed Dec 21 2022 10:22:36 for gem5 by doxygen 1.9.1