eventq.hh (5602:9abcc140f346) eventq.hh (5605:b194a80157e2)
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;

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

46#include "base/fast_alloc.hh"
47#include "base/misc.hh"
48#include "base/trace.hh"
49#include "sim/serialize.hh"
50#include "sim/host.hh"
51
52class EventQueue; // forward declaration
53
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;

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

46#include "base/fast_alloc.hh"
47#include "base/misc.hh"
48#include "base/trace.hh"
49#include "sim/serialize.hh"
50#include "sim/host.hh"
51
52class EventQueue; // forward declaration
53
54//////////////////////
55//
56// Main Event Queue
57//
58// Events on this queue are processed at the *beginning* of each
59// cycle, before the pipeline simulation is performed.
60//
61// defined in eventq.cc
62//
63//////////////////////
64extern EventQueue mainEventQueue;
65
66/*
67 * An item on an event queue. The action caused by a given
68 * event is specified by deriving a subclass and overriding the
69 * process() member function.
70 *
71 * Caution, the order of members is chosen to maximize data packing.

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

85 // constant/constant. Hopefully this is a significant improvement
86 // over the current fully linear insertion.
87 Event *nextBin;
88 Event *nextInBin;
89
90 static Event *insertBefore(Event *event, Event *curr);
91 static Event *removeItem(Event *event, Event *last);
92
54extern EventQueue mainEventQueue;
55
56/*
57 * An item on an event queue. The action caused by a given
58 * event is specified by deriving a subclass and overriding the
59 * process() member function.
60 *
61 * Caution, the order of members is chosen to maximize data packing.

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

75 // constant/constant. Hopefully this is a significant improvement
76 // over the current fully linear insertion.
77 Event *nextBin;
78 Event *nextInBin;
79
80 static Event *insertBefore(Event *event, Event *curr);
81 static Event *removeItem(Event *event, Event *last);
82
93 /// queue to which this event belongs (though it may or may not be
94 /// scheduled on this queue yet)
95 EventQueue *_queue;
96
97 Tick _when; //!< timestamp when event should be processed
98 short _priority; //!< event priority
99 short _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
108 /// debugging.
109 Counter instance;
83 Tick _when; //!< timestamp when event should be processed
84 short _priority; //!< event priority
85 short _flags;
86
87#ifndef NDEBUG
88 /// Global counter to generate unique IDs for Event instances
89 static Counter instanceCounter;
90
91 /// This event's unique ID. We can also use pointer values for
92 /// this but they're not consistent across runs making debugging
93 /// more difficult. Thus we use a global counter value when
94 /// debugging.
95 Counter instance;
96
97 /// queue to which this event belongs (though it may or may not be
98 /// scheduled on this queue yet)
99 EventQueue *queue;
110#endif
111
112#ifdef EVENTQ_DEBUG
113 Tick whenCreated; //!< time created
114 Tick whenScheduled; //!< time scheduled
115#endif
116
100#endif
101
102#ifdef EVENTQ_DEBUG
103 Tick whenCreated; //!< time created
104 Tick whenScheduled; //!< time scheduled
105#endif
106
117 protected:
118 void
107 void
119 setWhen(Tick when)
108 setWhen(Tick when, EventQueue *q)
120 {
121 _when = when;
109 {
110 _when = when;
111#ifndef NDEBUG
112 queue = q;
113#endif
122#ifdef EVENTQ_DEBUG
123 whenScheduled = curTick;
124#endif
125 }
126
127 protected:
128 enum Flags {
129 None = 0x0,
130 Squashed = 0x1,
131 Scheduled = 0x2,
132 AutoDelete = 0x4,
133 AutoSerialize = 0x8,
114#ifdef EVENTQ_DEBUG
115 whenScheduled = curTick;
116#endif
117 }
118
119 protected:
120 enum Flags {
121 None = 0x0,
122 Squashed = 0x1,
123 Scheduled = 0x2,
124 AutoDelete = 0x4,
125 AutoSerialize = 0x8,
134 IsExitEvent = 0x10
126 IsExitEvent = 0x10,
127 IsMainQueue = 0x20
135 };
136
137 bool getFlags(Flags f) const { return (_flags & f) == f; }
138 void setFlags(Flags f) { _flags |= f; }
139 void clearFlags(Flags f) { _flags &= ~f; }
140
141 protected:
128 };
129
130 bool getFlags(Flags f) const { return (_flags & f) == f; }
131 void setFlags(Flags f) { _flags |= f; }
132 void clearFlags(Flags f) { _flags &= ~f; }
133
134 protected:
142 EventQueue *queue() const { return _queue; }
143
144 // This function isn't really useful if TRACING_ON is not defined
145 virtual void trace(const char *action); //!< trace event activity
146
147 public:
148 /// Event priorities, to provide tie-breakers for events scheduled
149 /// at the same cycle. Most events are scheduled at the default
150 /// priority; these values are used to control events that need to
151 /// be ordered within a cycle.

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

200 /// Maximum priority
201 Maximum_Pri = SHRT_MAX
202 };
203
204 /*
205 * Event constructor
206 * @param queue that the event gets scheduled on
207 */
135 // This function isn't really useful if TRACING_ON is not defined
136 virtual void trace(const char *action); //!< trace event activity
137
138 public:
139 /// Event priorities, to provide tie-breakers for events scheduled
140 /// at the same cycle. Most events are scheduled at the default
141 /// priority; these values are used to control events that need to
142 /// be ordered within a cycle.

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

191 /// Maximum priority
192 Maximum_Pri = SHRT_MAX
193 };
194
195 /*
196 * Event constructor
197 * @param queue that the event gets scheduled on
198 */
208 Event(EventQueue *q, Priority p = Default_Pri)
209 : nextBin(NULL), nextInBin(NULL), _queue(q), _priority(p), _flags(None)
199 Event(Priority p = Default_Pri)
200 : nextBin(NULL), nextInBin(NULL), _priority(p), _flags(None)
210 {
211#ifndef NDEBUG
212 instance = ++instanceCounter;
201 {
202#ifndef NDEBUG
203 instance = ++instanceCounter;
204 queue = NULL;
213#endif
214#ifdef EVENTQ_DEBUG
215 whenCreated = curTick;
216 whenScheduled = 0;
217#endif
218 }
219
220 virtual

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

251 * If the AutoDestroy flag is set, the object is deleted once it
252 * is processed.
253 */
254 virtual void process() = 0;
255
256 /// Determine if the current event is scheduled
257 bool scheduled() const { return getFlags(Scheduled); }
258
205#endif
206#ifdef EVENTQ_DEBUG
207 whenCreated = curTick;
208 whenScheduled = 0;
209#endif
210 }
211
212 virtual

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

243 * If the AutoDestroy flag is set, the object is deleted once it
244 * is processed.
245 */
246 virtual void process() = 0;
247
248 /// Determine if the current event is scheduled
249 bool scheduled() const { return getFlags(Scheduled); }
250
259 /// Schedule the event with the current priority or default priority
260 void schedule(Tick t);
261
262 /// Reschedule the event with the current priority
263 // always parameter means to schedule if not already scheduled
264 void reschedule(Tick t, bool always = false);
265
266 /// Remove the event from the current schedule
267 void deschedule();
268
269 /// Squash the current event
270 void squash() { setFlags(Squashed); }
271
272 /// Check whether the event is squashed
273 bool squashed() const { return getFlags(Squashed); }
274
275 /// See if this is a SimExitEvent (without resorting to RTTI)
276 bool isExitEvent() const { return getFlags(IsExitEvent); }
277
278 /// Get the time that the event is scheduled
279 Tick when() const { return _when; }
280
281 /// Get the event priority
282 int priority() const { return _priority; }
283
251 /// Squash the current event
252 void squash() { setFlags(Squashed); }
253
254 /// Check whether the event is squashed
255 bool squashed() const { return getFlags(Squashed); }
256
257 /// See if this is a SimExitEvent (without resorting to RTTI)
258 bool isExitEvent() const { return getFlags(IsExitEvent); }
259
260 /// Get the time that the event is scheduled
261 Tick when() const { return _when; }
262
263 /// Get the event priority
264 int priority() const { return _priority; }
265
266#ifndef SWIG
284 struct priority_compare
285 : public std::binary_function<Event *, Event *, bool>
286 {
287 bool
288 operator()(const Event *l, const Event *r) const
289 {
290 return l->when() >= r->when() || l->priority() >= r->priority();
291 }
292 };
293
294 virtual void serialize(std::ostream &os);
295 virtual void unserialize(Checkpoint *cp, const std::string &section);
267 struct priority_compare
268 : public std::binary_function<Event *, Event *, bool>
269 {
270 bool
271 operator()(const Event *l, const Event *r) const
272 {
273 return l->when() >= r->when() || l->priority() >= r->priority();
274 }
275 };
276
277 virtual void serialize(std::ostream &os);
278 virtual void unserialize(Checkpoint *cp, const std::string &section);
279#endif
296};
297
280};
281
298template <class T, void (T::* F)()>
299void
300DelayFunction(Tick when, T *object)
301{
302 class DelayEvent : public Event
303 {
304 private:
305 T *object;
306
307 public:
308 DelayEvent(Tick when, T *o)
309 : Event(&mainEventQueue), object(o)
310 { setFlags(this->AutoDestroy); schedule(when); }
311 void process() { (object->*F)(); }
312 const char *description() const { return "delay"; }
313 };
314
315 new DelayEvent(when, object);
316}
317
318template <class T, void (T::* F)()>
319class EventWrapper : public Event
320{
321 private:
322 T *object;
323
324 public:
325 EventWrapper(T *obj, bool del = false,
326 EventQueue *q = &mainEventQueue,
327 Priority p = Default_Pri)
328 : Event(q, p), object(obj)
329 {
330 if (del)
331 setFlags(AutoDelete);
332 }
333
334 EventWrapper(T *obj, Tick t, bool del = false,
335 EventQueue *q = &mainEventQueue,
336 Priority p = Default_Pri)
337 : Event(q, p), object(obj)
338 {
339 if (del)
340 setFlags(AutoDelete);
341 schedule(t);
342 }
343
344 void process() { (object->*F)(); }
345};
346
347/*
348 * Queue of events sorted in time order
349 */
350class EventQueue : public Serializable
351{
282/*
283 * Queue of events sorted in time order
284 */
285class EventQueue : public Serializable
286{
352 protected:
353 std::string objName;
354
355 private:
287 private:
288 std::string objName;
356 Event *head;
357
358 void insert(Event *event);
359 void remove(Event *event);
360
361 public:
289 Event *head;
290
291 void insert(Event *event);
292 void remove(Event *event);
293
294 public:
362
363 // constructor
364 EventQueue(const std::string &n)
365 : objName(n), head(NULL)
366 {}
367
368 virtual const std::string name() const { return objName; }
369
370 // schedule the given event on this queue
371 void schedule(Event *ev, Tick when);
372 void deschedule(Event *ev);
295 EventQueue(const std::string &n)
296 : objName(n), head(NULL)
297 {}
298
299 virtual const std::string name() const { return objName; }
300
301 // schedule the given event on this queue
302 void schedule(Event *ev, Tick when);
303 void deschedule(Event *ev);
373 void reschedule(Event *ev, Tick when);
304 void reschedule(Event *ev, Tick when, bool always = false);
374
375 Tick nextTick() const { return head->when(); }
376 Event *serviceOne();
377
378 // process all events up to the given timestamp. we inline a
379 // quick test to see if there are any events to process; if so,
380 // call the internal out-of-line version to process them all.
381 void

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

401 bool empty() const { return head == NULL; }
402
403 void dump() const;
404
405 Tick nextEventTime() { return empty() ? curTick : head->when(); }
406
407 bool debugVerify() const;
408
305
306 Tick nextTick() const { return head->when(); }
307 Event *serviceOne();
308
309 // process all events up to the given timestamp. we inline a
310 // quick test to see if there are any events to process; if so,
311 // call the internal out-of-line version to process them all.
312 void

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

332 bool empty() const { return head == NULL; }
333
334 void dump() const;
335
336 Tick nextEventTime() { return empty() ? curTick : head->when(); }
337
338 bool debugVerify() const;
339
340#ifndef SWIG
409 virtual void serialize(std::ostream &os);
410 virtual void unserialize(Checkpoint *cp, const std::string &section);
341 virtual void serialize(std::ostream &os);
342 virtual void unserialize(Checkpoint *cp, const std::string &section);
343#endif
411};
412
344};
345
346#ifndef SWIG
347class EventManager
348{
349 protected:
350 /** A pointer to this object's event queue */
351 EventQueue *eventq;
413
352
414//////////////////////
415//
416// inline functions
417//
418// can't put these inside declaration due to circular dependence
419// between Event and EventQueue classes.
420//
421//////////////////////
353 public:
354 EventManager(EventManager &em) : eventq(em.queue()) {}
355 EventManager(EventManager *em) : eventq(em ? em->queue() : NULL) {}
356 EventManager(EventQueue *eq) : eventq(eq) {}
422
357
423// schedule at specified time (place on event queue specified via
424// constructor)
425inline void
426Event::schedule(Tick when)
427{
428 _queue->schedule(this, when);
429}
358 EventQueue *
359 queue() const
360 {
361 return eventq;
362 }
430
363
431inline void
432Event::deschedule()
433{
434 _queue->deschedule(this);
435}
364 void
365 schedule(Event &event, Tick when)
366 {
367 eventq->schedule(&event, when);
368 }
436
369
437inline void
438Event::reschedule(Tick when, bool always)
439{
440 if (scheduled()) {
441 _queue->reschedule(this, when);
442 } else {
443 assert(always);
444 _queue->schedule(this, when);
370 void
371 deschedule(Event &event)
372 {
373 eventq->deschedule(&event);
445 }
374 }
446}
447
375
448inline bool
449operator<(const Event &l, const Event &r)
450{
451 return l.when() < r.when() ||
452 (l.when() == r.when() && l.priority() < r.priority());
453}
376 void
377 reschedule(Event &event, Tick when, bool always = false)
378 {
379 eventq->reschedule(&event, when, always);
380 }
454
381
455inline bool
456operator>(const Event &l, const Event &r)
457{
458 return l.when() > r.when() ||
459 (l.when() == r.when() && l.priority() > r.priority());
460}
382 void
383 schedule(Event *event, Tick when)
384 {
385 eventq->schedule(event, when);
386 }
461
387
462inline bool
463operator<=(const Event &l, const Event &r)
464{
465 return l.when() < r.when() ||
466 (l.when() == r.when() && l.priority() <= r.priority());
467}
468inline bool
469operator>=(const Event &l, const Event &r)
470{
471 return l.when() > r.when() ||
472 (l.when() == r.when() && l.priority() >= r.priority());
473}
388 void
389 deschedule(Event *event)
390 {
391 eventq->deschedule(event);
392 }
474
393
475inline bool
476operator==(const Event &l, const Event &r)
394 void
395 reschedule(Event *event, Tick when, bool always = false)
396 {
397 eventq->reschedule(event, when, always);
398 }
399};
400
401template <class T, void (T::* F)()>
402void
403DelayFunction(EventQueue *eventq, Tick when, T *object)
477{
404{
478 return l.when() == r.when() && l.priority() == r.priority();
405 class DelayEvent : public Event
406 {
407 private:
408 T *object;
409
410 public:
411 DelayEvent(T *o)
412 : object(o)
413 { setFlags(this->AutoDestroy); }
414 void process() { (object->*F)(); }
415 const char *description() const { return "delay"; }
416 };
417
418 eventq->schedule(new DelayEvent(object), when);
479}
480
419}
420
481inline bool
482operator!=(const Event &l, const Event &r)
421template <class T, void (T::* F)()>
422class EventWrapper : public Event
483{
423{
484 return l.when() != r.when() || l.priority() != r.priority();
485}
424 private:
425 T *object;
486
426
427 public:
428 EventWrapper(T *obj, bool del = false, Priority p = Default_Pri)
429 : Event(p), object(obj)
430 {
431 if (del)
432 setFlags(AutoDelete);
433 }
434
435 void process() { (object->*F)(); }
436};
437
487inline void
488EventQueue::schedule(Event *event, Tick when)
489{
490 assert(when >= curTick);
491 assert(!event->scheduled());
492
438inline void
439EventQueue::schedule(Event *event, Tick when)
440{
441 assert(when >= curTick);
442 assert(!event->scheduled());
443
493 event->setWhen(when);
444 event->setWhen(when, this);
494 insert(event);
495 event->setFlags(Event::Scheduled);
445 insert(event);
446 event->setFlags(Event::Scheduled);
447 if (this == &mainEventQueue)
448 event->setFlags(Event::IsMainQueue);
449 else
450 event->clearFlags(Event::IsMainQueue);
496
497 if (DTRACE(Event))
498 event->trace("scheduled");
499}
500
501inline void
502EventQueue::deschedule(Event *event)
503{

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

511 if (event->getFlags(Event::AutoDelete))
512 delete event;
513
514 if (DTRACE(Event))
515 event->trace("descheduled");
516}
517
518inline void
451
452 if (DTRACE(Event))
453 event->trace("scheduled");
454}
455
456inline void
457EventQueue::deschedule(Event *event)
458{

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

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