eventq.hh revision 237
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.
272665Ssaidi@eecs.umich.edu */
282665Ssaidi@eecs.umich.edu
292SN/A/* @file
302SN/A * EventQueue interfaces
312439SN/A */
322984Sgblack@eecs.umich.edu
33146SN/A#ifndef __EVENTQ_HH__
34146SN/A#define __EVENTQ_HH__
35146SN/A
36146SN/A#include <assert.h>
37146SN/A
38146SN/A#include <algorithm>
391717SN/A#include <map>
40146SN/A#include <string>
411717SN/A#include <vector>
42146SN/A
431977SN/A#include "sim/host.hh"	// for Tick
442623SN/A
452683Sktlim@umich.edu#include "base/fast_alloc.hh"
461717SN/A#include "sim/serialize.hh"
47146SN/A#include "base/trace.hh"
482683Sktlim@umich.edu
493348Sbinkertn@umich.educlass EventQueue;	// forward declaration
502683Sktlim@umich.edu
512036SN/A/*
52146SN/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.
5556SN/A */
56695SN/Aclass Event : public Serializeable, public FastAlloc
572901Ssaidi@eecs.umich.edu{
582SN/A    friend class EventQueue;
591858SN/A
603565Sgblack@eecs.umich.edu  private:
613565Sgblack@eecs.umich.edu    /// queue to which this event belongs (though it may or may not be
622171SN/A    /// scheduled on this queue yet)
632170SN/A    EventQueue *queue;
643562Sgblack@eecs.umich.edu
65146SN/A    Event *next;
662462SN/A
67146SN/A    Tick _when;	//!< timestamp when event should be processed
682SN/A    int _priority;	//!< event priority
692SN/A    char _flags;
702449SN/A
711355SN/A  protected:
722623SN/A    enum Flags {
733402Sktlim@umich.edu        None = 0x0,
74224SN/A        Squashed = 0x1,
751858SN/A        Scheduled = 0x2,
762683Sktlim@umich.edu        AutoDelete = 0x4,
772420SN/A        AutoSerialize = 0x8
782683Sktlim@umich.edu    };
793402Sktlim@umich.edu
802420SN/A    bool getFlags(Flags f) const { return (_flags & f) == f; }
812SN/A    void setFlags(Flags f) { _flags |= f; }
822683Sktlim@umich.edu    void clearFlags(Flags f) { _flags &= ~f; }
832672Sktlim@umich.edu
842683Sktlim@umich.edu  protected:
852SN/A    EventQueue *theQueue() const { return queue; }
862SN/A
87334SN/A#if TRACING_ON
88140SN/A    Tick when_created;	//!< Keep track of creation time For debugging
89334SN/A    Tick when_scheduled;	//!< Keep track of creation time For debugging
902SN/A
912SN/A    virtual void trace(const char *action);	//!< trace event activity
922SN/A#else
932680Sktlim@umich.edu    void trace(const char *) {}
942SN/A#endif
952SN/A
962623SN/A    unsigned annotated_value;
972SN/A
982SN/A  public:
992SN/A
100180SN/A    static const std::string defaultName;
1012623SN/A
102393SN/A    /*
103393SN/A     * Event constructor
104393SN/A     * @param queue that the event gets scheduled on
105393SN/A     */
106384SN/A    Event(EventQueue *q, int p = 0)
107384SN/A        : Serializeable(defaultName), queue(q), next(NULL),
108393SN/A          _priority(p), _flags(None),
1092623SN/A#if TRACING_ON
110393SN/A          when_created(curTick), when_scheduled(0),
111393SN/A#endif
112393SN/A          annotated_value(0)
113393SN/A    {
114384SN/A    }
115189SN/A
116189SN/A    /*
1172623SN/A     * Event constructor
1182SN/A     * @param queue that the event gets scheduled on
119729SN/A     */
120334SN/A    Event(EventQueue *q, std::string _name, int p = 0)
1212SN/A        : Serializeable(_name), queue(q), next(NULL),
1222SN/A          _priority(p), _flags(None),
1232SN/A#if TRACING_ON
1242SN/A          when_created(curTick), when_scheduled(0),
1252SN/A#endif
1262SN/A          annotated_value(0)
1272SN/A    {
1282SN/A    }
1292SN/A
1302SN/A    ~Event() {}
1312SN/A
1322SN/A    /// Determine if the current event is scheduled
1331001SN/A    bool scheduled() const { return getFlags(Scheduled); }
1341001SN/A
1351001SN/A    /// Schedule the event with the current priority or default priority
1361001SN/A    void schedule(Tick t);
1371001SN/A
1382SN/A    /// Schedule the event with a specific priority
1392SN/A    void schedule(Tick t, int priority);
1402SN/A
1412SN/A    /// Reschedule the event with the current priority
1422SN/A    void reschedule(Tick t);
1432SN/A
1442SN/A    /// Reschedule the event with a specific priority
1452SN/A    void reschedule(Tick t, int priority);
1462SN/A
1472SN/A    /// Remove the event from the current schedule
1482SN/A    void deschedule();
1492SN/A
1502SN/A    /// Return a C string describing the event.  This string should
1512SN/A    /// *not* be dynamically allocated; just a const char array
1522SN/A    /// describing the event class.
1532SN/A    virtual const char *description();
1542SN/A
1552390SN/A    /// Dump the current event data
1562390SN/A    void dump();
1572390SN/A
1582390SN/A    /*
1592390SN/A     * This member function is invoked when the event is processed
1602390SN/A     * (occurs).  There is no default implementation; each subclass
1612390SN/A     * must provide its own implementation.  The event is not
1622390SN/A     * automatically deleted after it is processed (to allow for
1632390SN/A     * statically allocated event objects).
1642390SN/A     *
1652390SN/A     * If the AutoDestroy flag is set, the object is deleted once it
1662390SN/A     * is processed.
167385SN/A     */
1682SN/A    virtual void process() = 0;
1692SN/A
1702SN/A    void annotate(unsigned value) { annotated_value = value; };
1712623SN/A    unsigned annotation() { return annotated_value; }
172334SN/A
1732361SN/A    /// Squash the current event
1742623SN/A    void squash() { setFlags(Squashed); }
175334SN/A
176334SN/A    /// Check whether the event is squashed
177334SN/A    bool squashed() { return getFlags(Squashed); }
1782623SN/A
1792SN/A    /// Get the time that the event is scheduled
180921SN/A    Tick when() const { return _when; }
1812915Sktlim@umich.edu
1822915Sktlim@umich.edu    /// Get the event priority
1832683Sktlim@umich.edu    int priority() const { return _priority; }
1842SN/A
1852SN/A    struct priority_compare :
1862SN/A    public std::binary_function<Event *, Event *, bool>
1872623SN/A    {
1882SN/A        bool operator()(const Event *l, const Event *r) const {
189921SN/A            return l->when() >= r->when() || l->priority() >= r->priority();
1902915Sktlim@umich.edu        }
1912915Sktlim@umich.edu    };
1922SN/A
1932SN/A    virtual void serialize(std::ostream &os);
1942SN/A    virtual void unserialize(Checkpoint *cp, const std::string &section);
1952SN/A};
1962SN/A
1972SN/Atemplate <class T, void (T::* F)()>
1982SN/Avoid
199595SN/ADelayFunction(Tick when, T *object)
2002623SN/A{
201595SN/A    class DelayEvent : public Event
2022390SN/A    {
2031080SN/A      private:
2041080SN/A        T *object;
2051080SN/A
2061080SN/A      public:
2071080SN/A        DelayEvent(Tick when, T *o)
2081080SN/A            : Event(&mainEventQueue), object(o)
2091080SN/A            { setFlags(AutoDestroy); schedule(when); }
2101121SN/A        void process() { (object->*F)(); }
2112107SN/A        const char *description() { return "delay"; }
2121089SN/A    };
2131089SN/A
2141080SN/A    new DelayEvent(when, object);
2151080SN/A}
2161080SN/A
2171080SN/A/*
218595SN/A * Queue of events sorted in time order
2192623SN/A */
2202683Sktlim@umich.educlass EventQueue : public Serializeable
221595SN/A{
2222090SN/A  private:
2232683Sktlim@umich.edu    Event *head;
2242683Sktlim@umich.edu
225595SN/A    // only used to hold value between nameChildren() and serialize()
2262205SN/A    int numAutoSerializeEvents;
2272205SN/A
2282683Sktlim@umich.edu    void insert(Event *event);
2292683Sktlim@umich.edu    void remove(Event *event);
230595SN/A
231595SN/A  public:
2322390SN/A
2332423SN/A    // constructor
2342390SN/A    EventQueue(const std::string &n)
235595SN/A        : Serializeable(n), head(NULL), numAutoSerializeEvents(-1)
236595SN/A    {}
237595SN/A
2382623SN/A    // schedule the given event on this queue
239595SN/A    void schedule(Event *ev);
2402390SN/A    void deschedule(Event *ev);
2411080SN/A    void reschedule(Event *ev);
242595SN/A
2431080SN/A    Tick nextTick() { return head->when(); }
2441080SN/A    void serviceOne();
245595SN/A
2462683Sktlim@umich.edu    // process all events up to the given timestamp.  we inline a
2471080SN/A    // quick test to see if there are any events to process; if so,
2481080SN/A    // call the internal out-of-line version to process them all.
2491080SN/A    void serviceEvents(Tick when) {
2501121SN/A        while (!empty()) {
2512107SN/A            if (nextTick() > when)
2521089SN/A                break;
2531080SN/A
2541089SN/A            assert(head->when() >= when && "event scheduled in the past");
2551080SN/A            serviceOne();
2561080SN/A        }
2571080SN/A    }
258595SN/A
2592683Sktlim@umich.edu    // default: process all events up to 'now' (curTick)
2601080SN/A    void serviceEvents() { serviceEvents(curTick); }
2612090SN/A
2621080SN/A    // return true if no events are queued
263595SN/A    bool empty() { return head == NULL; }
2642683Sktlim@umich.edu
2652683Sktlim@umich.edu    void dump();
266595SN/A
2672683Sktlim@umich.edu    Tick nextEventTime() { return empty() ? curTick : head->when(); }
2681098SN/A
2691098SN/A    virtual void nameChildren();
2701098SN/A    virtual void serialize(std::ostream &os);
2712683Sktlim@umich.edu    virtual void unserialize(Checkpoint *cp, const std::string &section);
2721098SN/A};
2731098SN/A
2741098SN/A
2752012SN/A//////////////////////
2761098SN/A//
2771098SN/A// inline functions
278595SN/A//
2792205SN/A// can't put these inside declaration due to circular dependence
2802205SN/A// between Event and EventQueue classes.
2812205SN/A//
282595SN/A//////////////////////
2832390SN/A
2842420SN/A// schedule at specified time (place on event queue specified via
2852423SN/A// constructor)
2862390SN/Ainline void
287595SN/AEvent::schedule(Tick t)
288595SN/A{
2891858SN/A    assert(!scheduled());
2902SN/A    setFlags(Scheduled);
2912623SN/A#if TRACING_ON
2922SN/A    when_scheduled = curTick;
2932680Sktlim@umich.edu#endif
2942SN/A    _when = t;
2952SN/A    queue->schedule(this);
2962SN/A}
2971858SN/A
2982SN/Ainline void
2992623SN/AEvent::schedule(Tick t, int p)
3002SN/A{
3012SN/A    _priority = p;
3022SN/A    schedule(t);
3032683Sktlim@umich.edu}
3042SN/A
3052683Sktlim@umich.eduinline void
3062SN/AEvent::deschedule()
3072SN/A{
3082SN/A    assert(scheduled());
3092SN/A
3102SN/A    clearFlags(Squashed);
3112623SN/A    clearFlags(Scheduled);
3122SN/A    queue->deschedule(this);
3131858SN/A}
3143521Sgblack@eecs.umich.edu
3153520Sgblack@eecs.umich.eduinline void
3162SN/AEvent::reschedule(Tick t)
3173520Sgblack@eecs.umich.edu{
3183521Sgblack@eecs.umich.edu    assert(scheduled());
3193520Sgblack@eecs.umich.edu    clearFlags(Squashed);
3202SN/A
3212SN/A#if TRACING_ON
3222SN/A    when_scheduled = curTick;
3232623SN/A#endif
3242SN/A    _when = t;
3252623SN/A    queue->reschedule(this);
3262623SN/A}
3272662Sstever@eecs.umich.edu
3282623SN/Ainline void
3292623SN/AEvent::reschedule(Tick t, int p)
3303093Sksewell@umich.edu{
3313093Sksewell@umich.edu    _priority = p;
3323093Sksewell@umich.edu    reschedule(t);
3333093Sksewell@umich.edu}
3342741Sksewell@umich.edu
3352741Sksewell@umich.eduinline void
3362741Sksewell@umich.eduEventQueue::schedule(Event *event)
3372623SN/A{
3382683Sktlim@umich.edu    insert(event);
3392683Sktlim@umich.edu    if (DTRACE(Event))
3402683Sktlim@umich.edu        event->trace("scheduled");
3412623SN/A}
3422683Sktlim@umich.edu
3432623SN/Ainline void
3442623SN/AEventQueue::deschedule(Event *event)
3452623SN/A{
3462623SN/A    remove(event);
3472623SN/A    if (DTRACE(Event))
3482623SN/A        event->trace("descheduled");
3492623SN/A}
3502623SN/A
3512SN/Ainline void
3522683Sktlim@umich.eduEventQueue::reschedule(Event *event)
3532427SN/A{
3542683Sktlim@umich.edu    remove(event);
3552427SN/A    insert(event);
3562SN/A    if (DTRACE(Event))
3572623SN/A        event->trace("rescheduled");
3582623SN/A}
3592623SN/A
3602SN/A
3612683Sktlim@umich.edu//////////////////////
3622SN/A//
3632623SN/A// Main Event Queue
3642623SN/A//
3652SN/A// Events on this queue are processed at the *beginning* of each
3662623SN/A// cycle, before the pipeline simulation is performed.
3672623SN/A//
3683276Sgblack@eecs.umich.edu// defined in eventq.cc
3693276Sgblack@eecs.umich.edu//
3703484Sktlim@umich.edu//////////////////////
3713484Sktlim@umich.eduextern EventQueue mainEventQueue;
3723484Sktlim@umich.edu
3733276Sgblack@eecs.umich.edu#endif // __EVENTQ_HH__
3743521Sgblack@eecs.umich.edu