1/*
2 * Copyright (c) 2000-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 30 unchanged lines hidden (view full) ---

39#include <algorithm>
40#include <cassert>
41#include <climits>
42#include <map>
43#include <string>
44#include <vector>
45
46#include "base/fast_alloc.hh"
47#include "base/flags.hh"
48#include "base/misc.hh"
49#include "base/trace.hh"
50#include "sim/serialize.hh"
51#include "sim/host.hh"
52
53class EventQueue; // forward declaration
54
55extern EventQueue mainEventQueue;

--- 4 unchanged lines hidden (view full) ---

60 * process() member function.
61 *
62 * Caution, the order of members is chosen to maximize data packing.
63 */
64class Event : public Serializable, public FastAlloc
65{
66 friend class EventQueue;
67
68 protected:
69 typedef short FlagsType;
70 typedef ::Flags<FlagsType> Flags;
71
72 static const FlagsType PublicRead = 0x003f;
73 static const FlagsType PublicWrite = 0x001d;
74 static const FlagsType Squashed = 0x0001;
75 static const FlagsType Scheduled = 0x0002;
76 static const FlagsType AutoDelete = 0x0004;
77 static const FlagsType AutoSerialize = 0x0008;
78 static const FlagsType IsExitEvent = 0x0010;
79 static const FlagsType IsMainQueue = 0x0020;
80
81 private:
82 // The event queue is now a linked list of linked lists. The
83 // 'nextBin' pointer is to find the bin, where a bin is defined as
84 // when+priority. All events in the same bin will be stored in a
85 // second linked list (a stack) maintained by the 'nextInBin'
86 // pointer. The list will be accessed in LIFO order. The end
87 // result is that the insert/removal in 'nextBin' is
88 // linear/constant, and the lookup/removal in 'nextInBin' is
89 // constant/constant. Hopefully this is a significant improvement
90 // over the current fully linear insertion.
91 Event *nextBin;
92 Event *nextInBin;
93
94 static Event *insertBefore(Event *event, Event *curr);
95 static Event *removeItem(Event *event, Event *last);
96
97 Tick _when; //!< timestamp when event should be processed
98 short _priority; //!< event priority
85 short _flags;
99 Flags flags;
100
101#ifndef NDEBUG
102 /// Global counter to generate unique IDs for Event instances
103 static Counter instanceCounter;
104
105 /// This event's unique ID. We can also use pointer values for
106 /// this but they're not consistent across runs making debugging
107 /// more difficult. Thus we use a global counter value when

--- 18 unchanged lines hidden (view full) ---

126 queue = q;
127#endif
128#ifdef EVENTQ_DEBUG
129 whenScheduled = curTick;
130#endif
131 }
132
133 protected:
120 enum Flags {
121 None = 0x0,
122 Squashed = 0x1,
123 Scheduled = 0x2,
124 AutoDelete = 0x4,
125 AutoSerialize = 0x8,
126 IsExitEvent = 0x10,
127 IsMainQueue = 0x20
128 };
134 /// Accessor for flags.
135 Flags
136 getFlags() const
137 {
138 return flags & PublicRead;
139 }
140
130 bool getFlags(Flags f) const { return (_flags & f) == f; }
131 void setFlags(Flags f) { _flags |= f; }
132 void clearFlags(Flags f) { _flags &= ~f; }
141 Flags
142 getFlags(Flags _flags) const
143 {
144 assert(flags.noneSet(~PublicRead));
145 return flags.isSet(_flags);
146 }
147
134 protected:
148 Flags
149 allFlags(Flags _flags) const
150 {
151 assert(_flags.noneSet(~PublicRead));
152 return flags.allSet(_flags);
153 }
154
155 /// Accessor for flags.
156 void
157 setFlags(Flags _flags)
158 {
159 assert(_flags.noneSet(~PublicWrite));
160 flags.set(_flags);
161 }
162
163 void
164 clearFlags(Flags _flags)
165 {
166 assert(_flags.noneSet(~PublicWrite));
167 flags.clear(_flags);
168 }
169
170 void
171 clearFlags()
172 {
173 flags.clear(PublicWrite);
174 }
175
176 // This function isn't really useful if TRACING_ON is not defined
177 virtual void trace(const char *action); //!< trace event activity
178
179 public:
180 /// Event priorities, to provide tie-breakers for events scheduled
181 /// at the same cycle. Most events are scheduled at the default
182 /// priority; these values are used to control events that need to
183 /// be ordered within a cycle.

--- 49 unchanged lines hidden (view full) ---

233 Maximum_Pri = SHRT_MAX
234 };
235
236 /*
237 * Event constructor
238 * @param queue that the event gets scheduled on
239 */
240 Event(Priority p = Default_Pri)
200 : nextBin(NULL), nextInBin(NULL), _priority(p), _flags(None)
241 : nextBin(NULL), nextInBin(NULL), _priority(p)
242 {
243#ifndef NDEBUG
244 instance = ++instanceCounter;
245 queue = NULL;
246#endif
247#ifdef EVENTQ_DEBUG
248 whenCreated = curTick;
249 whenScheduled = 0;

--- 20 unchanged lines hidden (view full) ---

270 * statically allocated event objects).
271 *
272 * If the AutoDestroy flag is set, the object is deleted once it
273 * is processed.
274 */
275 virtual void process() = 0;
276
277 /// Determine if the current event is scheduled
237 bool scheduled() const { return getFlags(Scheduled); }
278 bool scheduled() const { return flags.isSet(Scheduled); }
279
280 /// Squash the current event
240 void squash() { setFlags(Squashed); }
281 void squash() { flags.set(Squashed); }
282
283 /// Check whether the event is squashed
243 bool squashed() const { return getFlags(Squashed); }
284 bool squashed() const { return flags.isSet(Squashed); }
285
286 /// See if this is a SimExitEvent (without resorting to RTTI)
246 bool isExitEvent() const { return getFlags(IsExitEvent); }
287 bool isExitEvent() const { return flags.isSet(IsExitEvent); }
288
289 /// Get the time that the event is scheduled
290 Tick when() const { return _when; }
291
292 /// Get the event priority
293 int priority() const { return _priority; }
294
295#ifndef SWIG

--- 138 unchanged lines hidden (view full) ---

434 class DelayEvent : public Event
435 {
436 private:
437 T *object;
438
439 public:
440 DelayEvent(T *o)
441 : object(o)
401 { setFlags(this->AutoDestroy); }
442 { this->setFlags(AutoDelete); }
443 void process() { (object->*F)(); }
444 const char *description() const { return "delay"; }
445 };
446
447 eventq->schedule(new DelayEvent(object), when);
448}
449
450template <class T, void (T::* F)()>

--- 16 unchanged lines hidden (view full) ---

467inline void
468EventQueue::schedule(Event *event, Tick when)
469{
470 assert(when >= curTick);
471 assert(!event->scheduled());
472
473 event->setWhen(when, this);
474 insert(event);
434 event->setFlags(Event::Scheduled);
475 event->flags.set(Event::Scheduled);
476 if (this == &mainEventQueue)
436 event->setFlags(Event::IsMainQueue);
477 event->flags.set(Event::IsMainQueue);
478 else
438 event->clearFlags(Event::IsMainQueue);
479 event->flags.clear(Event::IsMainQueue);
480
481 if (DTRACE(Event))
482 event->trace("scheduled");
483}
484
485inline void
486EventQueue::deschedule(Event *event)
487{
488 assert(event->scheduled());
489
490 remove(event);
491
451 event->clearFlags(Event::Squashed);
452 event->clearFlags(Event::Scheduled);
492 event->flags.clear(Event::Squashed);
493 event->flags.clear(Event::Scheduled);
494
454 if (event->getFlags(Event::AutoDelete))
495 if (event->flags.isSet(Event::AutoDelete))
496 delete event;
497
498 if (DTRACE(Event))
499 event->trace("descheduled");
500}
501
502inline void
503EventQueue::reschedule(Event *event, Tick when, bool always)
504{
505 assert(when >= curTick);
506 assert(always || event->scheduled());
507
508 if (event->scheduled())
509 remove(event);
510
511 event->setWhen(when, this);
512 insert(event);
472 event->clearFlags(Event::Squashed);
473 event->setFlags(Event::Scheduled);
513 event->flags.clear(Event::Squashed);
514 event->flags.set(Event::Scheduled);
515 if (this == &mainEventQueue)
475 event->setFlags(Event::IsMainQueue);
516 event->flags.set(Event::IsMainQueue);
517 else
477 event->clearFlags(Event::IsMainQueue);
518 event->flags.clear(Event::IsMainQueue);
519
520 if (DTRACE(Event))
521 event->trace("rescheduled");
522}
523
524inline bool
525operator<(const Event &l, const Event &r)
526{

--- 38 unchanged lines hidden ---