diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 2c679be1e..ab0ba9385 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -30,18 +30,16 @@ * Steve Raasch */ -#include - +#include #include #include #include -#include "cpu/smt.hh" #include "base/misc.hh" - -#include "sim/eventq.hh" #include "base/trace.hh" +#include "cpu/smt.hh" #include "sim/core.hh" +#include "sim/eventq.hh" using namespace std; @@ -203,7 +201,7 @@ EventQueue::unserialize(Checkpoint *cp, const std::string §ion) } void -EventQueue::dump() +EventQueue::dump() const { cprintf("============================================================\n"); cprintf("EventQueue Dump (cycle %d)\n", curTick); @@ -235,7 +233,6 @@ Event::description() const return "generic"; } -#if TRACING_ON void Event::trace(const char *action) { @@ -250,23 +247,21 @@ Event::trace(const char *action) // needs to be printed. DPRINTFN("%s event %s @ %d\n", description(), action, when()); } -#endif void -Event::dump() +Event::dump() const { - cprintf("Event (%s)\n", description()); + cprintf("Event %s (%s)\n", name(), description()); cprintf("Flags: %#x\n", _flags); -#if TRACING_ON - cprintf("Created: %d\n", when_created); +#ifdef EVENTQ_DEBUG + cprintf("Created: %d\n", whenCreated); #endif if (scheduled()) { -#if TRACING_ON - cprintf("Scheduled at %d\n", when_scheduled); +#ifdef EVENTQ_DEBUG + cprintf("Scheduled at %d\n", whenScheduled); #endif cprintf("Scheduled for %d, priority %d\n", when(), _priority); - } - else { + } else { cprintf("Not Scheduled\n"); } } 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 - #include +#include #include #include #include -#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,27 +181,53 @@ 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 } + /// 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() const; + + public: + /* + * This member function is invoked when the event is processed + * (occurs). There is no default implementation; each subclass + * must provide its own implementation. The event is not + * automatically deleted after it is processed (to allow for + * statically allocated event objects). + * + * If the AutoDestroy flag is set, the object is deleted once it + * is processed. + */ + virtual void process() = 0; + /// Determine if the current event is scheduled bool scheduled() const { return getFlags(Scheduled); } @@ -216,37 +241,14 @@ class Event : public Serializable, public FastAlloc /// 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(); - - /* - * This member function is invoked when the event is processed - * (occurs). There is no default implementation; each subclass - * must provide its own implementation. The event is not - * automatically deleted after it is processed (to allow for - * statically allocated event objects). - * - * If the AutoDestroy flag is set, the object is deleted once it - * is processed. - */ - virtual void process() = 0; - - void annotate(unsigned value) { annotated_value = value; }; - unsigned annotation() { return annotated_value; } - /// 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 + struct priority_compare + : public std::binary_function { - 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__ diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc index 09087ef84..5fe59286c 100644 --- a/src/sim/sim_events.cc +++ b/src/sim/sim_events.cc @@ -49,7 +49,7 @@ SimLoopExitEvent::process() // if this got scheduled on a different queue (e.g. the committed // instruction queue) then make a corresponding event on the main // queue. - if (theQueue() != &mainEventQueue) { + if (queue() != &mainEventQueue) { exitSimLoop(cause, code); delete this; }