gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
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
46
47#include "mem/bridge.hh"
48
49#include "base/trace.hh"
50#include "debug/Bridge.hh"
51#include "params/Bridge.hh"
52
53namespace gem5
54{
55
57 const std::string& _name, BridgeBase& _bridge,
58 BridgeRequestPort& _memSidePort, Cycles _delay, int _resp_limit)
59 : ResponsePort(_name), bridge(_bridge),
60 memSidePort(_memSidePort), delay(_delay),
61 outstandingResponses(0), retryReq(false), respQueueLimit(_resp_limit),
62 sendEvent([this]{ trySendTiming(); }, _name)
63{
64}
65
67 const std::string& _name, BridgeBase& _bridge,
68 BridgeResponsePort& _cpuSidePort, Cycles _delay, int _req_limit)
69 : RequestPort(_name), bridge(_bridge),
70 cpuSidePort(_cpuSidePort),
71 delay(_delay), reqQueueLimit(_req_limit),
72 sendEvent([this]{ trySendTiming(); }, _name)
73{
74}
75
78 cpuSidePort(p.name + ".cpu_side_port", *this, memSidePort,
79 ticksToCycles(p.delay), p.resp_size),
80 memSidePort(p.name + ".mem_side_port", *this, cpuSidePort,
81 ticksToCycles(p.delay), p.req_size)
82{
83}
84
86 : BridgeBase(p), ranges(p.ranges.begin(), p.ranges.end())
87{
88}
89
90Port &
91BridgeBase::getPort(const std::string& if_name, PortID idx)
92{
93 if (if_name == "mem_side_port")
94 return memSidePort;
95 else if (if_name == "cpu_side_port")
96 return cpuSidePort;
97 else
98 // pass it along to our super class
99 return ClockedObject::getPort(if_name, idx);
100}
101
102void
104{
105 // make sure both sides are connected and have the same block size
106 if (!cpuSidePort.isConnected() || !memSidePort.isConnected())
107 fatal("Both ports of a bridge must be connected.\n");
108
109 // notify the request side of our address ranges
110 cpuSidePort.sendRangeChange();
111}
112
113bool
118
119bool
124
125bool
127{
128 // all checks are done when the request is accepted on the response
129 // side, so we are guaranteed to have space for the response
130 DPRINTF(Bridge, "recvTimingResp: %s addr 0x%x\n",
131 pkt->cmdString(), pkt->getAddr());
132
133 DPRINTF(Bridge, "Request queue size: %d\n", transmitList.size());
134
135 // technically the packet only reaches us after the header delay,
136 // and typically we also need to deserialise any payload (unless
137 // the two sides of the bridge are synchronous)
138 Tick receive_delay = pkt->headerDelay + pkt->payloadDelay;
139 pkt->headerDelay = pkt->payloadDelay = 0;
140
141 cpuSidePort.schedTimingResp(pkt, bridge.clockEdge(delay) +
142 receive_delay);
143
144 return true;
145}
146
147bool
149{
150 DPRINTF(Bridge, "recvTimingReq: %s addr 0x%x\n",
151 pkt->cmdString(), pkt->getAddr());
152
153 panic_if(pkt->cacheResponding(), "Should not see packets where cache "
154 "is responding");
155
156 // we should not get a new request after committing to retry the
157 // current one, but unfortunately the CPU violates this rule, so
158 // simply ignore it for now
159 if (retryReq)
160 return false;
161
162 DPRINTF(Bridge, "Response queue size: %d outresp: %d\n",
164
165 // if the request queue is full then there is no hope
166 if (memSidePort.reqQueueFull()) {
167 DPRINTF(Bridge, "Request queue full\n");
168 retryReq = true;
169 } else {
170 // look at the response queue if we expect to see a response
171 bool expects_response = pkt->needsResponse();
172 if (expects_response) {
173 if (respQueueFull()) {
174 DPRINTF(Bridge, "Response queue full\n");
175 retryReq = true;
176 } else {
177 // ok to send the request with space for the response
178 DPRINTF(Bridge, "Reserving space for response\n");
181
182 // no need to set retryReq to false as this is already the
183 // case
184 }
185 }
186
187 if (!retryReq) {
188 // technically the packet only reaches us after the header
189 // delay, and typically we also need to deserialise any
190 // payload (unless the two sides of the bridge are
191 // synchronous)
192 Tick receive_delay = pkt->headerDelay + pkt->payloadDelay;
193 pkt->headerDelay = pkt->payloadDelay = 0;
194
195 memSidePort.schedTimingReq(pkt, bridge.clockEdge(delay) +
196 receive_delay);
197 }
198 }
199
200 // remember that we are now stalling a packet and that we have to
201 // tell the sending requestor to retry once space becomes available,
202 // we make no distinction whether the stalling is due to the
203 // request queue or response queue being full
204 return !retryReq;
205}
206
207void
209{
210 if (retryReq) {
211 DPRINTF(Bridge, "Request waiting for retry, now retrying\n");
212 retryReq = false;
213 sendRetryReq();
214 }
215}
216
217void
219{
220 // If we're about to put this packet at the head of the queue, we
221 // need to schedule an event to do the transmit. Otherwise there
222 // should already be an event scheduled for sending the head
223 // packet.
224 if (transmitList.empty()) {
225 bridge.schedule(sendEvent, when);
226 }
227
228 assert(transmitList.size() != reqQueueLimit);
229
230 transmitList.emplace_back(pkt, when);
231}
232
233void
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
247void
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
278 cpuSidePort.retryStalledReq();
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
285void
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",
298
299 if (sendTimingResp(pkt)) {
300 // send successful
301 transmitList.pop_front();
302 DPRINTF(Bridge, "trySend response successful\n");
303
304 assert(outstandingResponses != 0);
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
329void
334
335void
340
341Tick
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
350Tick
352 MemBackdoorPtr& backdoor)
353{
354 return delay * bridge.clockPeriod() +
355 memSidePort.sendAtomicBackdoor(pkt, backdoor);
356}
357
358void
360{
361 pkt->pushLabel(name());
362
363 // check the response queue
364 for (auto i = transmitList.begin(); i != transmitList.end(); ++i) {
365 if (pkt->trySatisfyFunctional((*i).pkt)) {
366 pkt->makeResponse();
367 return;
368 }
369 }
370
371 // also check the request port's request queue
372 if (memSidePort.trySatisfyFunctional(pkt)) {
373 return;
374 }
375
376 pkt->popLabel();
377
378 // fall through if pkt still not satisfied
379 memSidePort.sendFunctional(pkt);
380}
381
382void
384 const MemBackdoorReq& req, MemBackdoorPtr& backdoor)
385{
386 memSidePort.sendMemBackdoorReq(req, backdoor);
387}
388
389bool
391{
392 bool found = false;
393 auto i = transmitList.begin();
394
395 while (i != transmitList.end() && !found) {
396 if (pkt->trySatisfyFunctional((*i).pkt)) {
397 pkt->makeResponse();
398 found = true;
399 }
400 ++i;
401 }
402
403 return found;
404}
405
406void
411
414{
415 return bridge.getAddrRanges();
416}
417
420{
421 return ranges;
422}
423
424} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
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:236
BridgeRequestPort(const std::string &_name, BridgeBase &_bridge, BridgeResponsePort &_cpuSidePort, Cycles _delay, int _req_limit)
Constructor for the BridgeRequestPort.
Definition bridge.cc:66
void recvRangeChange() override
When receiving an address range change from the peer port, pass it to the bridge.
Definition bridge.cc:407
void recvReqRetry() override
When receiving a retry request from the peer port, pass it to the bridge.
Definition bridge.cc:330
bool trySatisfyFunctional(PacketPtr pkt)
Check a functional request against the packets in our request queue.
Definition bridge.cc:390
const unsigned int reqQueueLimit
Max queue size for request packets.
Definition bridge.hh:260
EventFunctionWrapper sendEvent
Send event for the request queue.
Definition bridge.hh:270
bool reqQueueFull() const
Is this side blocked from accepting new request packets.
Definition bridge.cc:120
bool recvTimingResp(PacketPtr pkt) override
When receiving a timing request from the peer port, pass it to the bridge.
Definition bridge.cc:126
BridgeResponsePort & cpuSidePort
The response port on the other side of the bridge.
Definition bridge.hh:246
void trySendTiming()
Handle send event, scheduled when the packet at the head of the outbound queue is ready to transmit (...
Definition bridge.cc:248
std::deque< DeferredPacket > transmitList
Request packet queue.
Definition bridge.hh:257
BridgeBase & bridge
The bridge to which this port belongs.
Definition bridge.hh:241
const Cycles delay
Minimum delay though this bridge.
Definition bridge.hh:249
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:218
The port on the side that receives requests and sends responses.
Definition bridge.hh:107
void trySendTiming()
Handle send event, scheduled when the packet at the head of the response queue is ready to transmit (...
Definition bridge.cc:286
void recvFunctional(PacketPtr pkt) override
When receiving a Functional request from the peer port, pass it to the bridge.
Definition bridge.cc:359
void recvRespRetry() override
When receiving a retry request from the peer port, pass it to the bridge.
Definition bridge.cc:336
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) override
When receiving an Atomic backdoor request from the peer port, pass it to the bridge.
Definition bridge.cc:351
BridgeResponsePort(const std::string &_name, BridgeBase &_bridge, BridgeRequestPort &_memSidePort, Cycles _delay, int _resp_limit)
Constructor for the BridgeResponsePort.
Definition bridge.cc:56
void retryStalledReq()
Retry any stalled request that we have failed to accept at an earlier point in time.
Definition bridge.cc:208
BridgeBase & bridge
The bridge to which this port belongs.
Definition bridge.hh:112
void recvMemBackdoorReq(const MemBackdoorReq &req, MemBackdoorPtr &backdoor) override
When receiving a Functional backdoor request from the peer port, pass it to the bridge.
Definition bridge.cc:383
bool recvTimingReq(PacketPtr pkt) override
When receiving a timing request from the peer port, pass it to the bridge.
Definition bridge.cc:148
Tick recvAtomic(PacketPtr pkt) override
When receiving an Atomic request from the peer port, pass it to the bridge.
Definition bridge.cc:342
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
bool respQueueFull() const
Is this side blocked from accepting new response packets.
Definition bridge.cc:114
bool retryReq
If we should send a retry when space becomes available.
Definition bridge.hh:134
unsigned int outstandingResponses
Counter to track the outstanding responses.
Definition bridge.hh:131
const Cycles delay
Minimum request delay though this bridge.
Definition bridge.hh:120
AddrRangeList getAddrRanges() const override
When receiving a address range request the peer port, pass it to the bridge.
Definition bridge.cc:413
EventFunctionWrapper sendEvent
Send event for the response queue.
Definition bridge.hh:160
std::deque< DeferredPacket > transmitList
Response packet queue.
Definition bridge.hh:128
BridgeRequestPort & memSidePort
Request port on the other side of the bridge.
Definition bridge.hh:117
unsigned int respQueueLimit
Max queue size for reserved responses.
Definition bridge.hh:137
A deferred packet stores a packet along with its scheduled transmission time.
Definition bridge.hh:86
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition bridge.cc:91
BridgeResponsePort cpuSidePort
Response port of the bridge.
Definition bridge.hh:330
BridgeBase(const Params &p)
Definition bridge.cc:76
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition bridge.cc:103
BridgeRequestPort memSidePort
Request port of the bridge.
Definition bridge.hh:333
Implementation for a simple bridge with static and configurable set of address ranges.
Definition bridge.hh:369
AddrRangeList getAddrRanges() const override
Get a list of the non-overlapping address ranges the bridge is responsible for.
Definition bridge.cc:419
Bridge(const Params &p)
Definition bridge.cc:85
const AddrRangeList ranges
Address ranges to pass through the bridge.
Definition bridge.hh:371
ClockedObject(const ClockedObjectParams &p)
ClockedObjectParams Params
Parameters of ClockedObject.
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:54
virtual std::string name() const
Definition named.hh:60
Addr getAddr() const
Definition packet.hh:807
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition packet.hh:1470
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition packet.hh:588
bool needsResponse() const
Definition packet.hh:608
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition packet.hh:449
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:1062
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition packet.hh:431
bool trySatisfyFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Definition packet.hh:1399
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition packet.hh:1480
bool cacheResponding() const
Definition packet.hh:659
Ports are used to interface objects to each other.
Definition port.hh:62
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition port.hh:603
RequestPort(const std::string &name, SimObject *_owner, PortID id=InvalidPortID)
Request port.
Definition port.cc:125
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the request port by calling its corresponding receive function.
Definition port.hh:454
ResponsePort(const std::string &name, SimObject *_owner, PortID id=InvalidPortID)
Response port.
Definition port.cc:218
void sendRetryReq()
Send a retry to the request port that previously attempted a sendTimingReq to this response port and ...
Definition port.hh:489
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
Definition addr_range.hh:64
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:246
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 0 > p
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
MemBackdoor * MemBackdoorPtr
Definition backdoor.hh:127
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
Packet * PacketPtr

Generated on Mon Oct 27 2025 04:13:03 for gem5 by doxygen 1.14.0