gem5  v22.1.0.0
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 
47 namespace gem5
48 {
49 
50 PacketQueue::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 
62 {
63 }
64 
65 void
67 {
68  DPRINTF(PacketQueue, "Queue %s received retry\n", name());
69  assert(waitingOnRetry);
70  waitingOnRetry = false;
72 }
73 
74 bool
75 PacketQueue::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 
86 bool
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 
106 void
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() > 128) {
122  panic("Packet queue %s has grown beyond 128 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 
154 void
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
180  if (drainState() == DrainState::Draining &&
181  transmitList.empty() && !sendEvent.scheduled()) {
182 
183  DPRINTF(Drain, "PacketQueue done draining,"
184  "processing drain event\n");
185  signalDrainDone();
186  }
187  }
188 }
189 
190 void
192 {
193  // sanity checks
194  assert(!waitingOnRetry);
195  assert(deferredPacketReady());
196 
197  DeferredPacket dp = transmitList.front();
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
208  waitingOnRetry = !sendTiming(dp.pkt);
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 
220 void
222 {
223  assert(!waitingOnRetry);
225 }
226 
229 {
230  if (transmitList.empty()) {
231  return DrainState::Drained;
232  } else {
233  DPRINTF(Drain, "PacketQueue not drained\n");
234  return DrainState::Draining;
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 
245 bool
247 {
248  return memSidePort.sendTimingReq(pkt);
249 }
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 
260 bool
262 {
263  return memSidePort.sendTimingSnoopResp(pkt);
264 }
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 
275 bool
277 {
278  return cpuSidePort.sendTimingResp(pkt);
279 }
280 
281 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
A deferred packet, buffered to transmit later.
Definition: packet_queue.hh:70
A packet queue is a class that holds deferred packets and later sends them using the associated CPU-s...
Definition: packet_queue.hh:66
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.
Definition: packet_queue.hh:85
bool trySatisfyFunctional(PacketPtr pkt)
Check the list of buffered packets against the supplied functional request.
Definition: packet_queue.cc:87
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.
Definition: packet_queue.hh:82
const std::string label
Label to use for print request packets label stack.
EventFunctionWrapper sendEvent
Event used to call processSendEvent.
Definition: packet_queue.hh:91
void retry()
Retry sending a packet from the queue.
Definition: packet_queue.cc:66
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...
Definition: packet_queue.cc:50
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.
Definition: packet_queue.cc:75
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.
Definition: packet_queue.cc:61
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: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 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
unsigned getSize() const
Definition: packet.hh:815
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1458
bool isExpressSnoop() const
Definition: packet.hh:700
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:79
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:495
bool sendTimingSnoopResp(PacketPtr pkt)
Attempt to send a timing snoop response packet to the response port by calling its corresponding rece...
Definition: port.hh:515
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:270
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the request port by calling its corresponding receive function.
Definition: port.hh:370
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:465
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1037
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:508
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
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< 47, 44 > dp
Definition: misc_types.hh:95
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 2 > em
Definition: misc.hh:607
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
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:49

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