eventq: Clean up the Event class so that it uses fewer bytes. This
authorNathan Binkert <nate@binkert.org>
Fri, 11 Jul 2008 04:35:42 +0000 (21:35 -0700)
committerNathan Binkert <nate@binkert.org>
Fri, 11 Jul 2008 04:35:42 +0000 (21:35 -0700)
will hopefullly allow it to fit in a cache line.

src/sim/eventq.cc
src/sim/eventq.hh
src/sim/sim_events.cc

index 2c679be1ee1d9a6d32d137122e727098f168b217..ab0ba938507b526130e87be9d5a43cd9dc7d9445 100644 (file)
  *          Steve Raasch
  */
 
-#include <assert.h>
-
+#include <cassert>
 #include <iostream>
 #include <string>
 #include <vector>
 
-#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 &section)
 }
 
 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");
     }
 }
index a454e5d64f884f3fce6853f753b0147670b895aa..ea950e625b0c002f56ae9e84a94de6eddab6304c 100644 (file)
 #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__
index 09087ef8428b7df46f55a3cee6708c0cf941ceb6..5fe59286c7f52bfec74a490b0c8aa0728f0ce674 100644 (file)
@@ -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;
     }