X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsim%2Feventq.hh;h=3869ca287163fd1f8b8d78adea1c85cd50c3e4e6;hb=edca5f7da6bad677dfc1ea69fff904554181cc17;hp=2db652b549c3d5aa6586bb056fa2855f1e5bcc3c;hpb=8291d9db0a0bdeecb2a13f28962893ed3659230e;p=gem5.git diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index 2db652b54..3869ca287 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -39,15 +39,15 @@ #include #include #include -#include +#include #include -#include #include "base/fast_alloc.hh" +#include "base/flags.hh" #include "base/misc.hh" #include "base/trace.hh" +#include "base/types.hh" #include "sim/serialize.hh" -#include "sim/host.hh" class EventQueue; // forward declaration @@ -64,6 +64,30 @@ class Event : public Serializable, public FastAlloc { friend class EventQueue; + protected: + typedef short FlagsType; + typedef ::Flags Flags; + + static const FlagsType PublicRead = 0x003f; // public readable flags + static const FlagsType PublicWrite = 0x001d; // public writable flags + static const FlagsType Squashed = 0x0001; // has been squashed + static const FlagsType Scheduled = 0x0002; // has been scheduled + static const FlagsType AutoDelete = 0x0004; // delete after dispatch + static const FlagsType AutoSerialize = 0x0008; // must be serialized + static const FlagsType IsExitEvent = 0x0010; // special exit event + static const FlagsType IsMainQueue = 0x0020; // on main event queue + static const FlagsType Initialized = 0x7a40; // somewhat random bits + static const FlagsType InitMask = 0xffc0; // mask for init bits + + bool + initialized() const + { + return this && (flags & InitMask) == Initialized; + } + + public: + typedef int8_t Priority; + private: // The event queue is now a linked list of linked lists. The // 'nextBin' pointer is to find the bin, where a bin is defined as @@ -81,8 +105,8 @@ class Event : public Serializable, public FastAlloc static Event *removeItem(Event *event, Event *last); Tick _when; //!< timestamp when event should be processed - short _priority; //!< event priority - short _flags; + Priority _priority; //!< event priority + Flags flags; #ifndef NDEBUG /// Global counter to generate unique IDs for Event instances @@ -117,21 +141,48 @@ class Event : public Serializable, public FastAlloc } protected: - enum Flags { - None = 0x0, - Squashed = 0x1, - Scheduled = 0x2, - AutoDelete = 0x4, - AutoSerialize = 0x8, - IsExitEvent = 0x10, - IsMainQueue = 0x20 - }; + /// Accessor for flags. + Flags + getFlags() const + { + return flags & PublicRead; + } - bool getFlags(Flags f) const { return (_flags & f) == f; } - void setFlags(Flags f) { _flags |= f; } - void clearFlags(Flags f) { _flags &= ~f; } + Flags + getFlags(Flags _flags) const + { + assert(_flags.noneSet(~PublicRead)); + return flags.isSet(_flags); + } + + Flags + allFlags(Flags _flags) const + { + assert(_flags.noneSet(~PublicRead)); + return flags.allSet(_flags); + } + + /// Accessor for flags. + void + setFlags(Flags _flags) + { + assert(_flags.noneSet(~PublicWrite)); + flags.set(_flags); + } + + void + clearFlags(Flags _flags) + { + assert(_flags.noneSet(~PublicWrite)); + flags.clear(_flags); + } + + void + clearFlags() + { + flags.clear(PublicWrite); + } - protected: // This function isn't really useful if TRACING_ON is not defined virtual void trace(const char *action); //!< trace event activity @@ -140,64 +191,63 @@ class Event : public Serializable, public FastAlloc /// 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). - Trace_Enable_Pri = -101, - - /// Breakpoints should happen before anything else (except - /// enabling trace output), so we don't miss any action when - /// debugging. - Debug_Break_Pri = -100, - - /// CPU switches schedule the new CPU's tick event for the - /// same cycle (after unscheduling the old CPU's tick event). - /// The switch needs to come before any tick events to make - /// sure we don't tick both CPUs in the same cycle. - CPU_Switch_Pri = -31, - - /// For some reason "delayed" inter-cluster writebacks are - /// scheduled before regular writebacks (which have default - /// priority). Steve? - Delayed_Writeback_Pri = -1, - - /// Default is zero for historical reasons. - Default_Pri = 0, - - /// Serailization needs to occur before tick events also, so - /// that a serialize/unserialize is identical to an on-line - /// CPU switch. - Serialize_Pri = 32, - - /// CPU ticks must come after other associated CPU events - /// (such as writebacks). - CPU_Tick_Pri = 50, - - /// Statistics events (dump, reset, etc.) come after - /// everything else, but before exit. - Stat_Event_Pri = 90, - - /// Progress events come at the end. - Progress_Event_Pri = 95, - - /// If we want to exit on this cycle, it's the very last thing - /// we do. - Sim_Exit_Pri = 100, - - /// Maximum priority - Maximum_Pri = SHRT_MAX - }; + + /// Minimum priority + static const Priority Minimum_Pri = SCHAR_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). + static const Priority Trace_Enable_Pri = -101; + + /// Breakpoints should happen before anything else (except + /// enabling trace output), so we don't miss any action when + /// debugging. + static const Priority Debug_Break_Pri = -100; + + /// CPU switches schedule the new CPU's tick event for the + /// same cycle (after unscheduling the old CPU's tick event). + /// The switch needs to come before any tick events to make + /// sure we don't tick both CPUs in the same cycle. + static const Priority CPU_Switch_Pri = -31; + + /// For some reason "delayed" inter-cluster writebacks are + /// scheduled before regular writebacks (which have default + /// priority). Steve? + static const Priority Delayed_Writeback_Pri = -1; + + /// Default is zero for historical reasons. + static const Priority Default_Pri = 0; + + /// Serailization needs to occur before tick events also, so + /// that a serialize/unserialize is identical to an on-line + /// CPU switch. + static const Priority Serialize_Pri = 32; + + /// CPU ticks must come after other associated CPU events + /// (such as writebacks). + static const Priority CPU_Tick_Pri = 50; + + /// Statistics events (dump, reset, etc.) come after + /// everything else, but before exit. + static const Priority Stat_Event_Pri = 90; + + /// Progress events come at the end. + static const Priority Progress_Event_Pri = 95; + + /// If we want to exit on this cycle, it's the very last thing + /// we do. + static const Priority Sim_Exit_Pri = 100; + + /// Maximum priority + static const Priority Maximum_Pri = SCHAR_MAX; /* * Event constructor * @param queue that the event gets scheduled on */ Event(Priority p = Default_Pri) - : nextBin(NULL), nextInBin(NULL), _priority(p), _flags(None) + : nextBin(NULL), nextInBin(NULL), _priority(p), flags(Initialized) { #ifndef NDEBUG instance = ++instanceCounter; @@ -209,20 +259,8 @@ class Event : public Serializable, public FastAlloc #endif } - virtual - ~Event() - { - } - - virtual const std::string - name() const - { -#ifndef NDEBUG - return csprintf("Event_%d", instance); -#else - return csprintf("Event_%x", (uintptr_t)this); -#endif - } + virtual ~Event(); + virtual const std::string name() const; /// Return a C string describing the event. This string should /// *not* be dynamically allocated; just a const char array @@ -246,22 +284,22 @@ class Event : public Serializable, public FastAlloc virtual void process() = 0; /// Determine if the current event is scheduled - bool scheduled() const { return getFlags(Scheduled); } + bool scheduled() const { return flags.isSet(Scheduled); } /// Squash the current event - void squash() { setFlags(Squashed); } + void squash() { flags.set(Squashed); } /// Check whether the event is squashed - bool squashed() const { return getFlags(Squashed); } + bool squashed() const { return flags.isSet(Squashed); } /// See if this is a SimExitEvent (without resorting to RTTI) - bool isExitEvent() const { return getFlags(IsExitEvent); } + bool isExitEvent() const { return flags.isSet(IsExitEvent); } /// Get the time that the event is scheduled Tick when() const { return _when; } /// Get the event priority - int priority() const { return _priority; } + Priority priority() const { return _priority; } #ifndef SWIG struct priority_compare @@ -279,6 +317,47 @@ class Event : public Serializable, public FastAlloc #endif }; +#ifndef SWIG +inline bool +operator<(const Event &l, const Event &r) +{ + return l.when() < r.when() || + (l.when() == r.when() && l.priority() < r.priority()); +} + +inline bool +operator>(const Event &l, const Event &r) +{ + return l.when() > r.when() || + (l.when() == r.when() && l.priority() > r.priority()); +} + +inline bool +operator<=(const Event &l, const Event &r) +{ + return l.when() < r.when() || + (l.when() == r.when() && l.priority() <= r.priority()); +} +inline bool +operator>=(const Event &l, const Event &r) +{ + return l.when() > r.when() || + (l.when() == r.when() && l.priority() >= r.priority()); +} + +inline bool +operator==(const Event &l, const Event &r) +{ + return l.when() == r.when() && l.priority() == r.priority(); +} + +inline bool +operator!=(const Event &l, const Event &r) +{ + return l.when() != r.when() || l.priority() != r.priority(); +} +#endif + /* * Queue of events sorted in time order */ @@ -291,17 +370,18 @@ class EventQueue : public Serializable void insert(Event *event); void remove(Event *event); + EventQueue(const EventQueue &); + const EventQueue &operator=(const EventQueue &); + public: - EventQueue(const std::string &n) - : objName(n), head(NULL) - {} + EventQueue(const std::string &n); virtual const std::string name() const { return objName; } // schedule the given event on this queue - void schedule(Event *ev, Tick when); - void deschedule(Event *ev); - void reschedule(Event *ev, Tick when, bool always = false); + void schedule(Event *event, Tick when); + void deschedule(Event *event); + void reschedule(Event *event, Tick when, bool always = false); Tick nextTick() const { return head->when(); } Event *serviceOne(); @@ -361,6 +441,11 @@ class EventManager return eventq; } + operator EventQueue *() const + { + return eventq; + } + void schedule(Event &event, Tick when) { @@ -398,56 +483,20 @@ class EventManager } }; -template -void -DelayFunction(EventQueue *eventq, Tick when, T *object) -{ - class DelayEvent : public Event - { - private: - T *object; - - public: - DelayEvent(T *o) - : object(o) - { setFlags(this->AutoDestroy); } - void process() { (object->*F)(); } - const char *description() const { return "delay"; } - }; - - eventq->schedule(new DelayEvent(object), when); -} - -template -class EventWrapper : public Event -{ - private: - T *object; - - public: - EventWrapper(T *obj, bool del = false, Priority p = Default_Pri) - : Event(p), object(obj) - { - if (del) - setFlags(AutoDelete); - } - - void process() { (object->*F)(); } -}; - inline void EventQueue::schedule(Event *event, Tick when) { - assert(when >= curTick); + assert((UTick)when >= (UTick)curTick); assert(!event->scheduled()); + assert(event->initialized()); event->setWhen(when, this); insert(event); - event->setFlags(Event::Scheduled); + event->flags.set(Event::Scheduled); if (this == &mainEventQueue) - event->setFlags(Event::IsMainQueue); + event->flags.set(Event::IsMainQueue); else - event->clearFlags(Event::IsMainQueue); + event->flags.clear(Event::IsMainQueue); if (DTRACE(Event)) event->trace("scheduled"); @@ -457,13 +506,14 @@ inline void EventQueue::deschedule(Event *event) { assert(event->scheduled()); + assert(event->initialized()); remove(event); - event->clearFlags(Event::Squashed); - event->clearFlags(Event::Scheduled); + event->flags.clear(Event::Squashed); + event->flags.clear(Event::Scheduled); - if (event->getFlags(Event::AutoDelete)) + if (event->flags.isSet(Event::AutoDelete)) delete event; if (DTRACE(Event)) @@ -475,61 +525,75 @@ EventQueue::reschedule(Event *event, Tick when, bool always) { assert(when >= curTick); assert(always || event->scheduled()); + assert(event->initialized()); if (event->scheduled()) remove(event); event->setWhen(when, this); insert(event); - event->clearFlags(Event::Squashed); - event->setFlags(Event::Scheduled); + event->flags.clear(Event::Squashed); + event->flags.set(Event::Scheduled); if (this == &mainEventQueue) - event->setFlags(Event::IsMainQueue); + event->flags.set(Event::IsMainQueue); else - event->clearFlags(Event::IsMainQueue); + event->flags.clear(Event::IsMainQueue); if (DTRACE(Event)) event->trace("rescheduled"); } -inline bool -operator<(const Event &l, const Event &r) +template +void +DelayFunction(EventQueue *eventq, Tick when, T *object) { - return l.when() < r.when() || - (l.when() == r.when() && l.priority() < r.priority()); -} + class DelayEvent : public Event + { + private: + T *object; -inline bool -operator>(const Event &l, const Event &r) -{ - return l.when() > r.when() || - (l.when() == r.when() && l.priority() > r.priority()); -} + public: + DelayEvent(T *o) + : object(o) + { this->setFlags(AutoDelete); } + void process() { (object->*F)(); } + const char *description() const { return "delay"; } + }; -inline bool -operator<=(const Event &l, const Event &r) -{ - return l.when() < r.when() || - (l.when() == r.when() && l.priority() <= r.priority()); -} -inline bool -operator>=(const Event &l, const Event &r) -{ - return l.when() > r.when() || - (l.when() == r.when() && l.priority() >= r.priority()); + eventq->schedule(new DelayEvent(object), when); } -inline bool -operator==(const Event &l, const Event &r) +template +class EventWrapper : public Event { - return l.when() == r.when() && l.priority() == r.priority(); -} + private: + T *object; -inline bool -operator!=(const Event &l, const Event &r) -{ - return l.when() != r.when() || l.priority() != r.priority(); -} + public: + EventWrapper(T *obj, bool del = false, Priority p = Default_Pri) + : Event(p), object(obj) + { + if (del) + setFlags(AutoDelete); + } + + EventWrapper(T &obj, bool del = false, Priority p = Default_Pri) + : Event(p), object(&obj) + { + if (del) + setFlags(AutoDelete); + } + + void process() { (object->*F)(); } + + const std::string + name() const + { + return object->name() + ".wrapped_event"; + } + + const char *description() const { return "EventWrapped"; } +}; #endif #endif // __SIM_EVENTQ_HH__