eventq.hh revision 224
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 Serializeable, 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    };
782420SN/A
792SN/A    bool getFlags(Flags f) const { return (_flags & f) == f; }
802190SN/A    void setFlags(Flags f) { _flags |= f; }
812SN/A    void clearFlags(Flags f) { _flags &= ~f; }
822SN/A
83334SN/A  protected:
84140SN/A    EventQueue *theQueue() const { return queue; }
85334SN/A
862SN/A#if TRACING_ON
872SN/A    Tick when_created;	//!< Keep track of creation time For debugging
882SN/A    Tick when_scheduled;	//!< Keep track of creation time For debugging
892190SN/A
902SN/A    virtual void trace(const char *action);	//!< trace event activity
912SN/A#else
922623SN/A    void trace(const char *) {}
932SN/A#endif
942SN/A
952SN/A    unsigned annotated_value;
96180SN/A
972623SN/A  public:
98393SN/A
99393SN/A    static const std::string defaultName;
100393SN/A
101393SN/A    /*
102384SN/A     * Event constructor
103384SN/A     * @param queue that the event gets scheduled on
104393SN/A     */
1052623SN/A    Event(EventQueue *q, int p = 0)
106393SN/A        : Serializeable(defaultName), queue(q), next(NULL),
107393SN/A          _priority(p), _flags(None),
108393SN/A#if TRACING_ON
109393SN/A          when_created(curTick), when_scheduled(0),
110384SN/A#endif
111189SN/A          annotated_value(0)
112189SN/A    {
1132623SN/A    }
1142SN/A
115729SN/A    /*
116334SN/A     * Event constructor
1172SN/A     * @param queue that the event gets scheduled on
1182SN/A     */
1192SN/A    Event(EventQueue *q, std::string _name, int p = 0)
1202SN/A        : Serializeable(_name), queue(q), next(NULL),
1212SN/A          _priority(p), _flags(None),
1222SN/A#if TRACING_ON
1232SN/A          when_created(curTick), when_scheduled(0),
1242SN/A#endif
1252SN/A          annotated_value(0)
1262SN/A    {
1272SN/A    }
1282SN/A
1291001SN/A    ~Event() {}
1301001SN/A
1311001SN/A    /// Determine if the current event is scheduled
1321001SN/A    bool scheduled() const { return getFlags(Scheduled); }
1331001SN/A
1342SN/A    /// Schedule the event with the current priority or default priority
1352SN/A    void schedule(Tick t);
1362SN/A
1372SN/A    /// Schedule the event with a specific priority
1382SN/A    void schedule(Tick t, int priority);
1392SN/A
1402SN/A    /// Reschedule the event with the current priority
1412SN/A    void reschedule(Tick t);
1422SN/A
1432SN/A    /// Reschedule the event with a specific priority
1442SN/A    void reschedule(Tick t, int priority);
1452SN/A
1462SN/A    /// Remove the event from the current schedule
1472SN/A    void deschedule();
1482SN/A
1492SN/A    /// Return a C string describing the event.  This string should
1502SN/A    /// *not* be dynamically allocated; just a const char array
1512390SN/A    /// describing the event class.
1522390SN/A    virtual const char *description();
1532390SN/A
1542390SN/A    /// Dump the current event data
1552390SN/A    void dump();
1562390SN/A
1572390SN/A    /*
1582390SN/A     * This member function is invoked when the event is processed
1592390SN/A     * (occurs).  There is no default implementation; each subclass
1602390SN/A     * must provide its own implementation.  The event is not
1612390SN/A     * automatically deleted after it is processed (to allow for
1622390SN/A     * statically allocated event objects).
163385SN/A     *
1642SN/A     * If the AutoDestroy flag is set, the object is deleted once it
1652SN/A     * is processed.
1662SN/A     */
1672623SN/A    virtual void process() = 0;
168334SN/A
169334SN/A    void annotate(unsigned value) { annotated_value = value; };
1702623SN/A    unsigned annotation() { return annotated_value; }
171334SN/A
172334SN/A    /// Squash the current event
173334SN/A    void squash() { setFlags(Squashed); }
1742623SN/A
1752SN/A    /// Check whether the event is squashed
176921SN/A    bool squashed() { return getFlags(Squashed); }
177224SN/A
178237SN/A    /// Get the time that the event is scheduled
1792190SN/A    Tick when() const { return _when; }
1802SN/A
1812SN/A    /// Get the event priority
1822SN/A    int priority() const { return _priority; }
1832623SN/A
1842SN/A    struct priority_compare :
185921SN/A    public std::binary_function<Event *, Event *, bool>
186224SN/A    {
1872190SN/A        bool operator()(const Event *l, const Event *r) const {
1882SN/A            return l->when() >= r->when() || l->priority() >= r->priority();
1892SN/A        }
1902SN/A    };
1912SN/A
1922SN/A    virtual void serialize(std::ostream &os);
1932SN/A    virtual void unserialize(const IniFile *db, const std::string &section);
1942SN/A};
195595SN/A
1962623SN/Atemplate <class T, void (T::* F)()>
197595SN/Avoid
1982390SN/ADelayFunction(Tick when, T *object)
1991080SN/A{
2001080SN/A    class DelayEvent : public Event
2011080SN/A    {
2021080SN/A      private:
2031080SN/A        T *object;
2041080SN/A
2051080SN/A      public:
2061121SN/A        DelayEvent(Tick when, T *o)
2072107SN/A            : Event(&mainEventQueue), object(o)
2081089SN/A            { setFlags(AutoDestroy); schedule(when); }
2091089SN/A        void process() { (object->*F)(); }
2101080SN/A        const char *description() { return "delay"; }
2111080SN/A    };
2121080SN/A
2131080SN/A    new DelayEvent(when, object);
214595SN/A}
2152623SN/A
2162623SN/A/*
217595SN/A * Queue of events sorted in time order
2182090SN/A */
2192190SN/Aclass EventQueue : public Serializeable
2202190SN/A{
221595SN/A  private:
2222205SN/A    Event *head;
2232205SN/A
2242190SN/A    void insert(Event *event);
2252190SN/A    void remove(Event *event);
226595SN/A
227595SN/A  public:
2282390SN/A
2292423SN/A    // constructor
2302390SN/A    EventQueue(const std::string &n)
231595SN/A        : Serializeable(n), head(NULL)
232595SN/A    {}
233595SN/A
2342623SN/A    // schedule the given event on this queue
235595SN/A    void schedule(Event *ev);
2362390SN/A    void deschedule(Event *ev);
2371080SN/A    void reschedule(Event *ev);
238595SN/A
2391080SN/A    Tick nextTick() { return head->when(); }
2401080SN/A    void serviceOne();
241595SN/A
2422190SN/A    // process all events up to the given timestamp.  we inline a
2431080SN/A    // quick test to see if there are any events to process; if so,
2441080SN/A    // call the internal out-of-line version to process them all.
2451080SN/A    void serviceEvents(Tick when) {
2461121SN/A        while (!empty()) {
2472107SN/A            if (nextTick() > when)
2481089SN/A                break;
2491080SN/A
2501089SN/A            assert(head->when() >= when && "event scheduled in the past");
2511080SN/A            serviceOne();
2521080SN/A        }
2531080SN/A    }
254595SN/A
2552422SN/A    // default: process all events up to 'now' (curTick)
2561080SN/A    void serviceEvents() { serviceEvents(curTick); }
2572090SN/A
2581080SN/A    // return true if no events are queued
259595SN/A    bool empty() { return head == NULL; }
2602190SN/A
2612190SN/A    void dump();
262595SN/A
2632190SN/A    Tick nextEventTime() { return empty() ? curTick : head->when(); }
2641098SN/A
2651098SN/A    virtual void nameChildren();
2661098SN/A    virtual void serialize(std::ostream &os);
2672190SN/A};
2681098SN/A
2691098SN/A
2701098SN/A//////////////////////
2712012SN/A//
2721098SN/A// inline functions
2731098SN/A//
274595SN/A// can't put these inside declaration due to circular dependence
2752205SN/A// between Event and EventQueue classes.
2762205SN/A//
2772205SN/A//////////////////////
278595SN/A
2792390SN/A// schedule at specified time (place on event queue specified via
2802420SN/A// constructor)
2812423SN/Ainline void
2822390SN/AEvent::schedule(Tick t)
283595SN/A{
284595SN/A    assert(!scheduled());
2851858SN/A    setFlags(Scheduled);
2862SN/A#if TRACING_ON
2872623SN/A    when_scheduled = curTick;
2882SN/A#endif
2892190SN/A    _when = t;
2902SN/A    queue->schedule(this);
2912SN/A}
2922SN/A
2931858SN/Ainline void
2942SN/AEvent::schedule(Tick t, int p)
2952623SN/A{
2962SN/A    _priority = p;
2972SN/A    schedule(t);
2982SN/A}
2992190SN/A
3002SN/Ainline void
3012190SN/AEvent::deschedule()
3022SN/A{
3032SN/A    assert(scheduled());
3042SN/A
3052SN/A    clearFlags(Squashed);
3062SN/A    clearFlags(Scheduled);
3072623SN/A    queue->deschedule(this);
3082SN/A}
3091858SN/A
3102626SN/Ainline void
3112SN/AEvent::reschedule(Tick t)
3122SN/A{
3131133SN/A    assert(scheduled());
3142SN/A    clearFlags(Squashed);
3152190SN/A
3162107SN/A#if TRACING_ON
3172107SN/A    when_scheduled = curTick;
3182190SN/A#endif
3192SN/A    _when = t;
3202107SN/A    queue->reschedule(this);
3212SN/A}
3222SN/A
3232SN/Ainline void
3242SN/AEvent::reschedule(Tick t, int p)
3252SN/A{
3262190SN/A    _priority = p;
3272107SN/A    reschedule(t);
3282107SN/A}
3292SN/A
3302SN/Ainline void
3312SN/AEventQueue::schedule(Event *event)
3322SN/A{
3332SN/A    insert(event);
3342SN/A    if (DTRACE(Event))
3352SN/A        event->trace("scheduled");
3362190SN/A}
3372SN/A
3382SN/Ainline void
3392190SN/AEventQueue::deschedule(Event *event)
3402190SN/A{
3412190SN/A    remove(event);
3422234SN/A    if (DTRACE(Event))
3432234SN/A        event->trace("descheduled");
3442SN/A}
3452SN/A
3462190SN/Ainline void
3472SN/AEventQueue::reschedule(Event *event)
3482SN/A{
3492SN/A    remove(event);
3502623SN/A    insert(event);
3512SN/A    if (DTRACE(Event))
3522623SN/A        event->trace("rescheduled");
3532623SN/A}
3542662Sstever@eecs.umich.edu
3552623SN/A
3562623SN/A//////////////////////
3572623SN/A//
3582623SN/A// Main Event Queue
3592623SN/A//
3602662Sstever@eecs.umich.edu// Events on this queue are processed at the *beginning* of each
3612662Sstever@eecs.umich.edu// cycle, before the pipeline simulation is performed.
3622623SN/A//
3632662Sstever@eecs.umich.edu// defined in eventq.cc
3642623SN/A//
3652662Sstever@eecs.umich.edu//////////////////////
3662623SN/Aextern EventQueue mainEventQueue;
3672623SN/A
3682662Sstever@eecs.umich.edu#endif // __EVENTQ_HH__
3692623SN/A