gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
eventq.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2000-2005 The Regents of The University of Michigan
3  * Copyright (c) 2008 The Hewlett-Packard Development Company
4  * Copyright (c) 2013 Advanced Micro Devices, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met: redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer;
11  * redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution;
14  * neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "sim/eventq.hh"
32 
33 #include <cassert>
34 #include <iostream>
35 #include <mutex>
36 #include <string>
37 #include <unordered_map>
38 #include <vector>
39 
40 #include "base/logging.hh"
41 #include "base/trace.hh"
42 #include "cpu/smt.hh"
43 #include "debug/Checkpoint.hh"
44 
45 namespace gem5
46 {
47 
49 
50 //
51 // Main Event Queues
52 //
53 // Events on these queues are processed at the *beginning* of each
54 // cycle, before the pipeline simulation is performed.
55 //
56 uint32_t numMainEventQueues = 0;
58 __thread EventQueue *_curEventQueue = NULL;
59 bool inParallelMode = false;
60 
61 EventQueue *
63 {
64  while (numMainEventQueues <= index) {
66  mainEventQueue.push_back(
67  new EventQueue(csprintf("MainEventQueue-%d", index)));
68  }
69 
70  return mainEventQueue[index];
71 }
72 
73 #ifndef NDEBUG
75 #endif
76 
78 {
79  assert(!scheduled());
80  flags = 0;
81 }
82 
83 const std::string
84 Event::name() const
85 {
86  return csprintf("Event_%s", instanceString());
87 }
88 
89 
90 Event *
92 {
93  // Either way, event will be the top element in the 'in bin' list
94  // which is the pointer we need in order to look into the list, so
95  // we need to insert that into the bin list.
96  if (!curr || *event < *curr) {
97  // Insert the event before the current list since it is in the future.
98  event->nextBin = curr;
99  event->nextInBin = NULL;
100  } else {
101  // Since we're on the correct list, we need to point to the next list
102  event->nextBin = curr->nextBin; // curr->nextBin can now become stale
103 
104  // Insert event at the top of the stack
105  event->nextInBin = curr;
106  }
107 
108  return event;
109 }
110 
111 void
113 {
115  acquireImpl();
116 }
117 
118 void
120 {
122  releaseImpl();
123 }
124 
125 void
127 {
128 }
129 
130 void
132 {
133  if (!scheduled())
134  delete this;
135 }
136 
137 void
139 {
140  // Deal with the head case
141  if (!head || *event <= *head) {
143  return;
144  }
145 
146  // Figure out either which 'in bin' list we are on, or where a new list
147  // needs to be inserted
148  Event *prev = head;
149  Event *curr = head->nextBin;
150  while (curr && *curr < *event) {
151  prev = curr;
152  curr = curr->nextBin;
153  }
154 
155  // Note: this operation may render all nextBin pointers on the
156  // prev 'in bin' list stale (except for the top one)
157  prev->nextBin = Event::insertBefore(event, curr);
158 }
159 
160 Event *
162 {
163  Event *curr = top;
164  Event *next = top->nextInBin;
165 
166  // if we removed the top item, we need to handle things specially
167  // and just remove the top item, fixing up the next bin pointer of
168  // the new top item
169  if (event == top) {
170  if (!next)
171  return top->nextBin;
172  next->nextBin = top->nextBin;
173  return next;
174  }
175 
176  // Since we already checked the current element, we're going to
177  // keep checking event against the next element.
178  while (event != next) {
179  if (!next)
180  panic("event not found!");
181 
182  curr = next;
183  next = next->nextInBin;
184  }
185 
186  // remove next from the 'in bin' list since it's what we're looking for
187  curr->nextInBin = next->nextInBin;
188  return top;
189 }
190 
191 void
193 {
194  if (head == NULL)
195  panic("event not found!");
196 
197  assert(event->queue == this);
198 
199  // deal with an event on the head's 'in bin' list (event has the same
200  // time as the head)
201  if (*head == *event) {
203  return;
204  }
205 
206  // Find the 'in bin' list that this event belongs on
207  Event *prev = head;
208  Event *curr = head->nextBin;
209  while (curr && *curr < *event) {
210  prev = curr;
211  curr = curr->nextBin;
212  }
213 
214  if (!curr || *curr != *event)
215  panic("event not found!");
216 
217  // curr points to the top item of the the correct 'in bin' list, when
218  // we remove an item, it returns the new top item (which may be
219  // unchanged)
220  prev->nextBin = Event::removeItem(event, curr);
221 }
222 
223 Event *
225 {
226  std::lock_guard<EventQueue> lock(*this);
227  Event *event = head;
228  Event *next = head->nextInBin;
229  event->flags.clear(Event::Scheduled);
230 
231  if (next) {
232  // update the next bin pointer since it could be stale
233  next->nextBin = head->nextBin;
234 
235  // pop the stack
236  head = next;
237  } else {
238  // this was the only element on the 'in bin' list, so get rid of
239  // the 'in bin' list and point to the next bin list
240  head = head->nextBin;
241  }
242 
243  // handle action
244  if (!event->squashed()) {
245  // forward current cycle to the time when this event occurs.
246  setCurTick(event->when());
247  if (debug::Event)
248  event->trace("executed");
249  event->process();
250  if (event->isExitEvent()) {
251  assert(!event->flags.isSet(Event::Managed) ||
252  !event->flags.isSet(Event::IsMainQueue)); // would be silly
253  return event;
254  }
255  } else {
256  event->flags.clear(Event::Squashed);
257  }
258 
259  event->release();
260 
261  return NULL;
262 }
263 
264 void
266 {
269  short _flags = flags;
270  SERIALIZE_SCALAR(_flags);
271 }
272 
273 void
275 {
276  assert(!scheduled());
277 
280 
281  FlagsType _flags;
282  UNSERIALIZE_SCALAR(_flags);
283 
284  // Old checkpoints had no concept of the Initialized flag
285  // so restoring from old checkpoints always fail.
286  // Events are initialized on construction but original code
287  // "flags = _flags" would just overwrite the initialization.
288  // So, read in the checkpoint flags, but then set the Initialized
289  // flag on top of it in order to avoid failures.
290  assert(initialized());
291  flags = _flags;
293 
294  // need to see if original event was in a scheduled, unsquashed
295  // state, but don't want to restore those flags in the current
296  // object itself (since they aren't immediately true)
297  if (flags.isSet(Scheduled) && !flags.isSet(Squashed)) {
299  } else {
300  DPRINTF(Checkpoint, "Event '%s' need to be scheduled @%d\n",
301  name(), _when);
302  }
303 }
304 
305 void
307 {
308  // It's safe to call insert() directly here since this method
309  // should only be called when restoring from a checkpoint (which
310  // happens before thread creation).
311  if (event->flags.isSet(Event::Scheduled))
312  insert(event);
313 }
314 void
316 {
317  cprintf("============================================================\n");
318  cprintf("EventQueue Dump (cycle %d)\n", curTick());
319  cprintf("------------------------------------------------------------\n");
320 
321  if (empty())
322  cprintf("<No Events>\n");
323  else {
324  Event *nextBin = head;
325  while (nextBin) {
326  Event *nextInBin = nextBin;
327  while (nextInBin) {
328  nextInBin->dump();
329  nextInBin = nextInBin->nextInBin;
330  }
331 
332  nextBin = nextBin->nextBin;
333  }
334  }
335 
336  cprintf("============================================================\n");
337 }
338 
339 bool
341 {
342  std::unordered_map<long, bool> map;
343 
344  Tick time = 0;
345  short priority = 0;
346 
347  Event *nextBin = head;
348  while (nextBin) {
349  Event *nextInBin = nextBin;
350  while (nextInBin) {
351  if (nextInBin->when() < time) {
352  cprintf("time goes backwards!");
353  nextInBin->dump();
354  return false;
355  } else if (nextInBin->when() == time &&
356  nextInBin->priority() < priority) {
357  cprintf("priority inverted!");
358  nextInBin->dump();
359  return false;
360  }
361 
362  if (map[reinterpret_cast<long>(nextInBin)]) {
363  cprintf("Node already seen");
364  nextInBin->dump();
365  return false;
366  }
367  map[reinterpret_cast<long>(nextInBin)] = true;
368 
369  time = nextInBin->when();
370  priority = nextInBin->priority();
371 
372  nextInBin = nextInBin->nextInBin;
373  }
374 
375  nextBin = nextBin->nextBin;
376  }
377 
378  return true;
379 }
380 
381 Event*
383 {
384  Event* t = head;
385  head = s;
386  return t;
387 }
388 
389 void
391 {
392  for (uint32_t i = 0; i < numMainEventQueues; ++i) {
393  mainEventQueue[i]->dump();
394  }
395 }
396 
397 
398 const char *
400 {
401  return "generic";
402 }
403 
404 void
405 Event::trace(const char *action)
406 {
407  // This is just a default implementation for derived classes where
408  // it's not worth doing anything special. If you want to put a
409  // more informative message in the trace, override this method on
410  // the particular subclass where you have the information that
411  // needs to be printed.
412  DPRINTF(Event, "%s %s %s @ %d\n",
413  description(), instanceString(), action, when());
414 }
415 
416 const std::string
418 {
419 #ifndef NDEBUG
420  return csprintf("%d", instance);
421 #else
422  return csprintf("%#x", (uintptr_t)this);
423 #endif
424 }
425 
426 void
427 Event::dump() const
428 {
429  cprintf("Event %s (%s)\n", name(), description());
430  cprintf("Flags: %#x\n", flags);
431 #ifdef EVENTQ_DEBUG
432  cprintf("Created: %d\n", whenCreated);
433 #endif
434  if (scheduled()) {
435 #ifdef EVENTQ_DEBUG
436  cprintf("Scheduled at %d\n", whenScheduled);
437 #endif
438  cprintf("Scheduled for %d, priority %d\n", when(), _priority);
439  } else {
440  cprintf("Not Scheduled\n");
441  }
442 }
443 
444 EventQueue::EventQueue(const std::string &n)
445  : objName(n), head(NULL), _curTick(0)
446 {
447 }
448 
449 void
451 {
453  async_queue.push_back(event);
455 }
456 
457 void
459 {
460  assert(this == curEventQueue());
462 
463  while (!async_queue.empty()) {
464  insert(async_queue.front());
465  async_queue.pop_front();
466  }
467 
469 }
470 
471 } // namespace gem5
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::VegaISA::s
Bitfield< 1 > s
Definition: pagetable.hh:64
gem5::Event::description
virtual const char * description() const
Return a C string describing the event.
Definition: eventq.cc:399
gem5::Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:501
gem5::Counter
int64_t Counter
Statistics counter type.
Definition: types.hh:53
gem5::Event::name
virtual const std::string name() const
Definition: eventq.cc:84
gem5::cprintf
void cprintf(const char *format, const Args &...args)
Definition: cprintf.hh:155
gem5::UncontendedMutex::lock
void lock()
Definition: uncontended_mutex.hh:70
gem5::EventQueue::replaceHead
Event * replaceHead(Event *s)
function for replacing the head of the event queue, so that a different set of events can run without...
Definition: eventq.cc:382
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
gem5::Event::nextInBin
Event * nextInBin
Definition: eventq.hh:269
gem5::MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:47
gem5::mainEventQueue
std::vector< EventQueue * > mainEventQueue
Array for main event queues.
Definition: eventq.cc:57
gem5::Flags::set
void set(Type mask)
Set all flag's bits matching the given mask.
Definition: flags.hh:116
gem5::CheckpointIn
Definition: serialize.hh:68
gem5::Flags::clear
void clear()
Clear all flag's bits.
Definition: flags.hh:102
gem5::Event::removeItem
static Event * removeItem(Event *event, Event *last)
Definition: eventq.cc:161
gem5::MipsISA::event
Bitfield< 10, 5 > event
Definition: pra_constants.hh:300
gem5::EventBase::Scheduled
static const FlagsType Scheduled
Definition: eventq.hh:108
gem5::getEventQueue
EventQueue * getEventQueue(uint32_t index)
Function for returning eventq queue for the provided index.
Definition: eventq.cc:62
gem5::inParallelMode
bool inParallelMode
Current mode of execution: parallel / serial.
Definition: eventq.cc:59
gem5::EventQueue::lock
void lock()
Provide an interface for locking/unlocking the event queue.
Definition: eventq.hh:947
top
Definition: test.h:61
std::vector
STL vector class.
Definition: stl.hh:37
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
gem5::Event::release
void release()
Managed event removed from the event queue.
Definition: eventq.cc:119
gem5::EventQueue::head
Event * head
Definition: eventq.hh:621
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::Event::releaseImpl
virtual void releaseImpl()
Definition: eventq.cc:131
gem5::EventQueue::async_queue
std::list< Event * > async_queue
List of events added by other threads to this event queue.
Definition: eventq.hh:628
gem5::Event::priority
Priority priority() const
Get the event priority.
Definition: eventq.hh:508
gem5::ArmISA::priority
Bitfield< 3, 0 > priority
Definition: misc_types.hh:833
gem5::EventBase::Squashed
static const FlagsType Squashed
Definition: eventq.hh:107
gem5::Event::initialized
bool initialized() const
Definition: eventq.hh:311
gem5::EventQueue::handleAsyncInsertions
void handleAsyncInsertions()
Function for moving events from the async_queue to the main queue.
Definition: eventq.cc:458
gem5::EventQueue::insert
void insert(Event *event)
Insert / remove event from the queue.
Definition: eventq.cc:138
smt.hh
gem5::VegaISA::t
Bitfield< 51 > t
Definition: pagetable.hh:56
gem5::Flags::isSet
bool isSet(Type mask) const
Verifies whether any bit matching the given mask is set.
Definition: flags.hh:83
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
gem5::Event
Definition: eventq.hh:254
gem5::Event::instanceCounter
static Counter instanceCounter
Global counter to generate unique IDs for Event instances.
Definition: eventq.hh:280
gem5::EventBase::IsMainQueue
static const FlagsType IsMainQueue
Definition: eventq.hh:118
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::EventQueue::setCurTick
void setCurTick(Tick newVal)
Definition: eventq.hh:837
gem5::EventQueue::async_queue_mutex
UncontendedMutex async_queue_mutex
Mutex to protect async queue.
Definition: eventq.hh:625
gem5::EventQueue::EventQueue
EventQueue(const EventQueue &)
gem5::EventQueue
Queue of events sorted in time order.
Definition: eventq.hh:615
gem5::EventBase::Initialized
static const FlagsType Initialized
Definition: eventq.hh:119
gem5::simQuantum
Tick simQuantum
Simulation Quantum for multiple eventq simulation.
Definition: eventq.cc:48
gem5::EventQueue::empty
bool empty() const
Returns true if no events are queued.
Definition: eventq.hh:891
gem5::_curEventQueue
__thread EventQueue * _curEventQueue
The current event queue for the running thread.
Definition: eventq.cc:58
gem5::Event::acquire
void acquire()
Memory management hooks for events that have the Managed flag set.
Definition: eventq.cc:112
gem5::Event::nextBin
Event * nextBin
Definition: eventq.hh:268
gem5::EventBase::Managed
static const FlagsType Managed
Definition: eventq.hh:109
gem5::EventQueue::curEventQueue
friend void curEventQueue(EventQueue *)
Definition: eventq.hh:972
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
gem5::EventBase::FlagsType
unsigned short FlagsType
Definition: eventq.hh:102
gem5::Event::_priority
Priority _priority
event priority
Definition: eventq.hh:275
gem5::Event::_when
Tick _when
timestamp when event should be processed
Definition: eventq.hh:274
gem5::Event::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: eventq.cc:265
gem5::ArmISA::n
Bitfield< 31 > n
Definition: misc_types.hh:513
gem5::Event::flags
Flags flags
Definition: eventq.hh:276
gem5::EventQueue::checkpointReschedule
void checkpointReschedule(Event *event)
Reschedule an event after a checkpoint.
Definition: eventq.cc:306
gem5::Event::acquireImpl
virtual void acquireImpl()
Definition: eventq.cc:126
gem5::numMainEventQueues
uint32_t numMainEventQueues
Current number of allocated main event queues.
Definition: eventq.cc:56
gem5::Event::insertBefore
static Event * insertBefore(Event *event, Event *curr)
Definition: eventq.cc:91
gem5::Event::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: eventq.cc:274
gem5::EventQueue::asyncInsert
void asyncInsert(Event *event)
Function for adding events to the async queue.
Definition: eventq.cc:450
gem5::EventQueue::debugVerify
bool debugVerify() const
Definition: eventq.cc:340
logging.hh
gem5::Event::~Event
virtual ~Event()
Definition: eventq.cc:77
gem5::EventQueue::remove
void remove(Event *event)
Definition: eventq.cc:192
gem5::Event::instanceString
const std::string instanceString() const
Return the instance number as a string.
Definition: eventq.cc:417
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
trace.hh
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::Event::instance
Counter instance
This event's unique ID.
Definition: eventq.hh:286
gem5::EventQueue::serviceOne
Event * serviceOne()
Definition: eventq.cc:224
gem5::Event::trace
virtual void trace(const char *action)
This function isn't really useful if TRACING_ON is not defined.
Definition: eventq.cc:405
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:458
gem5::Event::dump
void dump() const
Dump the current event data.
Definition: eventq.cc:427
gem5::EventQueue::dump
void dump() const
This is a debugging function which will print everything on the event queue.
Definition: eventq.cc:315
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:188
gem5::UncontendedMutex::unlock
void unlock()
Definition: uncontended_mutex.hh:95
gem5::dumpMainQueue
void dumpMainQueue()
Definition: eventq.cc:390
eventq.hh

Generated on Sun Jul 30 2023 01:56:59 for gem5 by doxygen 1.8.17