eventq.hh revision 56
16019SN/A/*
26019SN/A * Copyright (c) 2003 The Regents of The University of Michigan
310037SARM gem5 Developers * All rights reserved.
47134Sgblack@eecs.umich.edu *
57134Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67134Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77134Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87134Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97134Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107134Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117134Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127134Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137134Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147134Sgblack@eecs.umich.edu * this software without specific prior written permission.
156019SN/A *
166019SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176019SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186019SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196019SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206019SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216019SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226019SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236019SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246019SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256019SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266019SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276019SN/A */
286019SN/A
296019SN/A/* @file
306019SN/A * EventQueue interfaces
316019SN/A */
326019SN/A
336019SN/A#ifndef __EVENTQ_HH__
346019SN/A#define __EVENTQ_HH__
356019SN/A
366019SN/A#include <assert.h>
376019SN/A
386019SN/A#include <algorithm>
396019SN/A#include <map>
406019SN/A#include <string>
416019SN/A#include <vector>
426308SN/A
436308SN/A#include "sim/host.hh"	// for Tick
446309SN/A
456309SN/A#include "base/fast_alloc.hh"
466309SN/A#include "sim/serialize.hh"
476309SN/A#include "base/trace.hh"
486309SN/A
497134Sgblack@eecs.umich.educlass EventQueue;	// forward declaration
508588Sgblack@eecs.umich.edu
516309SN/A/*
526309SN/A * An item on an event queue.  The action caused by a given
537296Sgblack@eecs.umich.edu * event is specified by deriving a subclass and overriding the
548139SMatt.Horsnell@arm.com * process() member function.
556309SN/A */
566309SN/Aclass Event : public Serializeable, public FastAlloc
576309SN/A{
588588Sgblack@eecs.umich.edu    friend class EventQueue;
597174Sgblack@eecs.umich.edu
607639Sgblack@eecs.umich.edu  private:
617639Sgblack@eecs.umich.edu    /// queue to which this event belongs (though it may or may not be
627644Sali.saidi@arm.com    /// scheduled on this queue yet)
638139SMatt.Horsnell@arm.com    EventQueue *queue;
647639Sgblack@eecs.umich.edu
657639Sgblack@eecs.umich.edu    Event *next;
667639Sgblack@eecs.umich.edu
678588Sgblack@eecs.umich.edu    Tick _when;	//!< timestamp when event should be processed
687639Sgblack@eecs.umich.edu    int _priority;	//!< event priority
697639Sgblack@eecs.umich.edu    char _flags;
707639Sgblack@eecs.umich.edu
717644Sali.saidi@arm.com  protected:
728139SMatt.Horsnell@arm.com    enum Flags {
737639Sgblack@eecs.umich.edu        None = 0x0,
747639Sgblack@eecs.umich.edu        Squashed = 0x1,
757639Sgblack@eecs.umich.edu        Scheduled = 0x2,
767639Sgblack@eecs.umich.edu        AutoDelete = 0x4
777639Sgblack@eecs.umich.edu    };
788588Sgblack@eecs.umich.edu
797639Sgblack@eecs.umich.edu    bool getFlags(Flags f) const { return (_flags & f) == f; }
807639Sgblack@eecs.umich.edu    void setFlags(Flags f) { _flags |= f; }
817639Sgblack@eecs.umich.edu    void clearFlags(Flags f) { _flags &= ~f; }
827644Sali.saidi@arm.com
838139SMatt.Horsnell@arm.com  protected:
847639Sgblack@eecs.umich.edu    EventQueue *theQueue() const { return queue; }
857639Sgblack@eecs.umich.edu
867639Sgblack@eecs.umich.edu#if TRACING_ON
877639Sgblack@eecs.umich.edu    Tick when_created;	//!< Keep track of creation time For debugging
887174Sgblack@eecs.umich.edu    Tick when_scheduled;	//!< Keep track of creation time For debugging
898148SAli.Saidi@ARM.com
908303SAli.Saidi@ARM.com    virtual void trace(const char *action);	//!< trace event activity
917400SAli.Saidi@ARM.com#else
928303SAli.Saidi@ARM.com    void trace(const char *) {}
938303SAli.Saidi@ARM.com#endif
9410037SARM gem5 Developers
9510037SARM gem5 Developers    unsigned annotated_value;
968303SAli.Saidi@ARM.com
978303SAli.Saidi@ARM.com  public:
988303SAli.Saidi@ARM.com
998303SAli.Saidi@ARM.com    static const std::string defaultName;
1008303SAli.Saidi@ARM.com
1018303SAli.Saidi@ARM.com    /*
1028205SAli.Saidi@ARM.com     * Event constructor
1037858SMatt.Horsnell@arm.com     * @param queue that the event gets scheduled on
1048285SPrakash.Ramrakhyani@arm.com     */
1056754SN/A    Event(EventQueue *q, int p = 0)
1068148SAli.Saidi@ARM.com        : Serializeable(defaultName), queue(q), next(NULL),
1076754SN/A          _priority(p), _flags(None),
1086754SN/A#if TRACING_ON
1098148SAli.Saidi@ARM.com          when_created(curTick), when_scheduled(0),
1108588Sgblack@eecs.umich.edu#endif
1116754SN/A          annotated_value(0)
1128139SMatt.Horsnell@arm.com    {
1137422Sgblack@eecs.umich.edu    }
1148148SAli.Saidi@ARM.com
1158148SAli.Saidi@ARM.com    ~Event() {}
1166754SN/A
1178588Sgblack@eecs.umich.edu    /// Determine if the current event is scheduled
1186309SN/A    bool scheduled() const { return getFlags(Scheduled); }
1196309SN/A
1207296Sgblack@eecs.umich.edu    /// Schedule the event with the current priority or default priority
1217303Sgblack@eecs.umich.edu    void schedule(Tick t);
1228139SMatt.Horsnell@arm.com
1236309SN/A    /// Schedule the event with a specific priority
1246309SN/A    void schedule(Tick t, int priority);
1256309SN/A
1268588Sgblack@eecs.umich.edu    /// Reschedule the event with the current priority
1277174Sgblack@eecs.umich.edu    void reschedule(Tick t);
1287174Sgblack@eecs.umich.edu
1297296Sgblack@eecs.umich.edu    /// Reschedule the event with a specific priority
1307303Sgblack@eecs.umich.edu    void reschedule(Tick t, int priority);
1317644Sali.saidi@arm.com
1328139SMatt.Horsnell@arm.com    /// Remove the event from the current schedule
1337174Sgblack@eecs.umich.edu    void deschedule();
1347174Sgblack@eecs.umich.edu
1357174Sgblack@eecs.umich.edu    /// Return a C string describing the event.  This string should
1368588Sgblack@eecs.umich.edu    /// *not* be dynamically allocated; just a const char array
1377639Sgblack@eecs.umich.edu    /// describing the event class.
1387639Sgblack@eecs.umich.edu    virtual const char *description();
1397639Sgblack@eecs.umich.edu
1407639Sgblack@eecs.umich.edu    /// Dump the current event data
1417644Sali.saidi@arm.com    void dump();
1428139SMatt.Horsnell@arm.com
1437639Sgblack@eecs.umich.edu    /*
1447639Sgblack@eecs.umich.edu     * This member function is invoked when the event is processed
1457639Sgblack@eecs.umich.edu     * (occurs).  There is no default implementation; each subclass
1467639Sgblack@eecs.umich.edu     * must provide its own implementation.  The event is not
1477639Sgblack@eecs.umich.edu     * automatically deleted after it is processed (to allow for
1488588Sgblack@eecs.umich.edu     * statically allocated event objects).
1497639Sgblack@eecs.umich.edu     *
1507639Sgblack@eecs.umich.edu     * If the AutoDestroy flag is set, the object is deleted once it
1517639Sgblack@eecs.umich.edu     * is processed.
1527639Sgblack@eecs.umich.edu     */
1537644Sali.saidi@arm.com    virtual void process() = 0;
1548139SMatt.Horsnell@arm.com
1557639Sgblack@eecs.umich.edu    void annotate(unsigned value) { annotated_value = value; };
1567639Sgblack@eecs.umich.edu    unsigned annotation() { return annotated_value; }
1577639Sgblack@eecs.umich.edu
1587639Sgblack@eecs.umich.edu    /// Squash the current event
1597639Sgblack@eecs.umich.edu    void squash() { setFlags(Squashed); }
1607174Sgblack@eecs.umich.edu
1617174Sgblack@eecs.umich.edu    /// Check whether the event is squashed
16210037SARM gem5 Developers    bool squashed() { return getFlags(Squashed); }
16310037SARM gem5 Developers
1647639Sgblack@eecs.umich.edu    /// Get the time that the event is scheduled
1657639Sgblack@eecs.umich.edu    Tick when() const { return _when; }
1667174Sgblack@eecs.umich.edu
1677174Sgblack@eecs.umich.edu    /// Get the event priority
1687174Sgblack@eecs.umich.edu    int priority() const { return _priority; }
1697174Sgblack@eecs.umich.edu
1707174Sgblack@eecs.umich.edu    struct priority_compare :
1717174Sgblack@eecs.umich.edu    public std::binary_function<Event *, Event *, bool>
1727174Sgblack@eecs.umich.edu    {
1737174Sgblack@eecs.umich.edu        bool operator()(const Event *l, const Event *r) const {
1747174Sgblack@eecs.umich.edu            return l->when() >= r->when() || l->priority() >= r->priority();
1757174Sgblack@eecs.umich.edu        }
1767174Sgblack@eecs.umich.edu    };
1776309SN/A};
1786308SN/A
1797639Sgblack@eecs.umich.edutemplate <class T, void (T::* F)()>
1807639Sgblack@eecs.umich.eduvoid
1817639Sgblack@eecs.umich.eduDelayFunction(Tick when, T *object)
18210037SARM gem5 Developers{
1837639Sgblack@eecs.umich.edu    class DelayEvent : public Event
1847639Sgblack@eecs.umich.edu    {
1857639Sgblack@eecs.umich.edu      private:
1867639Sgblack@eecs.umich.edu        T *object;
1877639Sgblack@eecs.umich.edu
1887639Sgblack@eecs.umich.edu      public:
1897639Sgblack@eecs.umich.edu        DelayEvent(Tick when, T *o)
1907639Sgblack@eecs.umich.edu            : Event(&mainEventQueue), object(o)
1917639Sgblack@eecs.umich.edu            { setFlags(AutoDestroy); schedule(when); }
1927639Sgblack@eecs.umich.edu        void process() { (object->*F)(); }
1937639Sgblack@eecs.umich.edu        const char *description() { return "delay"; }
1947639Sgblack@eecs.umich.edu    };
1957639Sgblack@eecs.umich.edu
1967639Sgblack@eecs.umich.edu    new DelayEvent(when, object);
1977639Sgblack@eecs.umich.edu}
1987639Sgblack@eecs.umich.edu
1997639Sgblack@eecs.umich.edu/*
2007639Sgblack@eecs.umich.edu * Queue of events sorted in time order
2017639Sgblack@eecs.umich.edu */
2027639Sgblack@eecs.umich.educlass EventQueue : public Serializeable
2037639Sgblack@eecs.umich.edu{
2047639Sgblack@eecs.umich.edu  private:
2057639Sgblack@eecs.umich.edu    Event *head;
2067639Sgblack@eecs.umich.edu
2077639Sgblack@eecs.umich.edu    void insert(Event *event);
2087639Sgblack@eecs.umich.edu    void remove(Event *event);
2097639Sgblack@eecs.umich.edu
2107639Sgblack@eecs.umich.edu  public:
2117639Sgblack@eecs.umich.edu
2127639Sgblack@eecs.umich.edu    // constructor
2137639Sgblack@eecs.umich.edu    EventQueue(const std::string &n)
2147639Sgblack@eecs.umich.edu        : Serializeable(n), head(NULL)
2157639Sgblack@eecs.umich.edu    {}
2167639Sgblack@eecs.umich.edu
2177639Sgblack@eecs.umich.edu    // schedule the given event on this queue
2188588Sgblack@eecs.umich.edu    void schedule(Event *ev);
2197639Sgblack@eecs.umich.edu    void deschedule(Event *ev);
2207639Sgblack@eecs.umich.edu    void reschedule(Event *ev);
2217639Sgblack@eecs.umich.edu
2227639Sgblack@eecs.umich.edu    Tick nextTick() { return head->when(); }
2237639Sgblack@eecs.umich.edu    void serviceOne();
2247639Sgblack@eecs.umich.edu
2258588Sgblack@eecs.umich.edu    // process all events up to the given timestamp.  we inline a
2267639Sgblack@eecs.umich.edu    // quick test to see if there are any events to process; if so,
2277639Sgblack@eecs.umich.edu    // call the internal out-of-line version to process them all.
2287639Sgblack@eecs.umich.edu    void serviceEvents(Tick when) {
2297639Sgblack@eecs.umich.edu        while (!empty()) {
2307639Sgblack@eecs.umich.edu            if (nextTick() > when)
2317639Sgblack@eecs.umich.edu                break;
2327639Sgblack@eecs.umich.edu
2337639Sgblack@eecs.umich.edu            assert(head->when() >= when && "event scheduled in the past");
2347639Sgblack@eecs.umich.edu            serviceOne();
2357639Sgblack@eecs.umich.edu        }
2367639Sgblack@eecs.umich.edu    }
2377644Sali.saidi@arm.com
2387639Sgblack@eecs.umich.edu    // default: process all events up to 'now' (curTick)
2397639Sgblack@eecs.umich.edu    void serviceEvents() { serviceEvents(curTick); }
2407639Sgblack@eecs.umich.edu
2417639Sgblack@eecs.umich.edu    // return true if no events are queued
2427639Sgblack@eecs.umich.edu    bool empty() { return head == NULL; }
2437639Sgblack@eecs.umich.edu
2447639Sgblack@eecs.umich.edu    void dump();
2457639Sgblack@eecs.umich.edu
2467644Sali.saidi@arm.com    Tick nextEventTime() { return empty() ? curTick : head->when(); }
2477639Sgblack@eecs.umich.edu
2487639Sgblack@eecs.umich.edu    virtual void nameChildren();
2497639Sgblack@eecs.umich.edu    virtual void serialize();
2507639Sgblack@eecs.umich.edu};
2517639Sgblack@eecs.umich.edu
2527639Sgblack@eecs.umich.edu
2537639Sgblack@eecs.umich.edu//////////////////////
2547639Sgblack@eecs.umich.edu//
2557639Sgblack@eecs.umich.edu// inline functions
2567639Sgblack@eecs.umich.edu//
2577639Sgblack@eecs.umich.edu// can't put these inside declaration due to circular dependence
2587639Sgblack@eecs.umich.edu// between Event and EventQueue classes.
2597639Sgblack@eecs.umich.edu//
2607639Sgblack@eecs.umich.edu//////////////////////
2617639Sgblack@eecs.umich.edu
2627639Sgblack@eecs.umich.edu// schedule at specified time (place on event queue specified via
2637639Sgblack@eecs.umich.edu// constructor)
2647639Sgblack@eecs.umich.eduinline void
2657639Sgblack@eecs.umich.eduEvent::schedule(Tick t)
2667639Sgblack@eecs.umich.edu{
2677639Sgblack@eecs.umich.edu    assert(!scheduled());
2687639Sgblack@eecs.umich.edu    setFlags(Scheduled);
2697639Sgblack@eecs.umich.edu#if TRACING_ON
2707639Sgblack@eecs.umich.edu    when_scheduled = curTick;
2717639Sgblack@eecs.umich.edu#endif
2727639Sgblack@eecs.umich.edu    _when = t;
2737639Sgblack@eecs.umich.edu    queue->schedule(this);
2747639Sgblack@eecs.umich.edu}
2757639Sgblack@eecs.umich.edu
2767639Sgblack@eecs.umich.eduinline void
2777639Sgblack@eecs.umich.eduEvent::schedule(Tick t, int p)
2787639Sgblack@eecs.umich.edu{
2797639Sgblack@eecs.umich.edu    _priority = p;
2807639Sgblack@eecs.umich.edu    schedule(t);
2817639Sgblack@eecs.umich.edu}
2827639Sgblack@eecs.umich.edu
2837639Sgblack@eecs.umich.eduinline void
2847639Sgblack@eecs.umich.eduEvent::deschedule()
2857639Sgblack@eecs.umich.edu{
2867639Sgblack@eecs.umich.edu    assert(scheduled());
2877639Sgblack@eecs.umich.edu
2887639Sgblack@eecs.umich.edu    clearFlags(Squashed);
2897639Sgblack@eecs.umich.edu    clearFlags(Scheduled);
2907639Sgblack@eecs.umich.edu    queue->deschedule(this);
2917639Sgblack@eecs.umich.edu}
2927639Sgblack@eecs.umich.edu
2937639Sgblack@eecs.umich.eduinline void
2947639Sgblack@eecs.umich.eduEvent::reschedule(Tick t)
2957639Sgblack@eecs.umich.edu{
2967639Sgblack@eecs.umich.edu    assert(scheduled());
2978588Sgblack@eecs.umich.edu    clearFlags(Squashed);
2988588Sgblack@eecs.umich.edu
2997639Sgblack@eecs.umich.edu#if TRACING_ON
3007639Sgblack@eecs.umich.edu    when_scheduled = curTick;
3018588Sgblack@eecs.umich.edu#endif
3028588Sgblack@eecs.umich.edu    _when = t;
3037639Sgblack@eecs.umich.edu    queue->reschedule(this);
3047639Sgblack@eecs.umich.edu}
3057639Sgblack@eecs.umich.edu
3067639Sgblack@eecs.umich.eduinline void
3077639Sgblack@eecs.umich.eduEvent::reschedule(Tick t, int p)
3087639Sgblack@eecs.umich.edu{
3097639Sgblack@eecs.umich.edu    _priority = p;
3107639Sgblack@eecs.umich.edu    reschedule(t);
3117639Sgblack@eecs.umich.edu}
3127639Sgblack@eecs.umich.edu
3137639Sgblack@eecs.umich.eduinline void
3147639Sgblack@eecs.umich.eduEventQueue::schedule(Event *event)
3157639Sgblack@eecs.umich.edu{
3167639Sgblack@eecs.umich.edu    insert(event);
3177639Sgblack@eecs.umich.edu    if (DTRACE(Event))
3187639Sgblack@eecs.umich.edu        event->trace("scheduled");
3197639Sgblack@eecs.umich.edu}
3207639Sgblack@eecs.umich.edu
3217639Sgblack@eecs.umich.eduinline void
3227639Sgblack@eecs.umich.eduEventQueue::deschedule(Event *event)
3237639Sgblack@eecs.umich.edu{
3247639Sgblack@eecs.umich.edu    remove(event);
3257639Sgblack@eecs.umich.edu    if (DTRACE(Event))
3267639Sgblack@eecs.umich.edu        event->trace("descheduled");
3277639Sgblack@eecs.umich.edu}
3287639Sgblack@eecs.umich.edu
3297639Sgblack@eecs.umich.eduinline void
3307639Sgblack@eecs.umich.eduEventQueue::reschedule(Event *event)
3317639Sgblack@eecs.umich.edu{
3327639Sgblack@eecs.umich.edu    remove(event);
3337639Sgblack@eecs.umich.edu    insert(event);
3347639Sgblack@eecs.umich.edu    if (DTRACE(Event))
3357639Sgblack@eecs.umich.edu        event->trace("rescheduled");
3367639Sgblack@eecs.umich.edu}
3377639Sgblack@eecs.umich.edu
3387639Sgblack@eecs.umich.edu
3397639Sgblack@eecs.umich.edu//////////////////////
3407639Sgblack@eecs.umich.edu//
3417639Sgblack@eecs.umich.edu// Main Event Queue
3427639Sgblack@eecs.umich.edu//
3438588Sgblack@eecs.umich.edu// Events on this queue are processed at the *beginning* of each
3448588Sgblack@eecs.umich.edu// cycle, before the pipeline simulation is performed.
3457639Sgblack@eecs.umich.edu//
3467639Sgblack@eecs.umich.edu// defined in eventq.cc
3478588Sgblack@eecs.umich.edu//
3488588Sgblack@eecs.umich.edu//////////////////////
3497639Sgblack@eecs.umich.eduextern EventQueue mainEventQueue;
3507639Sgblack@eecs.umich.edu
3517639Sgblack@eecs.umich.edu#endif // __EVENTQ_HH__
3527639Sgblack@eecs.umich.edu