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 §ion); | 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 §ion); |
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 §ion); | 341 virtual void serialize(std::ostream &os); 342 virtual void unserialize(Checkpoint *cp, const std::string §ion); |
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__ |