diff options
Diffstat (limited to 'src/sim/eventq.hh')
-rw-r--r-- | src/sim/eventq.hh | 157 |
1 files changed, 82 insertions, 75 deletions
diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index a454e5d64..ea950e625 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -36,19 +36,17 @@ #ifndef __SIM_EVENTQ_HH__ #define __SIM_EVENTQ_HH__ -#include <assert.h> - #include <algorithm> +#include <cassert> #include <map> #include <string> #include <vector> -#include "sim/host.hh" // for Tick - #include "base/fast_alloc.hh" #include "base/misc.hh" #include "base/trace.hh" #include "sim/serialize.hh" +#include "sim/host.hh" class EventQueue; // forward declaration @@ -64,17 +62,27 @@ class EventQueue; // forward declaration ////////////////////// extern EventQueue mainEventQueue; - /* * An item on an event queue. The action caused by a given * event is specified by deriving a subclass and overriding the * process() member function. + * + * Caution, the order of members is chosen to maximize data packing. */ class Event : public Serializable, public FastAlloc { friend class EventQueue; private: + Event *next; + + /// queue to which this event belongs (though it may or may not be + /// scheduled on this queue yet) + EventQueue *_queue; + + Tick _when; //!< timestamp when event should be processed + short _priority; //!< event priority + short _flags; #ifndef NDEBUG /// Global counter to generate unique IDs for Event instances @@ -84,19 +92,13 @@ class Event : public Serializable, public FastAlloc /// this but they're not consistent across runs making debugging /// more difficult. Thus we use a global counter value when /// debugging. - Counter instanceId; -#endif // NDEBUG - - /// queue to which this event belongs (though it may or may not be - /// scheduled on this queue yet) - EventQueue *queue; - - Event *next; - - Tick _when; //!< timestamp when event should be processed - int _priority; //!< event priority - char _flags; + Counter instance; +#endif +#ifdef DEBUG_EVENTQ + Tick whenCreated; //!< time created + Tick whenScheduled; //!< time scheduled +#endif protected: enum Flags { None = 0x0, @@ -112,26 +114,20 @@ class Event : public Serializable, public FastAlloc void clearFlags(Flags f) { _flags &= ~f; } protected: - EventQueue *theQueue() const { return queue; } - -#if TRACING_ON - Tick when_created; //!< Keep track of creation time For debugging - Tick when_scheduled; //!< Keep track of creation time For debugging + EventQueue *queue() const { return _queue; } + // This function isn't really useful if TRACING_ON is not defined virtual void trace(const char *action); //!< trace event activity -#else - void trace(const char *) {} -#endif - - unsigned annotated_value; public: - /// Event priorities, to provide tie-breakers for events scheduled /// at the same cycle. Most events are scheduled at the default /// priority; these values are used to control events that need to /// be ordered within a cycle. enum Priority { + /// Minimum priority + Minimum_Pri = SHRT_MIN, + /// If we enable tracing on a particular cycle, do that as the /// very first thing so we don't miss any of the events on /// that cycle (even if we enter the debugger). @@ -174,7 +170,10 @@ class Event : public Serializable, public FastAlloc /// If we want to exit on this cycle, it's the very last thing /// we do. - Sim_Exit_Pri = 100 + Sim_Exit_Pri = 100, + + /// Maximum priority + Maximum_Pri = SHRT_MAX }; /* @@ -182,48 +181,41 @@ class Event : public Serializable, public FastAlloc * @param queue that the event gets scheduled on */ Event(EventQueue *q, Priority p = Default_Pri) - : queue(q), next(NULL), _priority(p), _flags(None), -#if TRACING_ON - when_created(curTick), when_scheduled(0), -#endif - annotated_value(0) + : next(NULL), _queue(q), _priority(p), _flags(None) { #ifndef NDEBUG - instanceId = ++instanceCounter; + instance = ++instanceCounter; +#endif +#ifdef EVENTQ_DEBUG + whenCreated = curTick; + whenScheduled = 0; #endif } - ~Event() {} + virtual + ~Event() + { + } - virtual const std::string name() const { + virtual const std::string + name() const + { #ifndef NDEBUG - return csprintf("Event_%d", instanceId); + return csprintf("Event_%d", instance); #else return csprintf("Event_%x", (uintptr_t)this); #endif } - /// Determine if the current event is scheduled - bool scheduled() const { return getFlags(Scheduled); } - - /// Schedule the event with the current priority or default priority - void schedule(Tick t); - - /// Reschedule the event with the current priority - // always parameter means to schedule if not already scheduled - void reschedule(Tick t, bool always = false); - - /// Remove the event from the current schedule - void deschedule(); - /// Return a C string describing the event. This string should /// *not* be dynamically allocated; just a const char array /// describing the event class. virtual const char *description() const; /// Dump the current event data - void dump(); + void dump() const; + public: /* * This member function is invoked when the event is processed * (occurs). There is no default implementation; each subclass @@ -236,17 +228,27 @@ class Event : public Serializable, public FastAlloc */ virtual void process() = 0; - void annotate(unsigned value) { annotated_value = value; }; - unsigned annotation() { return annotated_value; } + /// Determine if the current event is scheduled + bool scheduled() const { return getFlags(Scheduled); } + + /// Schedule the event with the current priority or default priority + void schedule(Tick t); + + /// Reschedule the event with the current priority + // always parameter means to schedule if not already scheduled + void reschedule(Tick t, bool always = false); + + /// Remove the event from the current schedule + void deschedule(); /// Squash the current event void squash() { setFlags(Squashed); } /// Check whether the event is squashed - bool squashed() { return getFlags(Squashed); } + bool squashed() const { return getFlags(Squashed); } /// See if this is a SimExitEvent (without resorting to RTTI) - bool isExitEvent() { return getFlags(IsExitEvent); } + bool isExitEvent() const { return getFlags(IsExitEvent); } /// Get the time that the event is scheduled Tick when() const { return _when; } @@ -254,10 +256,12 @@ class Event : public Serializable, public FastAlloc /// Get the event priority int priority() const { return _priority; } - struct priority_compare : - public std::binary_function<Event *, Event *, bool> + struct priority_compare + : public std::binary_function<Event *, Event *, bool> { - bool operator()(const Event *l, const Event *r) const { + bool + operator()(const Event *l, const Event *r) const + { return l->when() >= r->when() || l->priority() >= r->priority(); } }; @@ -343,13 +347,15 @@ class EventQueue : public Serializable void deschedule(Event *ev); void reschedule(Event *ev); - Tick nextTick() { return head->when(); } + Tick nextTick() const { return head->when(); } Event *serviceOne(); // process all events up to the given timestamp. we inline a // quick test to see if there are any events to process; if so, // call the internal out-of-line version to process them all. - void serviceEvents(Tick when) { + void + serviceEvents(Tick when) + { while (!empty()) { if (nextTick() > when) break; @@ -367,9 +373,9 @@ class EventQueue : public Serializable void serviceEvents() { serviceEvents(curTick); } // return true if no events are queued - bool empty() { return head == NULL; } + bool empty() const { return head == NULL; } - void dump(); + void dump() const; Tick nextEventTime() { return empty() ? curTick : head->when(); } @@ -393,15 +399,14 @@ inline void Event::schedule(Tick t) { assert(!scheduled()); -// if (t < curTick) -// warn("t is less than curTick, ensure you don't want cycles"); + assert(t >= curTick); setFlags(Scheduled); -#if TRACING_ON - when_scheduled = curTick; +#ifdef DEBUG_EVENTQ + whenScheduled = curTick; #endif _when = t; - queue->schedule(this); + _queue->schedule(this); } inline void @@ -411,25 +416,26 @@ Event::deschedule() clearFlags(Squashed); clearFlags(Scheduled); - queue->deschedule(this); + _queue->deschedule(this); } inline void Event::reschedule(Tick t, bool always) { assert(scheduled() || always); + assert(t >= curTick); -#if TRACING_ON - when_scheduled = curTick; +#ifdef DEBUG_EVENTQ + whenScheduled = curTick; #endif _when = t; if (scheduled()) { clearFlags(Squashed); - queue->reschedule(this); + _queue->reschedule(this); } else { setFlags(Scheduled); - queue->schedule(this); + _queue->schedule(this); } } @@ -447,6 +453,9 @@ EventQueue::deschedule(Event *event) remove(event); if (DTRACE(Event)) event->trace("descheduled"); + + if (event->getFlags(Event::AutoDelete)) + delete event; } inline void @@ -458,6 +467,4 @@ EventQueue::reschedule(Event *event) event->trace("rescheduled"); } - - #endif // __SIM_EVENTQ_HH__ |