gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
packet_queue.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012,2015,2018 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() > 100) {
119  panic("Packet queue %s has grown beyond 100 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
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(_masterPort, _label)),
238  masterPort(_masterPort)
239 {
240 }
241 
242 bool
244 {
245  return masterPort.sendTimingReq(pkt);
246 }
247 
249  MasterPort& _masterPort,
250  bool force_order,
251  const std::string _label)
252  : PacketQueue(_em, _label, name(_masterPort, _label), force_order),
253  masterPort(_masterPort)
254 {
255 }
256 
257 bool
259 {
260  return masterPort.sendTimingSnoopResp(pkt);
261 }
262 
264  bool force_order,
265  const std::string _label)
266  : PacketQueue(_em, _label, name(_slavePort, _label), force_order),
267  slavePort(_slavePort)
268 {
269 }
270 
271 bool
273 {
274  return slavePort.sendTimingResp(pkt);
275 }
A MasterPort is a specialisation of a BaseMasterPort, which implements the default protocol for the t...
Definition: port.hh:71
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:163
#define DPRINTF(x,...)
Definition: trace.hh:222
DrainState drain() override
Notify an object that it needs to drain its state.
void retry()
Retry sending a packet from the queue.
Definition: packet_queue.cc:63
PacketPtr pkt
Pointer to the packet to transmit.
Definition: packet_queue.hh:69
Declaration of a simple PacketQueue that is associated with a port on which it attempts to send packe...
bool isExpressSnoop() const
Definition: packet.hh:628
Bitfield< 7 > i
bool forceOrder
if true, inserted packets have to be unconditionally scheduled after the last packet in the queue tha...
bool _disableSanityCheck
Definition: packet_queue.hh:94
void schedSendTiming(PacketPtr pkt, Tick when)
Add a packet to the transmit list, and schedule a send event.
bool waitingOnRetry
Remember whether we&#39;re awaiting a retry.
bool sendTimingSnoopResp(PacketPtr pkt)
Attempt to send a timing snoop response packet to the slave port by calling its corresponding receive...
Definition: port.hh:453
Bitfield< 47, 44 > dp
Bitfield< 2 > em
Definition: misc.hh:602
A deferred packet, buffered to transmit later.
Definition: packet_queue.hh:66
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
Definition: port.hh:441
A SlavePort is a specialisation of a port.
Definition: port.hh:254
EventFunctionWrapper sendEvent
Event used to call processSendEvent.
Definition: packet_queue.hh:87
void schedSendEvent(Tick when)
Schedule a send event if we are not already waiting for a retry.
ReqPacketQueue(EventManager &_em, MasterPort &_masterPort, const std::string _label="ReqPacketQueue")
Create a request packet queue, linked to an event manager, a master port, and a label that will be us...
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1320
DrainState
Object drain/handover states.
Definition: drain.hh:71
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:308
MasterPort & masterPort
unsigned getSize() const
Definition: packet.hh:730
const Tick MaxTick
Definition: types.hh:63
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the master port by calling its corresponding receive function...
Definition: port.hh:353
Draining buffers pending serialization/handover.
Tick curTick()
The current simulated tick.
Definition: core.hh:44
const std::string name() const
Provide a name to simplify debugging.
SlavePort & slavePort
uint64_t Tick
Tick count type.
Definition: types.hh:61
virtual bool sendTiming(PacketPtr pkt)=0
Send a packet using the appropriate method for the specific subclass (reuest, response or snoop respo...
EventManager & em
The manager which is used for the event queue.
Definition: packet_queue.hh:81
bool trySatisfyFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Definition: packet.hh:1258
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1330
RespPacketQueue(EventManager &_em, SlavePort &_slavePort, bool force_order=false, const std::string _label="RespPacketQueue")
Create a response packet queue, linked to an event manager, a slave port, and a label that will be us...
Addr getAddr() const
Definition: packet.hh:720
void schedule(Event &event, Tick when)
Definition: eventq.hh:998
bool sendTiming(PacketPtr pkt)
Send a packet using the appropriate method for the specific subclass (reuest, response or snoop respo...
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1016
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
bool sendTiming(PacketPtr pkt)
Send a packet using the appropriate method for the specific subclass (reuest, response or snoop respo...
SnoopRespPacketQueue(EventManager &_em, MasterPort &_masterPort, bool force_order=false, const std::string _label="SnoopRespPacketQueue")
Create a snoop response packet queue, linked to an event manager, a master port, and a label that wil...
void sendEvent(ThreadContext *tc)
Send an event (SEV) to a specific PE if there isn&#39;t already a pending event.
Definition: utility.cc:165
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:460
A packet queue is a class that holds deferred packets and later sends them using the associated slave...
Definition: packet_queue.hh:62
MasterPort & masterPort
void processSendEvent()
Used to schedule sending of deferred packets.
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
bool deferredPacketReady() const
Check whether we have a packet ready to go on the transmit list.
virtual ~PacketQueue()
Virtual desctructor since the class may be used as a base class.
Definition: packet_queue.cc:58
virtual const std::string name() const =0
Provide a name to simplify debugging.
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:289
Tick deferredPacketReadyTime() const
Get the next packet ready time.
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
DeferredPacketList transmitList
A list of outgoing packets.
Definition: packet_queue.hh:78
bool trySatisfyFunctional(PacketPtr pkt)
Check the list of buffered packets against the supplied functional request.
Definition: packet_queue.cc:84
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:517
bool sendTiming(PacketPtr pkt)
Send a packet using the appropriate method for the specific subclass (reuest, response or snoop respo...
Bitfield< 0 > p
Running normally.
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:500
virtual void sendDeferredPacket()
Attempt to send a packet.
const std::string label
Label to use for print request packets label stack.
const std::string name() const
Provide a name to simplify debugging.

Generated on Mon Jun 8 2020 15:45:12 for gem5 by doxygen 1.8.13