eventq.hh revision 571
12SN/A/*
21762SN/A * Copyright (c) 2003 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272SN/A */
282SN/A
292439SN/A/* @file
30146SN/A * EventQueue interfaces
31146SN/A */
32146SN/A
33146SN/A#ifndef __EVENTQ_HH__
34146SN/A#define __EVENTQ_HH__
35146SN/A
361717SN/A#include <assert.h>
37146SN/A
381717SN/A#include <algorithm>
392190SN/A#include <map>
40146SN/A#include <string>
41146SN/A#include <vector>
421977SN/A
431717SN/A#include "sim/host.hh"	// for Tick
442623SN/A
451717SN/A#include "base/fast_alloc.hh"
46146SN/A#include "sim/serialize.hh"
471917SN/A#include "base/trace.hh"
482592SN/A
492036SN/Aclass EventQueue;	// forward declaration
50146SN/A
51146SN/A/*
5256SN/A * An item on an event queue.  The action caused by a given
5356SN/A * event is specified by deriving a subclass and overriding the
5456SN/A * process() member function.
55695SN/A */
562SN/Aclass Event : public Serializable, public FastAlloc
571858SN/A{
5856SN/A    friend class EventQueue;
59146SN/A
602171SN/A  private:
612170SN/A    /// queue to which this event belongs (though it may or may not be
622170SN/A    /// scheduled on this queue yet)
63146SN/A    EventQueue *queue;
642462SN/A
65146SN/A    Event *next;
662SN/A
672SN/A    Tick _when;	//!< timestamp when event should be processed
682449SN/A    int _priority;	//!< event priority
691355SN/A    char _flags;
702623SN/A
712623SN/A  protected:
72224SN/A    enum Flags {
731858SN/A        None = 0x0,
742518SN/A        Squashed = 0x1,
752420SN/A        Scheduled = 0x2,
762519SN/A        AutoDelete = 0x4,
772520SN/A        AutoSerialize = 0x8
782420SN/A    };
792SN/A
802190SN/A    bool getFlags(Flags f) const { return (_flags & f) == f; }
812SN/A    void setFlags(Flags f) { _flags |= f; }
822SN/A    void clearFlags(Flags f) { _flags &= ~f; }
83334SN/A
84140SN/A  protected:
85334SN/A    EventQueue *theQueue() const { return queue; }
862SN/A
872SN/A#if TRACING_ON
882SN/A    Tick when_created;	//!< Keep track of creation time For debugging
892190SN/A    Tick when_scheduled;	//!< Keep track of creation time For debugging
902SN/A
912SN/A    virtual void trace(const char *action);	//!< trace event activity
922623SN/A#else
932SN/A    void trace(const char *) {}
942SN/A#endif
952SN/A
96180SN/A    unsigned annotated_value;
972623SN/A
98393SN/A  public:
99393SN/A
100393SN/A    /// Event priorities, to provide tie-breakers for events scheduled
101393SN/A    /// at the same cycle.  Most events are scheduled at the default
102384SN/A    /// priority; these values are used to control events that need to
103384SN/A    /// be ordered within a cycle.
104393SN/A    enum Priority {
1052623SN/A        /// Breakpoints should happen before anything else, so we
106393SN/A        /// don't miss any action when debugging.
107393SN/A        Debug_Break_Pri		= -100,
108393SN/A
109393SN/A        /// For some reason "delayed" inter-cluster writebacks are
110384SN/A        /// scheduled before regular writebacks (which have default
111189SN/A        /// priority).  Steve?
112189SN/A        Delayed_Writeback_Pri	=   -1,
1132623SN/A
1142SN/A        /// Default is zero for historical reasons.
115729SN/A        Default_Pri		=    0,
116334SN/A
1172SN/A        /// CPU switches schedule the new CPU's tick event for the
1182SN/A        /// same cycle (after unscheduling the old CPU's tick event).
1192SN/A        /// The switch needs to come before any tick events to make
1202SN/A        /// sure we don't tick both CPUs in the same cycle.
1212SN/A        CPU_Switch_Pri		=   31,
1222SN/A
1232SN/A        /// Serailization needs to occur before tick events also, so
1242SN/A        /// that a serialize/unserialize is identical to an on-line
1252SN/A        /// CPU switch.
1262SN/A        Serialize_Pri		=   32,
1272SN/A
1282SN/A        /// CPU ticks must come after other associated CPU events
1291001SN/A        /// (such as writebacks).
1301001SN/A        CPU_Tick_Pri		=   50,
1311001SN/A
1321001SN/A        /// Statistics events (dump, reset, etc.) come after
1331001SN/A        /// everything else, but before exit.
1342SN/A        Stat_Event_Pri		=   90,
1352SN/A
1362SN/A        /// If we want to exit on this cycle, it's the very last thing
1372SN/A        /// we do.
1382SN/A        Sim_Exit_Pri		=  100
1392SN/A    };
1402SN/A
1412SN/A    /*
1422SN/A     * Event constructor
1432SN/A     * @param queue that the event gets scheduled on
1442SN/A     */
1452SN/A    Event(EventQueue *q, Priority p = Default_Pri)
1462SN/A        : queue(q), next(NULL), _priority(p), _flags(None),
1472SN/A#if TRACING_ON
1482SN/A          when_created(curTick), when_scheduled(0),
1492SN/A#endif
1502SN/A          annotated_value(0)
1512390SN/A    {
1522390SN/A    }
1532390SN/A
1542390SN/A    ~Event() {}
1552390SN/A
1562390SN/A    virtual const std::string name() const {
1572390SN/A        return csprintf("Event_%x", (uintptr_t)this);
1582390SN/A    }
1592390SN/A
1602390SN/A    /// Determine if the current event is scheduled
1612390SN/A    bool scheduled() const { return getFlags(Scheduled); }
1622390SN/A
163385SN/A    /// Schedule the event with the current priority or default priority
1642SN/A    void schedule(Tick t);
1652SN/A
1662SN/A    /// Reschedule the event with the current priority
1672623SN/A    void reschedule(Tick t);
168334SN/A
169334SN/A    /// Remove the event from the current schedule
1702623SN/A    void deschedule();
171334SN/A
172334SN/A    /// Return a C string describing the event.  This string should
173334SN/A    /// *not* be dynamically allocated; just a const char array
1742623SN/A    /// describing the event class.
1752SN/A    virtual const char *description();
176921SN/A
177224SN/A    /// Dump the current event data
178237SN/A    void dump();
1792190SN/A
1802SN/A    /*
1812SN/A     * This member function is invoked when the event is processed
1822SN/A     * (occurs).  There is no default implementation; each subclass
1832623SN/A     * must provide its own implementation.  The event is not
1842SN/A     * automatically deleted after it is processed (to allow for
185921SN/A     * statically allocated event objects).
186224SN/A     *
1872190SN/A     * If the AutoDestroy flag is set, the object is deleted once it
1882SN/A     * is processed.
1892SN/A     */
1902SN/A    virtual void process() = 0;
1912SN/A
1922SN/A    void annotate(unsigned value) { annotated_value = value; };
1932SN/A    unsigned annotation() { return annotated_value; }
1942SN/A
195595SN/A    /// Squash the current event
1962623SN/A    void squash() { setFlags(Squashed); }
197595SN/A
1982390SN/A    /// Check whether the event is squashed
1991080SN/A    bool squashed() { return getFlags(Squashed); }
2001080SN/A
2011080SN/A    /// Get the time that the event is scheduled
2021080SN/A    Tick when() const { return _when; }
2031080SN/A
2041080SN/A    /// Get the event priority
2051080SN/A    int priority() const { return _priority; }
2061121SN/A
2072107SN/A    struct priority_compare :
2081089SN/A    public std::binary_function<Event *, Event *, bool>
2091089SN/A    {
2101080SN/A        bool operator()(const Event *l, const Event *r) const {
2111080SN/A            return l->when() >= r->when() || l->priority() >= r->priority();
2121080SN/A        }
2131080SN/A    };
214595SN/A
2152623SN/A    virtual void serialize(std::ostream &os);
2162623SN/A    virtual void unserialize(Checkpoint *cp, const std::string &section);
217595SN/A};
2182090SN/A
2192190SN/Atemplate <class T, void (T::* F)()>
2202190SN/Avoid
221595SN/ADelayFunction(Tick when, T *object)
2222205SN/A{
2232205SN/A    class DelayEvent : public Event
2242190SN/A    {
2252190SN/A      private:
226595SN/A        T *object;
227595SN/A
2282390SN/A      public:
2292423SN/A        DelayEvent(Tick when, T *o)
2302390SN/A            : Event(&mainEventQueue), object(o)
231595SN/A            { setFlags(AutoDestroy); schedule(when); }
232595SN/A        void process() { (object->*F)(); }
233595SN/A        const char *description() { return "delay"; }
2342623SN/A    };
235595SN/A
2362390SN/A    new DelayEvent(when, object);
2371080SN/A}
238595SN/A
2391080SN/Atemplate <class T, void (T::* F)()>
2401080SN/Aclass EventWrapper : public Event
241595SN/A{
2422190SN/A  private:
2431080SN/A    T *object;
2441080SN/A
2451080SN/A  public:
2461121SN/A    EventWrapper(T *obj, EventQueue *q = &mainEventQueue,
2472107SN/A                 Priority p = Default_Pri)
2481089SN/A        : Event(q, p), object(obj)
2491080SN/A    {}
2501089SN/A    void process() { (object->*F)(); }
2511080SN/A};
2521080SN/A
2531080SN/A/*
254595SN/A * Queue of events sorted in time order
2552422SN/A */
2561080SN/Aclass EventQueue : public Serializable
2572090SN/A{
2581080SN/A  protected:
259595SN/A    std::string objName;
2602190SN/A
2612190SN/A  private:
262595SN/A    Event *head;
2632190SN/A
2641098SN/A    void insert(Event *event);
2651098SN/A    void remove(Event *event);
2661098SN/A
2672190SN/A  public:
2681098SN/A
2691098SN/A    // constructor
2701098SN/A    EventQueue(const std::string &n)
2712012SN/A        : objName(n), head(NULL)
2721098SN/A    {}
2731098SN/A
274595SN/A    virtual const std::string name() const { return objName; }
2752205SN/A
2762205SN/A    // schedule the given event on this queue
2772205SN/A    void schedule(Event *ev);
278595SN/A    void deschedule(Event *ev);
2792390SN/A    void reschedule(Event *ev);
2802420SN/A
2812423SN/A    Tick nextTick() { return head->when(); }
2822390SN/A    void serviceOne();
283595SN/A
284595SN/A    // process all events up to the given timestamp.  we inline a
2851858SN/A    // quick test to see if there are any events to process; if so,
2862SN/A    // call the internal out-of-line version to process them all.
2872623SN/A    void serviceEvents(Tick when) {
2882SN/A        while (!empty()) {
2892190SN/A            if (nextTick() > when)
2902SN/A                break;
2912SN/A
2922SN/A            assert(head->when() >= when && "event scheduled in the past");
2931858SN/A            serviceOne();
2942SN/A        }
2952623SN/A    }
2962SN/A
2972SN/A    // default: process all events up to 'now' (curTick)
2982SN/A    void serviceEvents() { serviceEvents(curTick); }
2992190SN/A
3002SN/A    // return true if no events are queued
3012190SN/A    bool empty() { return head == NULL; }
3022SN/A
3032SN/A    void dump();
3042SN/A
3052SN/A    Tick nextEventTime() { return empty() ? curTick : head->when(); }
3062SN/A
3072623SN/A    virtual void serialize(std::ostream &os);
3082SN/A    virtual void unserialize(Checkpoint *cp, const std::string &section);
3091858SN/A};
3102626SN/A
3112SN/A
3122SN/A//////////////////////
3131133SN/A//
3142SN/A// inline functions
3152190SN/A//
3162107SN/A// can't put these inside declaration due to circular dependence
3172107SN/A// between Event and EventQueue classes.
3182190SN/A//
3192SN/A//////////////////////
3202107SN/A
3212SN/A// schedule at specified time (place on event queue specified via
3222SN/A// constructor)
3232SN/Ainline void
3242SN/AEvent::schedule(Tick t)
3252SN/A{
3262190SN/A    assert(!scheduled());
3272107SN/A    setFlags(Scheduled);
3282107SN/A#if TRACING_ON
3292SN/A    when_scheduled = curTick;
3302SN/A#endif
3312SN/A    _when = t;
3322SN/A    queue->schedule(this);
3332SN/A}
3342SN/A
3352SN/Ainline void
3362190SN/AEvent::deschedule()
3372SN/A{
3382SN/A    assert(scheduled());
3392190SN/A
3402190SN/A    clearFlags(Squashed);
3412190SN/A    clearFlags(Scheduled);
3422234SN/A    queue->deschedule(this);
3432234SN/A}
3442SN/A
3452SN/Ainline void
3462190SN/AEvent::reschedule(Tick t)
3472SN/A{
3482SN/A    assert(scheduled());
3492SN/A    clearFlags(Squashed);
3502623SN/A
3512SN/A#if TRACING_ON
3522623SN/A    when_scheduled = curTick;
3532623SN/A#endif
3542623SN/A    _when = t;
3552623SN/A    queue->reschedule(this);
3562623SN/A}
3572623SN/A
3582623SN/Ainline void
3592623SN/AEventQueue::schedule(Event *event)
3602623SN/A{
3612623SN/A    insert(event);
3622623SN/A    if (DTRACE(Event))
3632623SN/A        event->trace("scheduled");
3642623SN/A}
3652623SN/A
3662623SN/Ainline void
3672623SN/AEventQueue::deschedule(Event *event)
3682623SN/A{
3692623SN/A    remove(event);
3702623SN/A    if (DTRACE(Event))
3712623SN/A        event->trace("descheduled");
3722623SN/A}
3732623SN/A
3742623SN/Ainline void
3752641Sstever@eecs.umich.eduEventQueue::reschedule(Event *event)
3762623SN/A{
3772623SN/A    remove(event);
3782623SN/A    insert(event);
3792623SN/A    if (DTRACE(Event))
3802623SN/A        event->trace("rescheduled");
3812623SN/A}
3822623SN/A
3832623SN/A
3842623SN/A//////////////////////
3852SN/A//
3862190SN/A// Main Event Queue
3872427SN/A//
3882455SN/A// Events on this queue are processed at the *beginning* of each
3892427SN/A// cycle, before the pipeline simulation is performed.
3902SN/A//
3912623SN/A// defined in eventq.cc
3922623SN/A//
3932623SN/A//////////////////////
3942SN/Aextern EventQueue mainEventQueue;
3952623SN/A
3962SN/A#endif // __EVENTQ_HH__
3972623SN/A