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; --- 22 unchanged lines hidden (view full) --- 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 <map> 42#include <string> 43#include <vector> 44 |
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" |
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 |
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. |
71 */ 72class Event : public Serializable, public FastAlloc 73{ 74 friend class EventQueue; 75 76 private: |
77 Event *next; |
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 |
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#endif |
97 |
98#ifdef DEBUG_EVENTQ 99 Tick whenCreated; //!< time created 100 Tick whenScheduled; //!< time scheduled 101#endif |
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: |
117 EventQueue *queue() const { return _queue; } |
118 |
119 // This function isn't really useful if TRACING_ON is not defined |
120 virtual void trace(const char *action); //!< trace event activity |
121 |
122 public: |
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 |
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. --- 26 unchanged lines hidden (view full) --- 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. |
173 Sim_Exit_Pri = 100, 174 175 /// Maximum priority 176 Maximum_Pri = SHRT_MAX |
177 }; 178 179 /* 180 * Event constructor 181 * @param queue that the event gets scheduled on 182 */ 183 Event(EventQueue *q, Priority p = Default_Pri) |
184 : next(NULL), _queue(q), _priority(p), _flags(None) |
185 { 186#ifndef NDEBUG |
187 instance = ++instanceCounter; |
188#endif |
189#ifdef EVENTQ_DEBUG 190 whenCreated = curTick; 191 whenScheduled = 0; 192#endif |
193 } 194 |
195 virtual 196 ~Event() 197 { 198 } |
199 |
200 virtual const std::string 201 name() const 202 { |
203#ifndef NDEBUG |
204 return csprintf("Event_%d", instance); |
205#else 206 return csprintf("Event_%x", (uintptr_t)this); 207#endif 208 } 209 |
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 |
216 void dump() const; |
217 |
218 public: |
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 |
231 /// Determine if the current event is scheduled 232 bool scheduled() const { return getFlags(Scheduled); } |
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 |
244 /// Squash the current event 245 void squash() { setFlags(Squashed); } 246 247 /// Check whether the event is squashed |
248 bool squashed() const { return getFlags(Squashed); } |
249 250 /// See if this is a SimExitEvent (without resorting to RTTI) |
251 bool isExitEvent() const { return getFlags(IsExitEvent); } |
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 |
259 struct priority_compare 260 : public std::binary_function<Event *, Event *, bool> |
261 { |
262 bool 263 operator()(const Event *l, const Event *r) const 264 { |
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 --- 69 unchanged lines hidden (view full) --- 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 |
350 Tick nextTick() const { return head->when(); } |
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. |
356 void 357 serviceEvents(Tick when) 358 { |
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 |
376 bool empty() const { return head == NULL; } |
377 |
378 void dump() const; |
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 --- 7 unchanged lines hidden (view full) --- 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()); |
402 assert(t >= curTick); |
403 404 setFlags(Scheduled); |
405#ifdef DEBUG_EVENTQ 406 whenScheduled = curTick; |
407#endif 408 _when = t; |
409 _queue->schedule(this); |
410} 411 412inline void 413Event::deschedule() 414{ 415 assert(scheduled()); 416 417 clearFlags(Squashed); 418 clearFlags(Scheduled); |
419 _queue->deschedule(this); |
420} 421 422inline void 423Event::reschedule(Tick t, bool always) 424{ 425 assert(scheduled() || always); |
426 assert(t >= curTick); |
427 |
428#ifdef DEBUG_EVENTQ 429 whenScheduled = curTick; |
430#endif 431 _when = t; 432 433 if (scheduled()) { 434 clearFlags(Squashed); |
435 _queue->reschedule(this); |
436 } else { 437 setFlags(Scheduled); |
438 _queue->schedule(this); |
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; |
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 |
470#endif // __SIM_EVENTQ_HH__ |