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
| 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 <assert.h> 40
| |
41#include <algorithm>
| 39#include <algorithm>
|
| 40#include <cassert>
|
42#include <map> 43#include <string> 44#include <vector> 45
| 41#include <map> 42#include <string> 43#include <vector> 44
|
46#include "sim/host.hh" // for Tick 47
| |
48#include "base/fast_alloc.hh" 49#include "base/misc.hh" 50#include "base/trace.hh" 51#include "sim/serialize.hh"
| 45#include "base/fast_alloc.hh" 46#include "base/misc.hh" 47#include "base/trace.hh" 48#include "sim/serialize.hh"
|
| 49#include "sim/host.hh"
|
52 53class EventQueue; // forward declaration 54 55////////////////////// 56// 57// Main Event Queue 58// 59// Events on this queue are processed at the *beginning* of each 60// cycle, before the pipeline simulation is performed. 61// 62// defined in eventq.cc 63// 64////////////////////// 65extern EventQueue mainEventQueue; 66
| 50 51class EventQueue; // forward declaration 52 53////////////////////// 54// 55// Main Event Queue 56// 57// Events on this queue are processed at the *beginning* of each 58// cycle, before the pipeline simulation is performed. 59// 60// defined in eventq.cc 61// 62////////////////////// 63extern EventQueue mainEventQueue; 64
|
67
| |
68/* 69 * An item on an event queue. The action caused by a given 70 * event is specified by deriving a subclass and overriding the 71 * process() member function.
| 65/* 66 * An item on an event queue. The action caused by a given 67 * event is specified by deriving a subclass and overriding the 68 * process() member function.
|
| 69 * 70 * Caution, the order of members is chosen to maximize data packing.
|
72 */ 73class Event : public Serializable, public FastAlloc 74{ 75 friend class EventQueue; 76 77 private:
| 71 */ 72class Event : public Serializable, public FastAlloc 73{ 74 friend class EventQueue; 75 76 private:
|
| 77 Event *next;
|
78
| 78
|
| 79 /// queue to which this event belongs (though it may or may not be 80 /// scheduled on this queue yet) 81 EventQueue *_queue; 82 83 Tick _when; //!< timestamp when event should be processed 84 short _priority; //!< event priority 85 short _flags; 86
|
79#ifndef NDEBUG 80 /// Global counter to generate unique IDs for Event instances 81 static Counter instanceCounter; 82 83 /// This event's unique ID. We can also use pointer values for 84 /// this but they're not consistent across runs making debugging 85 /// more difficult. Thus we use a global counter value when 86 /// debugging.
| 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.
|
87 Counter instanceId; 88#endif // NDEBUG
| 95 Counter instance; 96#endif
|
89
| 97
|
90 /// queue to which this event belongs (though it may or may not be 91 /// scheduled on this queue yet) 92 EventQueue *queue; 93 94 Event *next; 95 96 Tick _when; //!< timestamp when event should be processed 97 int _priority; //!< event priority 98 char _flags; 99
| 98#ifdef DEBUG_EVENTQ 99 Tick whenCreated; //!< time created 100 Tick whenScheduled; //!< time scheduled 101#endif
|
100 protected: 101 enum Flags { 102 None = 0x0, 103 Squashed = 0x1, 104 Scheduled = 0x2, 105 AutoDelete = 0x4, 106 AutoSerialize = 0x8, 107 IsExitEvent = 0x10 108 }; 109 110 bool getFlags(Flags f) const { return (_flags & f) == f; } 111 void setFlags(Flags f) { _flags |= f; } 112 void clearFlags(Flags f) { _flags &= ~f; } 113 114 protected:
| 102 protected: 103 enum Flags { 104 None = 0x0, 105 Squashed = 0x1, 106 Scheduled = 0x2, 107 AutoDelete = 0x4, 108 AutoSerialize = 0x8, 109 IsExitEvent = 0x10 110 }; 111 112 bool getFlags(Flags f) const { return (_flags & f) == f; } 113 void setFlags(Flags f) { _flags |= f; } 114 void clearFlags(Flags f) { _flags &= ~f; } 115 116 protected:
|
115 EventQueue *theQueue() const { return queue; }
| 117 EventQueue *queue() const { return _queue; }
|
116
| 118
|
117#if TRACING_ON 118 Tick when_created; //!< Keep track of creation time For debugging 119 Tick when_scheduled; //!< Keep track of creation time For debugging 120
| 119 // This function isn't really useful if TRACING_ON is not defined
|
121 virtual void trace(const char *action); //!< trace event activity
| 120 virtual void trace(const char *action); //!< trace event activity
|
122#else 123 void trace(const char *) {} 124#endif
| |
125
| 121
|
126 unsigned annotated_value; 127
| |
128 public:
| 122 public:
|
129
| |
130 /// Event priorities, to provide tie-breakers for events scheduled 131 /// at the same cycle. Most events are scheduled at the default 132 /// priority; these values are used to control events that need to 133 /// be ordered within a cycle. 134 enum Priority {
| 123 /// Event priorities, to provide tie-breakers for events scheduled 124 /// at the same cycle. Most events are scheduled at the default 125 /// priority; these values are used to control events that need to 126 /// be ordered within a cycle. 127 enum Priority {
|
| 128 /// Minimum priority 129 Minimum_Pri = SHRT_MIN, 130
|
135 /// If we enable tracing on a particular cycle, do that as the 136 /// very first thing so we don't miss any of the events on 137 /// that cycle (even if we enter the debugger). 138 Trace_Enable_Pri = -101, 139 140 /// Breakpoints should happen before anything else (except 141 /// enabling trace output), so we don't miss any action when 142 /// debugging. 143 Debug_Break_Pri = -100, 144 145 /// CPU switches schedule the new CPU's tick event for the 146 /// same cycle (after unscheduling the old CPU's tick event). 147 /// The switch needs to come before any tick events to make 148 /// sure we don't tick both CPUs in the same cycle. 149 CPU_Switch_Pri = -31, 150 151 /// For some reason "delayed" inter-cluster writebacks are 152 /// scheduled before regular writebacks (which have default 153 /// priority). Steve? 154 Delayed_Writeback_Pri = -1, 155 156 /// Default is zero for historical reasons. 157 Default_Pri = 0, 158 159 /// Serailization needs to occur before tick events also, so 160 /// that a serialize/unserialize is identical to an on-line 161 /// CPU switch. 162 Serialize_Pri = 32, 163 164 /// CPU ticks must come after other associated CPU events 165 /// (such as writebacks). 166 CPU_Tick_Pri = 50, 167 168 /// Statistics events (dump, reset, etc.) come after 169 /// everything else, but before exit. 170 Stat_Event_Pri = 90, 171 172 /// Progress events come at the end. 173 Progress_Event_Pri = 95, 174 175 /// If we want to exit on this cycle, it's the very last thing 176 /// we do.
| 131 /// If we enable tracing on a particular cycle, do that as the 132 /// very first thing so we don't miss any of the events on 133 /// that cycle (even if we enter the debugger). 134 Trace_Enable_Pri = -101, 135 136 /// Breakpoints should happen before anything else (except 137 /// enabling trace output), so we don't miss any action when 138 /// debugging. 139 Debug_Break_Pri = -100, 140 141 /// CPU switches schedule the new CPU's tick event for the 142 /// same cycle (after unscheduling the old CPU's tick event). 143 /// The switch needs to come before any tick events to make 144 /// sure we don't tick both CPUs in the same cycle. 145 CPU_Switch_Pri = -31, 146 147 /// For some reason "delayed" inter-cluster writebacks are 148 /// scheduled before regular writebacks (which have default 149 /// priority). Steve? 150 Delayed_Writeback_Pri = -1, 151 152 /// Default is zero for historical reasons. 153 Default_Pri = 0, 154 155 /// Serailization needs to occur before tick events also, so 156 /// that a serialize/unserialize is identical to an on-line 157 /// CPU switch. 158 Serialize_Pri = 32, 159 160 /// CPU ticks must come after other associated CPU events 161 /// (such as writebacks). 162 CPU_Tick_Pri = 50, 163 164 /// Statistics events (dump, reset, etc.) come after 165 /// everything else, but before exit. 166 Stat_Event_Pri = 90, 167 168 /// Progress events come at the end. 169 Progress_Event_Pri = 95, 170 171 /// If we want to exit on this cycle, it's the very last thing 172 /// we do.
|
177 Sim_Exit_Pri = 100
| 173 Sim_Exit_Pri = 100, 174 175 /// Maximum priority 176 Maximum_Pri = SHRT_MAX
|
178 }; 179 180 /* 181 * Event constructor 182 * @param queue that the event gets scheduled on 183 */ 184 Event(EventQueue *q, Priority p = Default_Pri)
| 177 }; 178 179 /* 180 * Event constructor 181 * @param queue that the event gets scheduled on 182 */ 183 Event(EventQueue *q, Priority p = Default_Pri)
|
185 : queue(q), next(NULL), _priority(p), _flags(None), 186#if TRACING_ON 187 when_created(curTick), when_scheduled(0), 188#endif 189 annotated_value(0)
| 184 : next(NULL), _queue(q), _priority(p), _flags(None)
|
190 { 191#ifndef NDEBUG
| 185 { 186#ifndef NDEBUG
|
192 instanceId = ++instanceCounter;
| 187 instance = ++instanceCounter;
|
193#endif
| 188#endif
|
| 189#ifdef EVENTQ_DEBUG 190 whenCreated = curTick; 191 whenScheduled = 0; 192#endif
|
194 } 195
| 193 } 194
|
196 ~Event() {}
| 195 virtual 196 ~Event() 197 { 198 }
|
197
| 199
|
198 virtual const std::string name() const {
| 200 virtual const std::string 201 name() const 202 {
|
199#ifndef NDEBUG
| 203#ifndef NDEBUG
|
200 return csprintf("Event_%d", instanceId);
| 204 return csprintf("Event_%d", instance);
|
201#else 202 return csprintf("Event_%x", (uintptr_t)this); 203#endif 204 } 205
| 205#else 206 return csprintf("Event_%x", (uintptr_t)this); 207#endif 208 } 209
|
206 /// Determine if the current event is scheduled 207 bool scheduled() const { return getFlags(Scheduled); } 208 209 /// Schedule the event with the current priority or default priority 210 void schedule(Tick t); 211 212 /// Reschedule the event with the current priority 213 // always parameter means to schedule if not already scheduled 214 void reschedule(Tick t, bool always = false); 215 216 /// Remove the event from the current schedule 217 void deschedule(); 218
| |
219 /// Return a C string describing the event. This string should 220 /// *not* be dynamically allocated; just a const char array 221 /// describing the event class. 222 virtual const char *description() const; 223 224 /// Dump the current event data
| 210 /// Return a C string describing the event. This string should 211 /// *not* be dynamically allocated; just a const char array 212 /// describing the event class. 213 virtual const char *description() const; 214 215 /// Dump the current event data
|
225 void dump();
| 216 void dump() const;
|
226
| 217
|
| 218 public:
|
227 /* 228 * This member function is invoked when the event is processed 229 * (occurs). There is no default implementation; each subclass 230 * must provide its own implementation. The event is not 231 * automatically deleted after it is processed (to allow for 232 * statically allocated event objects). 233 * 234 * If the AutoDestroy flag is set, the object is deleted once it 235 * is processed. 236 */ 237 virtual void process() = 0; 238
| 219 /* 220 * This member function is invoked when the event is processed 221 * (occurs). There is no default implementation; each subclass 222 * must provide its own implementation. The event is not 223 * automatically deleted after it is processed (to allow for 224 * statically allocated event objects). 225 * 226 * If the AutoDestroy flag is set, the object is deleted once it 227 * is processed. 228 */ 229 virtual void process() = 0; 230
|
239 void annotate(unsigned value) { annotated_value = value; }; 240 unsigned annotation() { return annotated_value; }
| 231 /// Determine if the current event is scheduled 232 bool scheduled() const { return getFlags(Scheduled); }
|
241
| 233
|
| 234 /// Schedule the event with the current priority or default priority 235 void schedule(Tick t); 236 237 /// Reschedule the event with the current priority 238 // always parameter means to schedule if not already scheduled 239 void reschedule(Tick t, bool always = false); 240 241 /// Remove the event from the current schedule 242 void deschedule(); 243
|
242 /// Squash the current event 243 void squash() { setFlags(Squashed); } 244 245 /// Check whether the event is squashed
| 244 /// Squash the current event 245 void squash() { setFlags(Squashed); } 246 247 /// Check whether the event is squashed
|
246 bool squashed() { return getFlags(Squashed); }
| 248 bool squashed() const { return getFlags(Squashed); }
|
247 248 /// See if this is a SimExitEvent (without resorting to RTTI)
| 249 250 /// See if this is a SimExitEvent (without resorting to RTTI)
|
249 bool isExitEvent() { return getFlags(IsExitEvent); }
| 251 bool isExitEvent() const { return getFlags(IsExitEvent); }
|
250 251 /// Get the time that the event is scheduled 252 Tick when() const { return _when; } 253 254 /// Get the event priority 255 int priority() const { return _priority; } 256
| 252 253 /// Get the time that the event is scheduled 254 Tick when() const { return _when; } 255 256 /// Get the event priority 257 int priority() const { return _priority; } 258
|
257 struct priority_compare : 258 public std::binary_function
| 259 struct priority_compare 260 : public std::binary_function<Event *, Event *, bool>
|
259 {
| 261 {
|
260 bool operator()(const Event *l, const Event *r) const {
| 262 bool 263 operator()(const Event *l, const Event *r) const 264 {
|
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}; 268 269template <class T, void (T::* F)()> 270void 271DelayFunction(Tick when, T *object) 272{ 273 class DelayEvent : public Event 274 { 275 private: 276 T *object; 277 278 public: 279 DelayEvent(Tick when, T *o) 280 : Event(&mainEventQueue), object(o) 281 { setFlags(this->AutoDestroy); schedule(when); } 282 void process() { (object->*F)(); } 283 const char *description() const { return "delay"; } 284 }; 285 286 new DelayEvent(when, object); 287} 288 289template <class T, void (T::* F)()> 290class EventWrapper : public Event 291{ 292 private: 293 T *object; 294 295 public: 296 EventWrapper(T *obj, bool del = false, 297 EventQueue *q = &mainEventQueue, 298 Priority p = Default_Pri) 299 : Event(q, p), object(obj) 300 { 301 if (del) 302 setFlags(AutoDelete); 303 } 304 305 EventWrapper(T *obj, Tick t, bool del = false, 306 EventQueue *q = &mainEventQueue, 307 Priority p = Default_Pri) 308 : Event(q, p), object(obj) 309 { 310 if (del) 311 setFlags(AutoDelete); 312 schedule(t); 313 } 314 315 void process() { (object->*F)(); } 316}; 317 318/* 319 * Queue of events sorted in time order 320 */ 321class EventQueue : public Serializable 322{ 323 protected: 324 std::string objName; 325 326 private: 327 Event *head; 328 329 void insert(Event *event); 330 void remove(Event *event); 331 332 public: 333 334 // constructor 335 EventQueue(const std::string &n) 336 : objName(n), head(NULL) 337 {} 338 339 virtual const std::string name() const { return objName; } 340 341 // schedule the given event on this queue 342 void schedule(Event *ev); 343 void deschedule(Event *ev); 344 void reschedule(Event *ev); 345
| 265 return l->when() >= r->when() || l->priority() >= r->priority(); 266 } 267 }; 268 269 virtual void serialize(std::ostream &os); 270 virtual void unserialize(Checkpoint *cp, const std::string §ion); 271}; 272 273template <class T, void (T::* F)()> 274void 275DelayFunction(Tick when, T *object) 276{ 277 class DelayEvent : public Event 278 { 279 private: 280 T *object; 281 282 public: 283 DelayEvent(Tick when, T *o) 284 : Event(&mainEventQueue), object(o) 285 { setFlags(this->AutoDestroy); schedule(when); } 286 void process() { (object->*F)(); } 287 const char *description() const { return "delay"; } 288 }; 289 290 new DelayEvent(when, object); 291} 292 293template <class T, void (T::* F)()> 294class EventWrapper : public Event 295{ 296 private: 297 T *object; 298 299 public: 300 EventWrapper(T *obj, bool del = false, 301 EventQueue *q = &mainEventQueue, 302 Priority p = Default_Pri) 303 : Event(q, p), object(obj) 304 { 305 if (del) 306 setFlags(AutoDelete); 307 } 308 309 EventWrapper(T *obj, Tick t, bool del = false, 310 EventQueue *q = &mainEventQueue, 311 Priority p = Default_Pri) 312 : Event(q, p), object(obj) 313 { 314 if (del) 315 setFlags(AutoDelete); 316 schedule(t); 317 } 318 319 void process() { (object->*F)(); } 320}; 321 322/* 323 * Queue of events sorted in time order 324 */ 325class EventQueue : public Serializable 326{ 327 protected: 328 std::string objName; 329 330 private: 331 Event *head; 332 333 void insert(Event *event); 334 void remove(Event *event); 335 336 public: 337 338 // constructor 339 EventQueue(const std::string &n) 340 : objName(n), head(NULL) 341 {} 342 343 virtual const std::string name() const { return objName; } 344 345 // schedule the given event on this queue 346 void schedule(Event *ev); 347 void deschedule(Event *ev); 348 void reschedule(Event *ev); 349
|
346 Tick nextTick() { return head->when(); }
| 350 Tick nextTick() const { return head->when(); }
|
347 Event *serviceOne(); 348 349 // process all events up to the given timestamp. we inline a 350 // quick test to see if there are any events to process; if so, 351 // call the internal out-of-line version to process them all.
| 351 Event *serviceOne(); 352 353 // process all events up to the given timestamp. we inline a 354 // quick test to see if there are any events to process; if so, 355 // call the internal out-of-line version to process them all.
|
352 void serviceEvents(Tick when) {
| 356 void 357 serviceEvents(Tick when) 358 {
|
353 while (!empty()) { 354 if (nextTick() > when) 355 break; 356 357 /** 358 * @todo this assert is a good bug catcher. I need to 359 * make it true again. 360 */ 361 //assert(head->when() >= when && "event scheduled in the past"); 362 serviceOne(); 363 } 364 } 365 366 // default: process all events up to 'now' (curTick) 367 void serviceEvents() { serviceEvents(curTick); } 368 369 // return true if no events are queued
| 359 while (!empty()) { 360 if (nextTick() > when) 361 break; 362 363 /** 364 * @todo this assert is a good bug catcher. I need to 365 * make it true again. 366 */ 367 //assert(head->when() >= when && "event scheduled in the past"); 368 serviceOne(); 369 } 370 } 371 372 // default: process all events up to 'now' (curTick) 373 void serviceEvents() { serviceEvents(curTick); } 374 375 // return true if no events are queued
|
370 bool empty() { return head == NULL; }
| 376 bool empty() const { return head == NULL; }
|
371
| 377
|
372 void dump();
| 378 void dump() const;
|
373 374 Tick nextEventTime() { return empty() ? curTick : head->when(); } 375 376 virtual void serialize(std::ostream &os); 377 virtual void unserialize(Checkpoint *cp, const std::string §ion); 378}; 379 380 381////////////////////// 382// 383// inline functions 384// 385// can't put these inside declaration due to circular dependence 386// between Event and EventQueue classes. 387// 388////////////////////// 389 390// schedule at specified time (place on event queue specified via 391// constructor) 392inline void 393Event::schedule(Tick t) 394{ 395 assert(!scheduled());
| 379 380 Tick nextEventTime() { return empty() ? curTick : head->when(); } 381 382 virtual void serialize(std::ostream &os); 383 virtual void unserialize(Checkpoint *cp, const std::string §ion); 384}; 385 386 387////////////////////// 388// 389// inline functions 390// 391// can't put these inside declaration due to circular dependence 392// between Event and EventQueue classes. 393// 394////////////////////// 395 396// schedule at specified time (place on event queue specified via 397// constructor) 398inline void 399Event::schedule(Tick t) 400{ 401 assert(!scheduled());
|
396// if (t < curTick) 397// warn("t is less than curTick, ensure you don't want cycles");
| 402 assert(t >= curTick);
|
398 399 setFlags(Scheduled);
| 403 404 setFlags(Scheduled);
|
400#if TRACING_ON 401 when_scheduled = curTick;
| 405#ifdef DEBUG_EVENTQ 406 whenScheduled = curTick;
|
402#endif 403 _when = t;
| 407#endif 408 _when = t;
|
404 queue->schedule(this);
| 409 _queue->schedule(this);
|
405} 406 407inline void 408Event::deschedule() 409{ 410 assert(scheduled()); 411 412 clearFlags(Squashed); 413 clearFlags(Scheduled);
| 410} 411 412inline void 413Event::deschedule() 414{ 415 assert(scheduled()); 416 417 clearFlags(Squashed); 418 clearFlags(Scheduled);
|
414 queue->deschedule(this);
| 419 _queue->deschedule(this);
|
415} 416 417inline void 418Event::reschedule(Tick t, bool always) 419{ 420 assert(scheduled() || always);
| 420} 421 422inline void 423Event::reschedule(Tick t, bool always) 424{ 425 assert(scheduled() || always);
|
| 426 assert(t >= curTick);
|
421
| 427
|
422#if TRACING_ON 423 when_scheduled = curTick;
| 428#ifdef DEBUG_EVENTQ 429 whenScheduled = curTick;
|
424#endif 425 _when = t; 426 427 if (scheduled()) { 428 clearFlags(Squashed);
| 430#endif 431 _when = t; 432 433 if (scheduled()) { 434 clearFlags(Squashed);
|
429 queue->reschedule(this);
| 435 _queue->reschedule(this);
|
430 } else { 431 setFlags(Scheduled);
| 436 } else { 437 setFlags(Scheduled);
|
432 queue->schedule(this);
| 438 _queue->schedule(this);
|
433 } 434} 435 436inline void 437EventQueue::schedule(Event *event) 438{ 439 insert(event); 440 if (DTRACE(Event)) 441 event->trace("scheduled"); 442} 443 444inline void 445EventQueue::deschedule(Event *event) 446{ 447 remove(event); 448 if (DTRACE(Event)) 449 event->trace("descheduled");
| 439 } 440} 441 442inline void 443EventQueue::schedule(Event *event) 444{ 445 insert(event); 446 if (DTRACE(Event)) 447 event->trace("scheduled"); 448} 449 450inline void 451EventQueue::deschedule(Event *event) 452{ 453 remove(event); 454 if (DTRACE(Event)) 455 event->trace("descheduled");
|
| 456 457 if (event->getFlags(Event::AutoDelete)) 458 delete event;
|
450} 451 452inline void 453EventQueue::reschedule(Event *event) 454{ 455 remove(event); 456 insert(event); 457 if (DTRACE(Event)) 458 event->trace("rescheduled"); 459} 460
| 459} 460 461inline void 462EventQueue::reschedule(Event *event) 463{ 464 remove(event); 465 insert(event); 466 if (DTRACE(Event)) 467 event->trace("rescheduled"); 468} 469
|
461 462
| |
463#endif // __SIM_EVENTQ_HH__
| 470#endif // __SIM_EVENTQ_HH__
|