eventq.hh revision 571
11689SN/A/*
28733Sgeoffrey.blake@arm.com * Copyright (c) 2003 The Regents of The University of Michigan
37598Sminkyu.jeong@arm.com * All rights reserved.
47598Sminkyu.jeong@arm.com *
57598Sminkyu.jeong@arm.com * Redistribution and use in source and binary forms, with or without
67598Sminkyu.jeong@arm.com * modification, are permitted provided that the following conditions are
77598Sminkyu.jeong@arm.com * met: redistributions of source code must retain the above copyright
87598Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer;
97598Sminkyu.jeong@arm.com * redistributions in binary form must reproduce the above copyright
107598Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer in the
117598Sminkyu.jeong@arm.com * documentation and/or other materials provided with the distribution;
127598Sminkyu.jeong@arm.com * neither the name of the copyright holders nor the names of its
137598Sminkyu.jeong@arm.com * contributors may be used to endorse or promote products derived from
142326SN/A * this software without specific prior written permission.
151689SN/A *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271689SN/A */
281689SN/A
291689SN/A/* @file
301689SN/A * EventQueue interfaces
311689SN/A */
321689SN/A
331689SN/A#ifndef __EVENTQ_HH__
341689SN/A#define __EVENTQ_HH__
351689SN/A
361689SN/A#include <assert.h>
371689SN/A
381689SN/A#include <algorithm>
392665Ssaidi@eecs.umich.edu#include <map>
402665Ssaidi@eecs.umich.edu#include <string>
411689SN/A#include <vector>
421689SN/A
431060SN/A#include "sim/host.hh"	// for Tick
441060SN/A
451689SN/A#include "base/fast_alloc.hh"
461060SN/A#include "sim/serialize.hh"
471060SN/A#include "base/trace.hh"
481060SN/A
498230Snate@binkert.orgclass EventQueue;	// forward declaration
506658Snate@binkert.org
518733Sgeoffrey.blake@arm.com/*
522292SN/A * An item on an event queue.  The action caused by a given
531717SN/A * event is specified by deriving a subclass and overriding the
548229Snate@binkert.org * process() member function.
558232Snate@binkert.org */
568232Snate@binkert.orgclass Event : public Serializable, public FastAlloc
578232Snate@binkert.org{
585529Snate@binkert.org    friend class EventQueue;
591060SN/A
608733Sgeoffrey.blake@arm.com  private:
618733Sgeoffrey.blake@arm.com    /// queue to which this event belongs (though it may or may not be
628733Sgeoffrey.blake@arm.com    /// scheduled on this queue yet)
638733Sgeoffrey.blake@arm.com    EventQueue *queue;
646221Snate@binkert.org
656221Snate@binkert.org    Event *next;
661681SN/A
675529Snate@binkert.org    Tick _when;	//!< timestamp when event should be processed
682873Sktlim@umich.edu    int _priority;	//!< event priority
694329Sktlim@umich.edu    char _flags;
704329Sktlim@umich.edu
714329Sktlim@umich.edu  protected:
722292SN/A    enum Flags {
732292SN/A        None = 0x0,
742292SN/A        Squashed = 0x1,
752292SN/A        Scheduled = 0x2,
762820Sktlim@umich.edu        AutoDelete = 0x4,
772292SN/A        AutoSerialize = 0x8
782820Sktlim@umich.edu    };
792820Sktlim@umich.edu
805529Snate@binkert.org    bool getFlags(Flags f) const { return (_flags & f) == f; }
812307SN/A    void setFlags(Flags f) { _flags |= f; }
821060SN/A    void clearFlags(Flags f) { _flags &= ~f; }
832292SN/A
842292SN/A  protected:
852292SN/A    EventQueue *theQueue() const { return queue; }
861060SN/A
871060SN/A#if TRACING_ON
881060SN/A    Tick when_created;	//!< Keep track of creation time For debugging
891060SN/A    Tick when_scheduled;	//!< Keep track of creation time For debugging
901060SN/A
911060SN/A    virtual void trace(const char *action);	//!< trace event activity
921681SN/A#else
936221Snate@binkert.org    void trace(const char *) {}
946221Snate@binkert.org#endif
956221Snate@binkert.org
966221Snate@binkert.org    unsigned annotated_value;
972292SN/A
982292SN/A  public:
992820Sktlim@umich.edu
1002820Sktlim@umich.edu    /// Event priorities, to provide tie-breakers for events scheduled
1012292SN/A    /// at the same cycle.  Most events are scheduled at the default
1022292SN/A    /// priority; these values are used to control events that need to
1032820Sktlim@umich.edu    /// be ordered within a cycle.
1042820Sktlim@umich.edu    enum Priority {
1052292SN/A        /// Breakpoints should happen before anything else, so we
1062292SN/A        /// don't miss any action when debugging.
1072292SN/A        Debug_Break_Pri		= -100,
1082292SN/A
1092292SN/A        /// For some reason "delayed" inter-cluster writebacks are
1102292SN/A        /// scheduled before regular writebacks (which have default
1112292SN/A        /// priority).  Steve?
1122292SN/A        Delayed_Writeback_Pri	=   -1,
1131060SN/A
1141060SN/A        /// Default is zero for historical reasons.
1151681SN/A        Default_Pri		=    0,
1161062SN/A
1172292SN/A        /// CPU switches schedule the new CPU's tick event for the
1181062SN/A        /// same cycle (after unscheduling the old CPU's tick event).
1192301SN/A        /// The switch needs to come before any tick events to make
1202301SN/A        /// sure we don't tick both CPUs in the same cycle.
1211062SN/A        CPU_Switch_Pri		=   31,
1222727Sktlim@umich.edu
1231062SN/A        /// Serailization needs to occur before tick events also, so
1241062SN/A        /// that a serialize/unserialize is identical to an on-line
1251062SN/A        /// CPU switch.
1261062SN/A        Serialize_Pri		=   32,
1271062SN/A
1281062SN/A        /// CPU ticks must come after other associated CPU events
1291062SN/A        /// (such as writebacks).
1301062SN/A        CPU_Tick_Pri		=   50,
1311062SN/A
1321062SN/A        /// Statistics events (dump, reset, etc.) come after
1331062SN/A        /// everything else, but before exit.
1341062SN/A        Stat_Event_Pri		=   90,
1351062SN/A
1361062SN/A        /// If we want to exit on this cycle, it's the very last thing
1371062SN/A        /// we do.
1381062SN/A        Sim_Exit_Pri		=  100
1391062SN/A    };
1401062SN/A
1411062SN/A    /*
1421062SN/A     * Event constructor
1431062SN/A     * @param queue that the event gets scheduled on
1441062SN/A     */
1451062SN/A    Event(EventQueue *q, Priority p = Default_Pri)
1461062SN/A        : queue(q), next(NULL), _priority(p), _flags(None),
1471062SN/A#if TRACING_ON
1481062SN/A          when_created(curTick), when_scheduled(0),
1491062SN/A#endif
1501062SN/A          annotated_value(0)
1511062SN/A    {
1521062SN/A    }
1531062SN/A
1541062SN/A    ~Event() {}
1551062SN/A
1561062SN/A    virtual const std::string name() const {
1571062SN/A        return csprintf("Event_%x", (uintptr_t)this);
1581062SN/A    }
1591062SN/A
1601062SN/A    /// Determine if the current event is scheduled
1611062SN/A    bool scheduled() const { return getFlags(Scheduled); }
1621062SN/A
1631062SN/A    /// Schedule the event with the current priority or default priority
1642292SN/A    void schedule(Tick t);
1652292SN/A
1662292SN/A    /// Reschedule the event with the current priority
1672292SN/A    void reschedule(Tick t);
1681062SN/A
1691062SN/A    /// Remove the event from the current schedule
1701062SN/A    void deschedule();
1711062SN/A
1721062SN/A    /// Return a C string describing the event.  This string should
1731062SN/A    /// *not* be dynamically allocated; just a const char array
1741062SN/A    /// describing the event class.
1752292SN/A    virtual const char *description();
1762292SN/A
1772292SN/A    /// Dump the current event data
1782292SN/A    void dump();
1792292SN/A
1802292SN/A    /*
1812292SN/A     * This member function is invoked when the event is processed
1822292SN/A     * (occurs).  There is no default implementation; each subclass
1832292SN/A     * must provide its own implementation.  The event is not
1842292SN/A     * automatically deleted after it is processed (to allow for
1852301SN/A     * statically allocated event objects).
1862727Sktlim@umich.edu     *
1872353SN/A     * If the AutoDestroy flag is set, the object is deleted once it
1882727Sktlim@umich.edu     * is processed.
1892727Sktlim@umich.edu     */
1902727Sktlim@umich.edu    virtual void process() = 0;
1916221Snate@binkert.org
1922353SN/A    void annotate(unsigned value) { annotated_value = value; };
1932727Sktlim@umich.edu    unsigned annotation() { return annotated_value; }
1942727Sktlim@umich.edu
1952727Sktlim@umich.edu    /// Squash the current event
1962727Sktlim@umich.edu    void squash() { setFlags(Squashed); }
1972353SN/A
1982727Sktlim@umich.edu    /// Check whether the event is squashed
1992727Sktlim@umich.edu    bool squashed() { return getFlags(Squashed); }
2002727Sktlim@umich.edu
2016221Snate@binkert.org    /// Get the time that the event is scheduled
2028240Snate@binkert.org    Tick when() const { return _when; }
2032301SN/A
2042727Sktlim@umich.edu    /// Get the event priority
2052301SN/A    int priority() const { return _priority; }
2062727Sktlim@umich.edu
2076221Snate@binkert.org    struct priority_compare :
2088240Snate@binkert.org    public std::binary_function<Event *, Event *, bool>
2092301SN/A    {
2102727Sktlim@umich.edu        bool operator()(const Event *l, const Event *r) const {
2112301SN/A            return l->when() >= r->when() || l->priority() >= r->priority();
2122727Sktlim@umich.edu        }
2136221Snate@binkert.org    };
2148240Snate@binkert.org
2152301SN/A    virtual void serialize(std::ostream &os);
2162727Sktlim@umich.edu    virtual void unserialize(Checkpoint *cp, const std::string &section);
2172301SN/A};
2182727Sktlim@umich.edu
2196221Snate@binkert.orgtemplate <class T, void (T::* F)()>
2208240Snate@binkert.orgvoid
2212301SN/ADelayFunction(Tick when, T *object)
2222727Sktlim@umich.edu{
2232301SN/A    class DelayEvent : public Event
2242301SN/A    {
2258240Snate@binkert.org      private:
2262301SN/A        T *object;
2272727Sktlim@umich.edu
2282727Sktlim@umich.edu      public:
2292727Sktlim@umich.edu        DelayEvent(Tick when, T *o)
2302727Sktlim@umich.edu            : Event(&mainEventQueue), object(o)
2318240Snate@binkert.org            { setFlags(AutoDestroy); schedule(when); }
2322727Sktlim@umich.edu        void process() { (object->*F)(); }
2332727Sktlim@umich.edu        const char *description() { return "delay"; }
2342727Sktlim@umich.edu    };
2352727Sktlim@umich.edu
2362301SN/A    new DelayEvent(when, object);
2372301SN/A}
2386221Snate@binkert.org
2398240Snate@binkert.orgtemplate <class T, void (T::* F)()>
2402301SN/Aclass EventWrapper : public Event
2412727Sktlim@umich.edu{
2422301SN/A  private:
2432326SN/A    T *object;
2446221Snate@binkert.org
2458240Snate@binkert.org  public:
2462301SN/A    EventWrapper(T *obj, EventQueue *q = &mainEventQueue,
2472727Sktlim@umich.edu                 Priority p = Default_Pri)
2482301SN/A        : Event(q, p), object(obj)
2492326SN/A    {}
2506221Snate@binkert.org    void process() { (object->*F)(); }
2518240Snate@binkert.org};
2522301SN/A
2532727Sktlim@umich.edu/*
2542301SN/A * Queue of events sorted in time order
2552326SN/A */
2566221Snate@binkert.orgclass EventQueue : public Serializable
2578240Snate@binkert.org{
2582301SN/A  protected:
2592727Sktlim@umich.edu    std::string objName;
2602301SN/A
2612326SN/A  private:
2626221Snate@binkert.org    Event *head;
2638240Snate@binkert.org
2642301SN/A    void insert(Event *event);
2652727Sktlim@umich.edu    void remove(Event *event);
2662301SN/A
2672326SN/A  public:
2688240Snate@binkert.org
2692301SN/A    // constructor
2702727Sktlim@umich.edu    EventQueue(const std::string &n)
2712301SN/A        : objName(n), head(NULL)
2722326SN/A    {}
2732301SN/A
2742326SN/A    virtual const std::string name() const { return objName; }
2758240Snate@binkert.org
2762301SN/A    // schedule the given event on this queue
2772727Sktlim@umich.edu    void schedule(Event *ev);
2782301SN/A    void deschedule(Event *ev);
2792326SN/A    void reschedule(Event *ev);
2802301SN/A
2812326SN/A    Tick nextTick() { return head->when(); }
2828240Snate@binkert.org    void serviceOne();
2832301SN/A
2842727Sktlim@umich.edu    // process all events up to the given timestamp.  we inline a
2852326SN/A    // quick test to see if there are any events to process; if so,
2861062SN/A    // call the internal out-of-line version to process them all.
2871062SN/A    void serviceEvents(Tick when) {
2881681SN/A        while (!empty()) {
2891060SN/A            if (nextTick() > when)
2902292SN/A                break;
2911060SN/A
2926221Snate@binkert.org            assert(head->when() >= when && "event scheduled in the past");
2932292SN/A            serviceOne();
2942292SN/A        }
2952292SN/A    }
2962292SN/A
2972292SN/A    // default: process all events up to 'now' (curTick)
2982292SN/A    void serviceEvents() { serviceEvents(curTick); }
2992292SN/A
3002292SN/A    // return true if no events are queued
3012292SN/A    bool empty() { return head == NULL; }
3028733Sgeoffrey.blake@arm.com
3038733Sgeoffrey.blake@arm.com    void dump();
3048733Sgeoffrey.blake@arm.com
3058850Sandreas.hansson@arm.com    Tick nextEventTime() { return empty() ? curTick : head->when(); }
3068733Sgeoffrey.blake@arm.com
3078733Sgeoffrey.blake@arm.com    virtual void serialize(std::ostream &os);
3088733Sgeoffrey.blake@arm.com    virtual void unserialize(Checkpoint *cp, const std::string &section);
3092733Sktlim@umich.edu};
3101060SN/A
3111060SN/A
3121681SN/A//////////////////////
3131060SN/A//
3142292SN/A// inline functions
3151060SN/A//
3161060SN/A// can't put these inside declaration due to circular dependence
3171060SN/A// between Event and EventQueue classes.
3181060SN/A//
3191060SN/A//////////////////////
3201060SN/A
3211060SN/A// schedule at specified time (place on event queue specified via
3221060SN/A// constructor)
3231060SN/Ainline void
3242292SN/AEvent::schedule(Tick t)
3252292SN/A{
3261060SN/A    assert(!scheduled());
3271060SN/A    setFlags(Scheduled);
3281060SN/A#if TRACING_ON
3291060SN/A    when_scheduled = curTick;
3301681SN/A#endif
3311060SN/A    _when = t;
3322292SN/A    queue->schedule(this);
3331060SN/A}
3341060SN/A
3351060SN/Ainline void
3361060SN/AEvent::deschedule()
3371060SN/A{
3381060SN/A    assert(scheduled());
3391060SN/A
3401681SN/A    clearFlags(Squashed);
3411060SN/A    clearFlags(Scheduled);
3422292SN/A    queue->deschedule(this);
3431060SN/A}
3441060SN/A
3451060SN/Ainline void
3461060SN/AEvent::reschedule(Tick t)
3471060SN/A{
3481060SN/A    assert(scheduled());
3491060SN/A    clearFlags(Squashed);
3501681SN/A
3511060SN/A#if TRACING_ON
3526221Snate@binkert.org    when_scheduled = curTick;
3531060SN/A#endif
3542292SN/A    _when = t;
3552292SN/A    queue->reschedule(this);
3562292SN/A}
3572292SN/A
3581060SN/Ainline void
3591060SN/AEventQueue::schedule(Event *event)
3601681SN/A{
3611060SN/A    insert(event);
3622292SN/A    if (DTRACE(Event))
3631060SN/A        event->trace("scheduled");
3642292SN/A}
3651060SN/A
3661060SN/Ainline void
3672307SN/AEventQueue::deschedule(Event *event)
3682863Sktlim@umich.edu{
3692843Sktlim@umich.edu    remove(event);
3702307SN/A    if (DTRACE(Event))
3712843Sktlim@umich.edu        event->trace("descheduled");
3722843Sktlim@umich.edu}
3732863Sktlim@umich.edu
3741681SN/Ainline void
3751681SN/AEventQueue::reschedule(Event *event)
3762316SN/A{
3771681SN/A    remove(event);
3782843Sktlim@umich.edu    insert(event);
3792843Sktlim@umich.edu    if (DTRACE(Event))
3802843Sktlim@umich.edu        event->trace("rescheduled");
3812843Sktlim@umich.edu}
3822843Sktlim@umich.edu
3832843Sktlim@umich.edu
3842843Sktlim@umich.edu//////////////////////
3851681SN/A//
3862348SN/A// Main Event Queue
3872307SN/A//
3882367SN/A// Events on this queue are processed at the *beginning* of each
3892367SN/A// cycle, before the pipeline simulation is performed.
3901681SN/A//
3912307SN/A// defined in eventq.cc
3922307SN/A//
3932307SN/A//////////////////////
3942307SN/Aextern EventQueue mainEventQueue;
3956221Snate@binkert.org
3966221Snate@binkert.org#endif // __EVENTQ_HH__
3976221Snate@binkert.org