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

Generated on Wed Sep 30 2020 14:02:13 for gem5 by doxygen 1.8.17