eventq.hh revision 270
11758SN/A/*
21762SN/A * Copyright (c) 2003 The Regents of The University of Michigan
31758SN/A * All rights reserved.
41758SN/A *
51758SN/A * Redistribution and use in source and binary forms, with or without
61758SN/A * modification, are permitted provided that the following conditions are
71758SN/A * met: redistributions of source code must retain the above copyright
81758SN/A * notice, this list of conditions and the following disclaimer;
91758SN/A * redistributions in binary form must reproduce the above copyright
101758SN/A * notice, this list of conditions and the following disclaimer in the
111758SN/A * documentation and/or other materials provided with the distribution;
121758SN/A * neither the name of the copyright holders nor the names of its
131758SN/A * contributors may be used to endorse or promote products derived from
141758SN/A * this software without specific prior written permission.
151758SN/A *
161758SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171758SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181758SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191758SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201758SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211758SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221758SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231758SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241758SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251758SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261758SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu */
282665Ssaidi@eecs.umich.edu
292665Ssaidi@eecs.umich.edu/* @file
301758SN/A * EventQueue interfaces
312SN/A */
322984Sgblack@eecs.umich.edu
33732SN/A#ifndef __EVENTQ_HH__
343565Sgblack@eecs.umich.edu#define __EVENTQ_HH__
35732SN/A
362984Sgblack@eecs.umich.edu#include <assert.h>
375953Ssaidi@eecs.umich.edu
385882Snate@binkert.org#include <algorithm>
391717SN/A#include <map>
402683Sktlim@umich.edu#include <string>
412680Sktlim@umich.edu#include <vector>
422710Sstever@eecs.umich.edu
432SN/A#include "sim/host.hh"	// for Tick
445568Snate@binkert.org
455566Snate@binkert.org#include "base/fast_alloc.hh"
4612406Sgabeblack@google.com#include "sim/serialize.hh"
4712406Sgabeblack@google.com#include "base/trace.hh"
4812406Sgabeblack@google.com
4912406Sgabeblack@google.comclass EventQueue;	// forward declaration
5012406Sgabeblack@google.com
5112406Sgabeblack@google.com/*
5212406Sgabeblack@google.com * An item on an event queue.  The action caused by a given
5312406Sgabeblack@google.com * event is specified by deriving a subclass and overriding the
5412406Sgabeblack@google.com * process() member function.
5512406Sgabeblack@google.com */
5612406Sgabeblack@google.comclass Event : public Serializeable, public FastAlloc
5712406Sgabeblack@google.com{
5812406Sgabeblack@google.com    friend class EventQueue;
5912406Sgabeblack@google.com
6012406Sgabeblack@google.com  private:
6112406Sgabeblack@google.com    /// queue to which this event belongs (though it may or may not be
6212406Sgabeblack@google.com    /// scheduled on this queue yet)
6312406Sgabeblack@google.com    EventQueue *queue;
642SN/A
652SN/A    Event *next;
662SN/A
672SN/A    Tick _when;	//!< timestamp when event should be processed
682SN/A    int _priority;	//!< event priority
695568Snate@binkert.org    char _flags;
702SN/A
712680Sktlim@umich.edu  protected:
72190SN/A    enum Flags {
732680Sktlim@umich.edu        None = 0x0,
742680Sktlim@umich.edu        Squashed = 0x1,
752114SN/A        Scheduled = 0x2,
765568Snate@binkert.org        AutoDelete = 0x4,
772700Sktlim@umich.edu        AutoSerialize = 0x8
787720Sgblack@eecs.umich.edu    };
792700Sktlim@umich.edu
802700Sktlim@umich.edu    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; }
831133SN/A
84716SN/A  protected:
855568Snate@binkert.org    EventQueue *theQueue() const { return queue; }
86716SN/A
87716SN/A#if TRACING_ON
88739SN/A    Tick when_created;	//!< Keep track of creation time For debugging
89739SN/A    Tick when_scheduled;	//!< Keep track of creation time For debugging
902683Sktlim@umich.edu
912683Sktlim@umich.edu    virtual void trace(const char *action);	//!< trace event activity
92716SN/A#else
93716SN/A    void trace(const char *) {}
944997Sgblack@eecs.umich.edu#endif
954997Sgblack@eecs.umich.edu
964997Sgblack@eecs.umich.edu    unsigned annotated_value;
974997Sgblack@eecs.umich.edu
984997Sgblack@eecs.umich.edu  public:
995568Snate@binkert.org
1004997Sgblack@eecs.umich.edu    /*
1014997Sgblack@eecs.umich.edu     * Event constructor
1024997Sgblack@eecs.umich.edu     * @param queue that the event gets scheduled on
1034997Sgblack@eecs.umich.edu     */
1044997Sgblack@eecs.umich.edu    Event(EventQueue *q, int p = 0)
1055568Snate@binkert.org        : queue(q), next(NULL), _priority(p), _flags(None),
1064997Sgblack@eecs.umich.edu#if TRACING_ON
1074997Sgblack@eecs.umich.edu          when_created(curTick), when_scheduled(0),
1084997Sgblack@eecs.umich.edu#endif
1094997Sgblack@eecs.umich.edu          annotated_value(0)
1105568Snate@binkert.org    {
1116330Sgblack@eecs.umich.edu    }
1122159SN/A
1135543Ssaidi@eecs.umich.edu    ~Event() {}
1142SN/A
1152SN/A    virtual std::string name() const {
1165568Snate@binkert.org        return csprintf("Event_%x", (uintptr_t)this);
1175568Snate@binkert.org    }
1185568Snate@binkert.org
1195568Snate@binkert.org    /// Determine if the current event is scheduled
1205568Snate@binkert.org    bool scheduled() const { return getFlags(Scheduled); }
1215568Snate@binkert.org
1225568Snate@binkert.org    /// Schedule the event with the current priority or default priority
1235568Snate@binkert.org    void schedule(Tick t);
1245568Snate@binkert.org
1255568Snate@binkert.org    /// Schedule the event with a specific priority
1265568Snate@binkert.org    void schedule(Tick t, int priority);
1275568Snate@binkert.org
1285568Snate@binkert.org    /// Reschedule the event with the current priority
1295568Snate@binkert.org    void reschedule(Tick t);
1305568Snate@binkert.org
1315568Snate@binkert.org    /// Reschedule the event with a specific priority
1325568Snate@binkert.org    void reschedule(Tick t, int priority);
1335568Snate@binkert.org
1345568Snate@binkert.org    /// Remove the event from the current schedule
1355568Snate@binkert.org    void deschedule();
1365568Snate@binkert.org
1375568Snate@binkert.org    /// Return a C string describing the event.  This string should
1385568Snate@binkert.org    /// *not* be dynamically allocated; just a const char array
1395568Snate@binkert.org    /// describing the event class.
1405568Snate@binkert.org    virtual const char *description();
1412SN/A
1425568Snate@binkert.org    /// Dump the current event data
1435568Snate@binkert.org    void dump();
1445568Snate@binkert.org
1455568Snate@binkert.org    /*
1465568Snate@binkert.org     * This member function is invoked when the event is processed
1475568Snate@binkert.org     * (occurs).  There is no default implementation; each subclass
1485568Snate@binkert.org     * must provide its own implementation.  The event is not
1495568Snate@binkert.org     * automatically deleted after it is processed (to allow for
1505568Snate@binkert.org     * statically allocated event objects).
1515568Snate@binkert.org     *
1525568Snate@binkert.org     * If the AutoDestroy flag is set, the object is deleted once it
1535568Snate@binkert.org     * is processed.
1545568Snate@binkert.org     */
1555568Snate@binkert.org    virtual void process() = 0;
1565568Snate@binkert.org
1575568Snate@binkert.org    void annotate(unsigned value) { annotated_value = value; };
1585568Snate@binkert.org    unsigned annotation() { return annotated_value; }
1592SN/A
1602SN/A    /// Squash the current event
1612SN/A    void squash() { setFlags(Squashed); }
1622SN/A
1635568Snate@binkert.org    /// Check whether the event is squashed
164597SN/A    bool squashed() { return getFlags(Squashed); }
1652680Sktlim@umich.edu
166597SN/A    /// Get the time that the event is scheduled
167597SN/A    Tick when() const { return _when; }
1685568Snate@binkert.org
1692SN/A    /// Get the event priority
1702SN/A    int priority() const { return _priority; }
1712SN/A
1725568Snate@binkert.org    struct priority_compare :
1735568Snate@binkert.org    public std::binary_function<Event *, Event *, bool>
1745568Snate@binkert.org    {
1755568Snate@binkert.org        bool operator()(const Event *l, const Event *r) const {
1765568Snate@binkert.org            return l->when() >= r->when() || l->priority() >= r->priority();
1772SN/A        }
1782SN/A    };
1792SN/A
1805568Snate@binkert.org    virtual void serialize(std::ostream &os);
1812SN/A    virtual void unserialize(Checkpoint *cp, const std::string &section);
18212406Sgabeblack@google.com};
1832SN/A
1845004Sgblack@eecs.umich.edutemplate <class T, void (T::* F)()>
1855004Sgblack@eecs.umich.eduvoid
1865004Sgblack@eecs.umich.eduDelayFunction(Tick when, T *object)
1875004Sgblack@eecs.umich.edu{
1885004Sgblack@eecs.umich.edu    class DelayEvent : public Event
1895004Sgblack@eecs.umich.edu    {
1905004Sgblack@eecs.umich.edu      private:
1912SN/A        T *object;
1922SN/A
1932SN/A      public:
1942SN/A        DelayEvent(Tick when, T *o)
1955568Snate@binkert.org            : Event(&mainEventQueue), object(o)
1965568Snate@binkert.org            { setFlags(AutoDestroy); schedule(when); }
1975568Snate@binkert.org        void process() { (object->*F)(); }
1985568Snate@binkert.org        const char *description() { return "delay"; }
1995568Snate@binkert.org    };
2005568Snate@binkert.org
2015568Snate@binkert.org    new DelayEvent(when, object);
2025568Snate@binkert.org}
2035568Snate@binkert.org
2043468Sgblack@eecs.umich.edu/*
2052SN/A * Queue of events sorted in time order
2062SN/A */
2072SN/Aclass EventQueue : public Serializeable
2082SN/A{
2093468Sgblack@eecs.umich.edu  protected:
2102SN/A    std::string objName;
2112SN/A
2122SN/A  private:
2132SN/A    Event *head;
2142SN/A
2152SN/A    void insert(Event *event);
2162SN/A    void remove(Event *event);
2172SN/A
2182SN/A  public:
2193468Sgblack@eecs.umich.edu
2206330Sgblack@eecs.umich.edu    // constructor
2212SN/A    EventQueue(const std::string &n)
2222SN/A        : objName(n), head(NULL)
2235568Snate@binkert.org    {}
2245568Snate@binkert.org
2255568Snate@binkert.org    virtual std::string name() const { return objName; }
2265568Snate@binkert.org
2275568Snate@binkert.org    // schedule the given event on this queue
2285568Snate@binkert.org    void schedule(Event *ev);
2295568Snate@binkert.org    void deschedule(Event *ev);
2305568Snate@binkert.org    void reschedule(Event *ev);
2315568Snate@binkert.org
2325568Snate@binkert.org    Tick nextTick() { return head->when(); }
2335568Snate@binkert.org    void serviceOne();
2345568Snate@binkert.org
2355568Snate@binkert.org    // process all events up to the given timestamp.  we inline a
2365568Snate@binkert.org    // quick test to see if there are any events to process; if so,
2375568Snate@binkert.org    // call the internal out-of-line version to process them all.
2385568Snate@binkert.org    void serviceEvents(Tick when) {
2395568Snate@binkert.org        while (!empty()) {
2405568Snate@binkert.org            if (nextTick() > when)
2415568Snate@binkert.org                break;
2425568Snate@binkert.org
2435568Snate@binkert.org            assert(head->when() >= when && "event scheduled in the past");
2445568Snate@binkert.org            serviceOne();
2455568Snate@binkert.org        }
2465568Snate@binkert.org    }
2475568Snate@binkert.org
2485568Snate@binkert.org    // default: process all events up to 'now' (curTick)
2495568Snate@binkert.org    void serviceEvents() { serviceEvents(curTick); }
2502SN/A
2512SN/A    // return true if no events are queued
2522SN/A    bool empty() { return head == NULL; }
2532SN/A
2545568Snate@binkert.org    void dump();
255596SN/A
256596SN/A    Tick nextEventTime() { return empty() ? curTick : head->when(); }
257596SN/A
258596SN/A    virtual void serialize(std::ostream &os);
259596SN/A    virtual void unserialize(Checkpoint *cp, const std::string &section);
260596SN/A};
2615568Snate@binkert.org
262596SN/A
263596SN/A//////////////////////
264596SN/A//
265596SN/A// inline functions
266596SN/A//
267596SN/A// can't put these inside declaration due to circular dependence
2685568Snate@binkert.org// between Event and EventQueue classes.
2692SN/A//
2702680Sktlim@umich.edu//////////////////////
2718607Sgblack@eecs.umich.edu
2728607Sgblack@eecs.umich.edu// schedule at specified time (place on event queue specified via
2732SN/A// constructor)
2742SN/Ainline void
2755568Snate@binkert.orgEvent::schedule(Tick t)
2762SN/A{
2772SN/A    assert(!scheduled());
2782SN/A    setFlags(Scheduled);
2792SN/A#if TRACING_ON
2805568Snate@binkert.org    when_scheduled = curTick;
2812SN/A#endif
2822SN/A    _when = t;
2832SN/A    queue->schedule(this);
2842SN/A}
2855568Snate@binkert.org
2865568Snate@binkert.orginline void
2872SN/AEvent::schedule(Tick t, int p)
2882SN/A{
2892SN/A    _priority = p;
2902SN/A    schedule(t);
2915568Snate@binkert.org}
2922SN/A
2932SN/Ainline void
2942680Sktlim@umich.eduEvent::deschedule()
2952680Sktlim@umich.edu{
2962SN/A    assert(scheduled());
2972SN/A
2985568Snate@binkert.org    clearFlags(Squashed);
2992330SN/A    clearFlags(Scheduled);
3002680Sktlim@umich.edu    queue->deschedule(this);
3015568Snate@binkert.org}
3022341SN/A
3032680Sktlim@umich.eduinline void
3045568Snate@binkert.orgEvent::reschedule(Tick t)
3052330SN/A{
3062SN/A    assert(scheduled());
3075568Snate@binkert.org    clearFlags(Squashed);
3082SN/A
3092SN/A#if TRACING_ON
3102SN/A    when_scheduled = curTick;
3112SN/A#endif
3125568Snate@binkert.org    _when = t;
3132SN/A    queue->reschedule(this);
3142SN/A}
3152SN/A
3162SN/Ainline void
3175568Snate@binkert.orgEvent::reschedule(Tick t, int p)
3182SN/A{
3192SN/A    _priority = p;
3202SN/A    reschedule(t);
3212SN/A}
3225568Snate@binkert.org
3232SN/Ainline void
3242SN/AEventQueue::schedule(Event *event)
3252SN/A{
3262SN/A    insert(event);
3275568Snate@binkert.org    if (DTRACE(Event))
3282SN/A        event->trace("scheduled");
3292SN/A}
3302SN/A
3315568Snate@binkert.orginline void
3325568Snate@binkert.orgEventQueue::deschedule(Event *event)
3332SN/A{
3342SN/A    remove(event);
3352SN/A    if (DTRACE(Event))
3365568Snate@binkert.org        event->trace("descheduled");
3372SN/A}
3382SN/A
3392SN/Ainline void
3405568Snate@binkert.orgEventQueue::reschedule(Event *event)
3415568Snate@binkert.org{
3422SN/A    remove(event);
3432SN/A    insert(event);
3442SN/A    if (DTRACE(Event))
3455568Snate@binkert.org        event->trace("rescheduled");
3462SN/A}
3472SN/A
3482SN/A
3495568Snate@binkert.org//////////////////////
3502SN/A//
3512SN/A// Main Event Queue
3522SN/A//
3535568Snate@binkert.org// Events on this queue are processed at the *beginning* of each
3545568Snate@binkert.org// cycle, before the pipeline simulation is performed.
3552SN/A//
3562SN/A// defined in eventq.cc
3572SN/A//
3582SN/A//////////////////////
3595568Snate@binkert.orgextern EventQueue mainEventQueue;
3605568Snate@binkert.org
3615568Snate@binkert.org#endif // __EVENTQ_HH__
3625568Snate@binkert.org