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; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Steve Reinhardt 29 * Nathan Binkert 30 */ 31 32/* @file 33 * EventQueue interfaces 34 */ 35 36#ifndef __SIM_EVENTQ_HH__ 37#define __SIM_EVENTQ_HH__ 38 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"
| 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; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Steve Reinhardt 29 * Nathan Binkert 30 */ 31 32/* @file 33 * EventQueue interfaces 34 */ 35 36#ifndef __SIM_EVENTQ_HH__ 37#define __SIM_EVENTQ_HH__ 38 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"
|
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 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. 62 */ 63class Event : public Serializable, public FastAlloc 64{ 65 friend class EventQueue; 66
| 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; 56 57/* 58 * An item on an event queue. The action caused by a given 59 * event is specified by deriving a subclass and overriding the 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
|
67 private: 68 // The event queue is now a linked list of linked lists. The 69 // 'nextBin' pointer is to find the bin, where a bin is defined as 70 // when+priority. All events in the same bin will be stored in a 71 // second linked list (a stack) maintained by the 'nextInBin' 72 // pointer. The list will be accessed in LIFO order. The end 73 // result is that the insert/removal in 'nextBin' is 74 // linear/constant, and the lookup/removal in 'nextInBin' is 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 83 Tick _when; //!< timestamp when event should be processed 84 short _priority; //!< event priority
| 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;
|
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; 100#endif 101 102#ifdef EVENTQ_DEBUG 103 Tick whenCreated; //!< time created 104 Tick whenScheduled; //!< time scheduled 105#endif 106 107 void 108 setWhen(Tick when, EventQueue *q) 109 { 110 _when = when; 111#ifndef NDEBUG 112 queue = q; 113#endif 114#ifdef EVENTQ_DEBUG 115 whenScheduled = curTick; 116#endif 117 } 118 119 protected:
| 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; 110 111 /// queue to which this event belongs (though it may or may not be 112 /// scheduled on this queue yet) 113 EventQueue *queue; 114#endif 115 116#ifdef EVENTQ_DEBUG 117 Tick whenCreated; //!< time created 118 Tick whenScheduled; //!< time scheduled 119#endif 120 121 void 122 setWhen(Tick when, EventQueue *q) 123 { 124 _when = when; 125#ifndef NDEBUG 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 }
|
129
| 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 }
|
133
| 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
|
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. 143 enum Priority { 144 /// Minimum priority 145 Minimum_Pri = SHRT_MIN, 146 147 /// If we enable tracing on a particular cycle, do that as the 148 /// very first thing so we don't miss any of the events on 149 /// that cycle (even if we enter the debugger). 150 Trace_Enable_Pri = -101, 151 152 /// Breakpoints should happen before anything else (except 153 /// enabling trace output), so we don't miss any action when 154 /// debugging. 155 Debug_Break_Pri = -100, 156 157 /// CPU switches schedule the new CPU's tick event for the 158 /// same cycle (after unscheduling the old CPU's tick event). 159 /// The switch needs to come before any tick events to make 160 /// sure we don't tick both CPUs in the same cycle. 161 CPU_Switch_Pri = -31, 162 163 /// For some reason "delayed" inter-cluster writebacks are 164 /// scheduled before regular writebacks (which have default 165 /// priority). Steve? 166 Delayed_Writeback_Pri = -1, 167 168 /// Default is zero for historical reasons. 169 Default_Pri = 0, 170 171 /// Serailization needs to occur before tick events also, so 172 /// that a serialize/unserialize is identical to an on-line 173 /// CPU switch. 174 Serialize_Pri = 32, 175 176 /// CPU ticks must come after other associated CPU events 177 /// (such as writebacks). 178 CPU_Tick_Pri = 50, 179 180 /// Statistics events (dump, reset, etc.) come after 181 /// everything else, but before exit. 182 Stat_Event_Pri = 90, 183 184 /// Progress events come at the end. 185 Progress_Event_Pri = 95, 186 187 /// If we want to exit on this cycle, it's the very last thing 188 /// we do. 189 Sim_Exit_Pri = 100, 190 191 /// Maximum priority 192 Maximum_Pri = SHRT_MAX 193 }; 194 195 /* 196 * Event constructor 197 * @param queue that the event gets scheduled on 198 */ 199 Event(Priority p = Default_Pri)
| 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. 184 enum Priority { 185 /// Minimum priority 186 Minimum_Pri = SHRT_MIN, 187 188 /// If we enable tracing on a particular cycle, do that as the 189 /// very first thing so we don't miss any of the events on 190 /// that cycle (even if we enter the debugger). 191 Trace_Enable_Pri = -101, 192 193 /// Breakpoints should happen before anything else (except 194 /// enabling trace output), so we don't miss any action when 195 /// debugging. 196 Debug_Break_Pri = -100, 197 198 /// CPU switches schedule the new CPU's tick event for the 199 /// same cycle (after unscheduling the old CPU's tick event). 200 /// The switch needs to come before any tick events to make 201 /// sure we don't tick both CPUs in the same cycle. 202 CPU_Switch_Pri = -31, 203 204 /// For some reason "delayed" inter-cluster writebacks are 205 /// scheduled before regular writebacks (which have default 206 /// priority). Steve? 207 Delayed_Writeback_Pri = -1, 208 209 /// Default is zero for historical reasons. 210 Default_Pri = 0, 211 212 /// Serailization needs to occur before tick events also, so 213 /// that a serialize/unserialize is identical to an on-line 214 /// CPU switch. 215 Serialize_Pri = 32, 216 217 /// CPU ticks must come after other associated CPU events 218 /// (such as writebacks). 219 CPU_Tick_Pri = 50, 220 221 /// Statistics events (dump, reset, etc.) come after 222 /// everything else, but before exit. 223 Stat_Event_Pri = 90, 224 225 /// Progress events come at the end. 226 Progress_Event_Pri = 95, 227 228 /// If we want to exit on this cycle, it's the very last thing 229 /// we do. 230 Sim_Exit_Pri = 100, 231 232 /// Maximum priority 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)
|
201 { 202#ifndef NDEBUG 203 instance = ++instanceCounter; 204 queue = NULL; 205#endif 206#ifdef EVENTQ_DEBUG 207 whenCreated = curTick; 208 whenScheduled = 0; 209#endif 210 } 211 212 virtual ~Event(); 213 virtual const std::string name() const; 214 215 /// Return a C string describing the event. This string should 216 /// *not* be dynamically allocated; just a const char array 217 /// describing the event class. 218 virtual const char *description() const; 219 220 /// Dump the current event data 221 void dump() const; 222 223 public: 224 /* 225 * This member function is invoked when the event is processed 226 * (occurs). There is no default implementation; each subclass 227 * must provide its own implementation. The event is not 228 * automatically deleted after it is processed (to allow for 229 * statically allocated event objects). 230 * 231 * If the AutoDestroy flag is set, the object is deleted once it 232 * is processed. 233 */ 234 virtual void process() = 0; 235 236 /// Determine if the current event is scheduled
| 242 { 243#ifndef NDEBUG 244 instance = ++instanceCounter; 245 queue = NULL; 246#endif 247#ifdef EVENTQ_DEBUG 248 whenCreated = curTick; 249 whenScheduled = 0; 250#endif 251 } 252 253 virtual ~Event(); 254 virtual const std::string name() const; 255 256 /// Return a C string describing the event. This string should 257 /// *not* be dynamically allocated; just a const char array 258 /// describing the event class. 259 virtual const char *description() const; 260 261 /// Dump the current event data 262 void dump() const; 263 264 public: 265 /* 266 * This member function is invoked when the event is processed 267 * (occurs). There is no default implementation; each subclass 268 * must provide its own implementation. The event is not 269 * automatically deleted after it is processed (to allow for 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); }
|
238 239 /// Squash the current event
| 279 280 /// Squash the current event
|
240 void squash() { setFlags(Squashed); }
| 281 void squash() { flags.set(Squashed); }
|
241 242 /// Check whether the event is squashed
| 282 283 /// Check whether the event is squashed
|
243 bool squashed() const { return getFlags(Squashed); }
| 284 bool squashed() const { return flags.isSet(Squashed); }
|
244 245 /// See if this is a SimExitEvent (without resorting to RTTI)
| 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); }
|
247 248 /// Get the time that the event is scheduled 249 Tick when() const { return _when; } 250 251 /// Get the event priority 252 int priority() const { return _priority; } 253 254#ifndef SWIG 255 struct priority_compare 256 : public std::binary_function<Event *, Event *, bool> 257 { 258 bool 259 operator()(const Event *l, const Event *r) const 260 { 261 return l->when() >= r->when() || l->priority() >= r->priority(); 262 } 263 }; 264 265 virtual void serialize(std::ostream &os); 266 virtual void unserialize(Checkpoint *cp, const std::string §ion); 267#endif 268}; 269 270/* 271 * Queue of events sorted in time order 272 */ 273class EventQueue : public Serializable 274{ 275 private: 276 std::string objName; 277 Event *head; 278 279 void insert(Event *event); 280 void remove(Event *event); 281 282 public: 283 EventQueue(const std::string &n) 284 : objName(n), head(NULL) 285 {} 286 287 virtual const std::string name() const { return objName; } 288 289 // schedule the given event on this queue 290 void schedule(Event *event, Tick when); 291 void deschedule(Event *event); 292 void reschedule(Event *event, Tick when, bool always = false); 293 294 Tick nextTick() const { return head->when(); } 295 Event *serviceOne(); 296 297 // process all events up to the given timestamp. we inline a 298 // quick test to see if there are any events to process; if so, 299 // call the internal out-of-line version to process them all. 300 void 301 serviceEvents(Tick when) 302 { 303 while (!empty()) { 304 if (nextTick() > when) 305 break; 306 307 /** 308 * @todo this assert is a good bug catcher. I need to 309 * make it true again. 310 */ 311 //assert(head->when() >= when && "event scheduled in the past"); 312 serviceOne(); 313 } 314 } 315 316 // default: process all events up to 'now' (curTick) 317 void serviceEvents() { serviceEvents(curTick); } 318 319 // return true if no events are queued 320 bool empty() const { return head == NULL; } 321 322 void dump() const; 323 324 Tick nextEventTime() { return empty() ? curTick : head->when(); } 325 326 bool debugVerify() const; 327 328#ifndef SWIG 329 virtual void serialize(std::ostream &os); 330 virtual void unserialize(Checkpoint *cp, const std::string §ion); 331#endif 332}; 333 334#ifndef SWIG 335class EventManager 336{ 337 protected: 338 /** A pointer to this object's event queue */ 339 EventQueue *eventq; 340 341 public: 342 EventManager(EventManager &em) : eventq(em.queue()) {} 343 EventManager(EventManager *em) : eventq(em ? em->queue() : NULL) {} 344 EventManager(EventQueue *eq) : eventq(eq) {} 345 346 EventQueue * 347 queue() const 348 { 349 return eventq; 350 } 351 352 void 353 schedule(Event &event, Tick when) 354 { 355 eventq->schedule(&event, when); 356 } 357 358 void 359 deschedule(Event &event) 360 { 361 eventq->deschedule(&event); 362 } 363 364 void 365 reschedule(Event &event, Tick when, bool always = false) 366 { 367 eventq->reschedule(&event, when, always); 368 } 369 370 void 371 schedule(Event *event, Tick when) 372 { 373 eventq->schedule(event, when); 374 } 375 376 void 377 deschedule(Event *event) 378 { 379 eventq->deschedule(event); 380 } 381 382 void 383 reschedule(Event *event, Tick when, bool always = false) 384 { 385 eventq->reschedule(event, when, always); 386 } 387}; 388 389template <class T, void (T::* F)()> 390void 391DelayFunction(EventQueue *eventq, Tick when, T *object) 392{ 393 class DelayEvent : public Event 394 { 395 private: 396 T *object; 397 398 public: 399 DelayEvent(T *o) 400 : object(o)
| 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 296 struct priority_compare 297 : public std::binary_function<Event *, Event *, bool> 298 { 299 bool 300 operator()(const Event *l, const Event *r) const 301 { 302 return l->when() >= r->when() || l->priority() >= r->priority(); 303 } 304 }; 305 306 virtual void serialize(std::ostream &os); 307 virtual void unserialize(Checkpoint *cp, const std::string §ion); 308#endif 309}; 310 311/* 312 * Queue of events sorted in time order 313 */ 314class EventQueue : public Serializable 315{ 316 private: 317 std::string objName; 318 Event *head; 319 320 void insert(Event *event); 321 void remove(Event *event); 322 323 public: 324 EventQueue(const std::string &n) 325 : objName(n), head(NULL) 326 {} 327 328 virtual const std::string name() const { return objName; } 329 330 // schedule the given event on this queue 331 void schedule(Event *event, Tick when); 332 void deschedule(Event *event); 333 void reschedule(Event *event, Tick when, bool always = false); 334 335 Tick nextTick() const { return head->when(); } 336 Event *serviceOne(); 337 338 // process all events up to the given timestamp. we inline a 339 // quick test to see if there are any events to process; if so, 340 // call the internal out-of-line version to process them all. 341 void 342 serviceEvents(Tick when) 343 { 344 while (!empty()) { 345 if (nextTick() > when) 346 break; 347 348 /** 349 * @todo this assert is a good bug catcher. I need to 350 * make it true again. 351 */ 352 //assert(head->when() >= when && "event scheduled in the past"); 353 serviceOne(); 354 } 355 } 356 357 // default: process all events up to 'now' (curTick) 358 void serviceEvents() { serviceEvents(curTick); } 359 360 // return true if no events are queued 361 bool empty() const { return head == NULL; } 362 363 void dump() const; 364 365 Tick nextEventTime() { return empty() ? curTick : head->when(); } 366 367 bool debugVerify() const; 368 369#ifndef SWIG 370 virtual void serialize(std::ostream &os); 371 virtual void unserialize(Checkpoint *cp, const std::string §ion); 372#endif 373}; 374 375#ifndef SWIG 376class EventManager 377{ 378 protected: 379 /** A pointer to this object's event queue */ 380 EventQueue *eventq; 381 382 public: 383 EventManager(EventManager &em) : eventq(em.queue()) {} 384 EventManager(EventManager *em) : eventq(em ? em->queue() : NULL) {} 385 EventManager(EventQueue *eq) : eventq(eq) {} 386 387 EventQueue * 388 queue() const 389 { 390 return eventq; 391 } 392 393 void 394 schedule(Event &event, Tick when) 395 { 396 eventq->schedule(&event, when); 397 } 398 399 void 400 deschedule(Event &event) 401 { 402 eventq->deschedule(&event); 403 } 404 405 void 406 reschedule(Event &event, Tick when, bool always = false) 407 { 408 eventq->reschedule(&event, when, always); 409 } 410 411 void 412 schedule(Event *event, Tick when) 413 { 414 eventq->schedule(event, when); 415 } 416 417 void 418 deschedule(Event *event) 419 { 420 eventq->deschedule(event); 421 } 422 423 void 424 reschedule(Event *event, Tick when, bool always = false) 425 { 426 eventq->reschedule(event, when, always); 427 } 428}; 429 430template <class T, void (T::* F)()> 431void 432DelayFunction(EventQueue *eventq, Tick when, T *object) 433{ 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); }
|
402 void process() { (object->*F)(); } 403 const char *description() const { return "delay"; } 404 }; 405 406 eventq->schedule(new DelayEvent(object), when); 407} 408 409template <class T, void (T::* F)()> 410class EventWrapper : public Event 411{ 412 private: 413 T *object; 414 415 public: 416 EventWrapper(T *obj, bool del = false, Priority p = Default_Pri) 417 : Event(p), object(obj) 418 { 419 if (del) 420 setFlags(AutoDelete); 421 } 422 423 void process() { (object->*F)(); } 424}; 425 426inline void 427EventQueue::schedule(Event *event, Tick when) 428{ 429 assert(when >= curTick); 430 assert(!event->scheduled()); 431 432 event->setWhen(when, this); 433 insert(event);
| 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)()> 451class EventWrapper : public Event 452{ 453 private: 454 T *object; 455 456 public: 457 EventWrapper(T *obj, bool del = false, Priority p = Default_Pri) 458 : Event(p), object(obj) 459 { 460 if (del) 461 setFlags(AutoDelete); 462 } 463 464 void process() { (object->*F)(); } 465}; 466 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);
|
435 if (this == &mainEventQueue)
| 476 if (this == &mainEventQueue)
|
436 event->setFlags(Event::IsMainQueue);
| 477 event->flags.set(Event::IsMainQueue);
|
437 else
| 478 else
|
438 event->clearFlags(Event::IsMainQueue);
| 479 event->flags.clear(Event::IsMainQueue);
|
439 440 if (DTRACE(Event)) 441 event->trace("scheduled"); 442} 443 444inline void 445EventQueue::deschedule(Event *event) 446{ 447 assert(event->scheduled()); 448 449 remove(event); 450
| 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);
|
453
| 494
|
454 if (event->getFlags(Event::AutoDelete))
| 495 if (event->flags.isSet(Event::AutoDelete))
|
455 delete event; 456 457 if (DTRACE(Event)) 458 event->trace("descheduled"); 459} 460 461inline void 462EventQueue::reschedule(Event *event, Tick when, bool always) 463{ 464 assert(when >= curTick); 465 assert(always || event->scheduled()); 466 467 if (event->scheduled()) 468 remove(event); 469 470 event->setWhen(when, this); 471 insert(event);
| 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);
|
474 if (this == &mainEventQueue)
| 515 if (this == &mainEventQueue)
|
475 event->setFlags(Event::IsMainQueue);
| 516 event->flags.set(Event::IsMainQueue);
|
476 else
| 517 else
|
477 event->clearFlags(Event::IsMainQueue);
| 518 event->flags.clear(Event::IsMainQueue);
|
478 479 if (DTRACE(Event)) 480 event->trace("rescheduled"); 481} 482 483inline bool 484operator<(const Event &l, const Event &r) 485{ 486 return l.when() < r.when() || 487 (l.when() == r.when() && l.priority() < r.priority()); 488} 489 490inline bool 491operator>(const Event &l, const Event &r) 492{ 493 return l.when() > r.when() || 494 (l.when() == r.when() && l.priority() > r.priority()); 495} 496 497inline bool 498operator<=(const Event &l, const Event &r) 499{ 500 return l.when() < r.when() || 501 (l.when() == r.when() && l.priority() <= r.priority()); 502} 503inline bool 504operator>=(const Event &l, const Event &r) 505{ 506 return l.when() > r.when() || 507 (l.when() == r.when() && l.priority() >= r.priority()); 508} 509 510inline bool 511operator==(const Event &l, const Event &r) 512{ 513 return l.when() == r.when() && l.priority() == r.priority(); 514} 515 516inline bool 517operator!=(const Event &l, const Event &r) 518{ 519 return l.when() != r.when() || l.priority() != r.priority(); 520} 521#endif 522 523#endif // __SIM_EVENTQ_HH__
| 519 520 if (DTRACE(Event)) 521 event->trace("rescheduled"); 522} 523 524inline bool 525operator<(const Event &l, const Event &r) 526{ 527 return l.when() < r.when() || 528 (l.when() == r.when() && l.priority() < r.priority()); 529} 530 531inline bool 532operator>(const Event &l, const Event &r) 533{ 534 return l.when() > r.when() || 535 (l.when() == r.when() && l.priority() > r.priority()); 536} 537 538inline bool 539operator<=(const Event &l, const Event &r) 540{ 541 return l.when() < r.when() || 542 (l.when() == r.when() && l.priority() <= r.priority()); 543} 544inline bool 545operator>=(const Event &l, const Event &r) 546{ 547 return l.when() > r.when() || 548 (l.when() == r.when() && l.priority() >= r.priority()); 549} 550 551inline bool 552operator==(const Event &l, const Event &r) 553{ 554 return l.when() == r.when() && l.priority() == r.priority(); 555} 556 557inline bool 558operator!=(const Event &l, const Event &r) 559{ 560 return l.when() != r.when() || l.priority() != r.priority(); 561} 562#endif 563 564#endif // __SIM_EVENTQ_HH__
|