gem5 v24.0.0.0
Loading...
Searching...
No Matches
packet_queue.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012,2015,2018-2020 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
41#include "mem/packet_queue.hh"
42
43#include "base/trace.hh"
44#include "debug/Drain.hh"
45#include "debug/PacketQueue.hh"
46
47namespace gem5
48{
49
50PacketQueue::PacketQueue(EventManager& _em, const std::string& _label,
51 const std::string& _sendEventName,
52 bool force_order,
53 bool disable_sanity_check)
54 : em(_em), sendEvent([this]{ processSendEvent(); }, _sendEventName),
55 _disableSanityCheck(disable_sanity_check),
56 forceOrder(force_order),
57 label(_label), waitingOnRetry(false)
58{
59}
60
64
65void
67{
68 DPRINTF(PacketQueue, "Queue %s received retry\n", name());
69 assert(waitingOnRetry);
70 waitingOnRetry = false;
72}
73
74bool
75PacketQueue::checkConflict(const PacketPtr pkt, const int blk_size) const
76{
77 // caller is responsible for ensuring that all packets have the
78 // same alignment
79 for (const auto& p : transmitList) {
80 if (p.pkt->matchBlockAddr(pkt, blk_size))
81 return true;
82 }
83 return false;
84}
85
86bool
88{
89 pkt->pushLabel(label);
90
91 auto i = transmitList.begin();
92 bool found = false;
93
94 while (!found && i != transmitList.end()) {
95 // If the buffered packet contains data, and it overlaps the
96 // current packet, then update data
97 found = pkt->trySatisfyFunctional(i->pkt);
98 ++i;
99 }
100
101 pkt->popLabel();
102
103 return found;
104}
105
106void
108{
109 DPRINTF(PacketQueue, "%s for %s address %x size %d when %lu ord: %i\n",
110 __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize(), when,
111 forceOrder);
112
113 // we can still send a packet before the end of this tick
114 assert(when >= curTick());
115
116 // express snoops should never be queued
117 assert(!pkt->isExpressSnoop());
118
119 // add a very basic sanity check on the port to ensure the
120 // invisible buffer is not growing beyond reasonable limits
121 if (!_disableSanityCheck && transmitList.size() > 1024) {
122 panic("Packet queue %s has grown beyond 1024 packets\n",
123 name());
124 }
125
126 // we should either have an outstanding retry, or a send event
127 // scheduled, but there is an unfortunate corner case where the
128 // x86 page-table walker and timing CPU send out a new request as
129 // part of the receiving of a response (called by
130 // PacketQueue::sendDeferredPacket), in which we end up calling
131 // ourselves again before we had a chance to update waitingOnRetry
132 // assert(waitingOnRetry || sendEvent.scheduled());
133
134 // this belongs in the middle somewhere, so search from the end to
135 // order by tick; however, if forceOrder is set, also make sure
136 // not to re-order in front of some existing packet with the same
137 // address
138 auto it = transmitList.end();
139 while (it != transmitList.begin()) {
140 --it;
141 if ((forceOrder && it->pkt->matchAddr(pkt)) || it->tick <= when) {
142 // emplace inserts the element before the position pointed to by
143 // the iterator, so advance it one step
144 transmitList.emplace(++it, when, pkt);
145 return;
146 }
147 }
148 // either the packet list is empty or this has to be inserted
149 // before every other packet
150 transmitList.emplace_front(when, pkt);
151 schedSendEvent(when);
152}
153
154void
156{
157 // if we are waiting on a retry just hold off
158 if (waitingOnRetry) {
159 DPRINTF(PacketQueue, "Not scheduling send as waiting for retry\n");
160 assert(!sendEvent.scheduled());
161 return;
162 }
163
164 if (when != MaxTick) {
165 // we cannot go back in time, and to be consistent we stick to
166 // one tick in the future
167 when = std::max(when, curTick() + 1);
168 // @todo Revisit the +1
169
170 if (!sendEvent.scheduled()) {
171 em.schedule(&sendEvent, when);
172 } else if (when < sendEvent.when()) {
173 // if the new time is earlier than when the event
174 // currently is scheduled, move it forward
175 em.reschedule(&sendEvent, when);
176 }
177 } else {
178 // we get a MaxTick when there is no more to send, so if we're
179 // draining, we may be done at this point
181 transmitList.empty() && !sendEvent.scheduled()) {
182
183 DPRINTF(Drain, "PacketQueue done draining,"
184 "processing drain event\n");
186 }
187 }
188}
189
190void
192{
193 // sanity checks
194 assert(!waitingOnRetry);
195 assert(deferredPacketReady());
196
198
199 // take the packet of the list before sending it, as sending of
200 // the packet in some cases causes a new packet to be enqueued
201 // (most notaly when responding to the timing CPU, leading to a
202 // new request hitting in the L1 icache, leading to a new
203 // response)
204 transmitList.pop_front();
205
206 // use the appropriate implementation of sendTiming based on the
207 // type of queue
209
210 // if we succeeded and are not waiting for a retry, schedule the
211 // next send
212 if (!waitingOnRetry) {
214 } else {
215 // put the packet back at the front of the list
216 transmitList.emplace_front(dp);
217 }
218}
219
220void
226
229{
230 if (transmitList.empty()) {
231 return DrainState::Drained;
232 } else {
233 DPRINTF(Drain, "PacketQueue not drained\n");
235 }
236}
237
239 const std::string _label)
240 : PacketQueue(_em, _label, name(_mem_side_port, _label)),
241 memSidePort(_mem_side_port)
242{
243}
244
245bool
250
252 RequestPort& _mem_side_port,
253 bool force_order,
254 const std::string _label)
255 : PacketQueue(_em, _label, name(_mem_side_port, _label), force_order),
256 memSidePort(_mem_side_port)
257{
258}
259
260bool
265
267 ResponsePort& _cpu_side_port,
268 bool force_order,
269 const std::string _label)
270 : PacketQueue(_em, _label, name(_cpu_side_port, _label), force_order),
271 cpuSidePort(_cpu_side_port)
272{
273}
274
275bool
280
281} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
A deferred packet, buffered to transmit later.
A packet queue is a class that holds deferred packets and later sends them using the associated CPU-s...
bool waitingOnRetry
Remember whether we're awaiting a retry.
bool forceOrder
if true, inserted packets have to be unconditionally scheduled after the last packet in the queue tha...
EventManager & em
The manager which is used for the event queue.
bool trySatisfyFunctional(PacketPtr pkt)
Check the list of buffered packets against the supplied functional request.
void processSendEvent()
Used to schedule sending of deferred packets.
bool deferredPacketReady() const
Check whether we have a packet ready to go on the transmit list.
DeferredPacketList transmitList
A list of outgoing packets.
const std::string label
Label to use for print request packets label stack.
EventFunctionWrapper sendEvent
Event used to call processSendEvent.
void retry()
Retry sending a packet from the queue.
virtual bool sendTiming(PacketPtr pkt)=0
Send a packet using the appropriate method for the specific subclass (request, response or snoop resp...
void schedSendTiming(PacketPtr pkt, Tick when)
Add a packet to the transmit list, and schedule a send event.
virtual const std::string name() const =0
Provide a name to simplify debugging.
PacketQueue(EventManager &_em, const std::string &_label, const std::string &_sendEventName, bool force_order=false, bool disable_sanity_check=false)
Create a packet queue, linked to an event manager, and a label that will be used for functional print...
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
bool checkConflict(const PacketPtr pkt, const int blk_size) const
Check if a packet corresponding to the same address exists in the queue.
virtual void sendDeferredPacket()
Attempt to send a packet.
void schedSendEvent(Tick when)
Schedule a send event if we are not already waiting for a retry.
virtual ~PacketQueue()
Virtual desctructor since the class may be used as a base class.
Tick deferredPacketReadyTime() const
Get the next packet ready time.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
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 trySatisfyFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Definition packet.hh:1399
unsigned getSize() const
Definition packet.hh:817
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition packet.hh:1480
bool isExpressSnoop() const
Definition packet.hh:702
bool sendTiming(PacketPtr pkt)
Send a packet using the appropriate method for the specific subclass (request, response or snoop resp...
ReqPacketQueue(EventManager &_em, RequestPort &_mem_side_port, const std::string _label="ReqPacketQueue")
Create a request packet queue, linked to an event manager, a memory-side port, and a label that will ...
RequestPort & memSidePort
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Definition port.hh:136
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition port.hh:603
bool sendTimingSnoopResp(PacketPtr pkt)
Attempt to send a timing snoop response packet to the response port by calling its corresponding rece...
Definition port.hh:627
bool sendTiming(PacketPtr pkt)
Send a packet using the appropriate method for the specific subclass (request, response or snoop resp...
ResponsePort & cpuSidePort
RespPacketQueue(EventManager &_em, ResponsePort &_cpu_side_port, bool force_order=false, const std::string _label="RespPacketQueue")
Create a response packet queue, linked to an event manager, a CPU-side port, and a label that will be...
A ResponsePort is a specialization of a port.
Definition port.hh:349
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the request port by calling its corresponding receive function.
Definition port.hh:454
SnoopRespPacketQueue(EventManager &_em, RequestPort &_mem_side_port, bool force_order=false, const std::string _label="SnoopRespPacketQueue")
Create a snoop response packet queue, linked to an event manager, a memory-side port,...
bool sendTiming(PacketPtr pkt)
Send a packet using the appropriate method for the specific subclass (request, response or snoop resp...
void signalDrainDone() const
Signal that an object is drained.
Definition drain.hh:305
DrainState drainState() const
Return the current drain state of an object.
Definition drain.hh:324
DrainState
Object drain/handover states.
Definition drain.hh:75
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
bool scheduled() const
Determine if the current event is scheduled.
Definition eventq.hh:458
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
void reschedule(Event &event, Tick when, bool always=false)
Definition eventq.hh:1030
Tick when() const
Get the time that the event is scheduled.
Definition eventq.hh:501
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
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< 7, 4 > dp
Bitfield< 0 > p
Bitfield< 2 > em
Definition misc.hh:617
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
uint64_t Tick
Tick count type.
Definition types.hh:58
const Tick MaxTick
Definition types.hh:60
Declaration of a simple PacketQueue that is associated with a port on which it attempts to send packe...
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:05 for gem5 by doxygen 1.11.0