eventq.hh revision 237
13520Sgblack@eecs.umich.edu/*
23520Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan
33520Sgblack@eecs.umich.edu * All rights reserved.
43520Sgblack@eecs.umich.edu *
53520Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
63520Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
73520Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
83520Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
93520Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
103520Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
113520Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
123520Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
133520Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
143520Sgblack@eecs.umich.edu * this software without specific prior written permission.
153520Sgblack@eecs.umich.edu *
163520Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173520Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183520Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193520Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203520Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213520Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223520Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233520Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243520Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253520Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263520Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273520Sgblack@eecs.umich.edu */
283520Sgblack@eecs.umich.edu
293520Sgblack@eecs.umich.edu/* @file
303520Sgblack@eecs.umich.edu * EventQueue interfaces
313520Sgblack@eecs.umich.edu */
323520Sgblack@eecs.umich.edu
333520Sgblack@eecs.umich.edu#ifndef __EVENTQ_HH__
343520Sgblack@eecs.umich.edu#define __EVENTQ_HH__
353520Sgblack@eecs.umich.edu
363520Sgblack@eecs.umich.edu#include <assert.h>
374103Ssaidi@eecs.umich.edu
385647Sgblack@eecs.umich.edu#include <algorithm>
393520Sgblack@eecs.umich.edu#include <map>
405647Sgblack@eecs.umich.edu#include <string>
415647Sgblack@eecs.umich.edu#include <vector>
423520Sgblack@eecs.umich.edu
435565Snate@binkert.org#include "sim/host.hh"	// for Tick
445565Snate@binkert.org
455647Sgblack@eecs.umich.edu#include "base/fast_alloc.hh"
463520Sgblack@eecs.umich.edu#include "sim/serialize.hh"
475565Snate@binkert.org#include "base/trace.hh"
485565Snate@binkert.org
495565Snate@binkert.orgclass EventQueue;	// forward declaration
505565Snate@binkert.org
515810Sgblack@eecs.umich.edu/*
525565Snate@binkert.org * An item on an event queue.  The action caused by a given
535565Snate@binkert.org * event is specified by deriving a subclass and overriding the
545565Snate@binkert.org * process() member function.
555565Snate@binkert.org */
565565Snate@binkert.orgclass Event : public Serializeable, public FastAlloc
575565Snate@binkert.org{
585647Sgblack@eecs.umich.edu    friend class EventQueue;
595647Sgblack@eecs.umich.edu
605647Sgblack@eecs.umich.edu  private:
615647Sgblack@eecs.umich.edu    /// queue to which this event belongs (though it may or may not be
625647Sgblack@eecs.umich.edu    /// scheduled on this queue yet)
635647Sgblack@eecs.umich.edu    EventQueue *queue;
645647Sgblack@eecs.umich.edu
655647Sgblack@eecs.umich.edu    Event *next;
665810Sgblack@eecs.umich.edu
673520Sgblack@eecs.umich.edu    Tick _when;	//!< timestamp when event should be processed
685565Snate@binkert.org    int _priority;	//!< event priority
695565Snate@binkert.org    char _flags;
705565Snate@binkert.org
715565Snate@binkert.org  protected:
723520Sgblack@eecs.umich.edu    enum Flags {
735565Snate@binkert.org        None = 0x0,
745810Sgblack@eecs.umich.edu        Squashed = 0x1,
755810Sgblack@eecs.umich.edu        Scheduled = 0x2,
765810Sgblack@eecs.umich.edu        AutoDelete = 0x4,
775810Sgblack@eecs.umich.edu        AutoSerialize = 0x8
785810Sgblack@eecs.umich.edu    };
795810Sgblack@eecs.umich.edu
805565Snate@binkert.org    bool getFlags(Flags f) const { return (_flags & f) == f; }
815565Snate@binkert.org    void setFlags(Flags f) { _flags |= f; }
825565Snate@binkert.org    void clearFlags(Flags f) { _flags &= ~f; }
833520Sgblack@eecs.umich.edu
845565Snate@binkert.org  protected:
855565Snate@binkert.org    EventQueue *theQueue() const { return queue; }
863520Sgblack@eecs.umich.edu
875565Snate@binkert.org#if TRACING_ON
885565Snate@binkert.org    Tick when_created;	//!< Keep track of creation time For debugging
893520Sgblack@eecs.umich.edu    Tick when_scheduled;	//!< Keep track of creation time For debugging
905565Snate@binkert.org
915565Snate@binkert.org    virtual void trace(const char *action);	//!< trace event activity
925565Snate@binkert.org#else
933520Sgblack@eecs.umich.edu    void trace(const char *) {}
945565Snate@binkert.org#endif
955565Snate@binkert.org
965565Snate@binkert.org    unsigned annotated_value;
975565Snate@binkert.org
983520Sgblack@eecs.umich.edu  public:
995568Snate@binkert.org
1005565Snate@binkert.org    static const std::string defaultName;
1013520Sgblack@eecs.umich.edu
1025565Snate@binkert.org    /*
1035565Snate@binkert.org     * Event constructor
1043520Sgblack@eecs.umich.edu     * @param queue that the event gets scheduled on
1055565Snate@binkert.org     */
1065565Snate@binkert.org    Event(EventQueue *q, int p = 0)
1075565Snate@binkert.org        : Serializeable(defaultName), queue(q), next(NULL),
1085565Snate@binkert.org          _priority(p), _flags(None),
1093520Sgblack@eecs.umich.edu#if TRACING_ON
1105565Snate@binkert.org          when_created(curTick), when_scheduled(0),
1115704Snate@binkert.org#endif
1125565Snate@binkert.org          annotated_value(0)
1135565Snate@binkert.org    {
1143520Sgblack@eecs.umich.edu    }
1155565Snate@binkert.org
1165565Snate@binkert.org    /*
1175565Snate@binkert.org     * Event constructor
1183520Sgblack@eecs.umich.edu     * @param queue that the event gets scheduled on
1195565Snate@binkert.org     */
1205565Snate@binkert.org    Event(EventQueue *q, std::string _name, int p = 0)
1215565Snate@binkert.org        : Serializeable(_name), queue(q), next(NULL),
1225565Snate@binkert.org          _priority(p), _flags(None),
1235565Snate@binkert.org#if TRACING_ON
1245565Snate@binkert.org          when_created(curTick), when_scheduled(0),
1253520Sgblack@eecs.umich.edu#endif
1265565Snate@binkert.org          annotated_value(0)
1275565Snate@binkert.org    {
1285565Snate@binkert.org    }
1295565Snate@binkert.org
1305565Snate@binkert.org    ~Event() {}
1315565Snate@binkert.org
1323520Sgblack@eecs.umich.edu    /// Determine if the current event is scheduled
1335565Snate@binkert.org    bool scheduled() const { return getFlags(Scheduled); }
1345704Snate@binkert.org
1355565Snate@binkert.org    /// Schedule the event with the current priority or default priority
1365565Snate@binkert.org    void schedule(Tick t);
1375565Snate@binkert.org
1383520Sgblack@eecs.umich.edu    /// Schedule the event with a specific priority
1395565Snate@binkert.org    void schedule(Tick t, int priority);
1405565Snate@binkert.org
1415565Snate@binkert.org    /// Reschedule the event with the current priority
1425565Snate@binkert.org    void reschedule(Tick t);
1435565Snate@binkert.org
1443521Sgblack@eecs.umich.edu    /// Reschedule the event with a specific priority
1455565Snate@binkert.org    void reschedule(Tick t, int priority);
1465565Snate@binkert.org
1473520Sgblack@eecs.umich.edu    /// Remove the event from the current schedule
1485565Snate@binkert.org    void deschedule();
1495565Snate@binkert.org
1505565Snate@binkert.org    /// Return a C string describing the event.  This string should
1515565Snate@binkert.org    /// *not* be dynamically allocated; just a const char array
1525565Snate@binkert.org    /// describing the event class.
1535565Snate@binkert.org    virtual const char *description();
1545565Snate@binkert.org
1553520Sgblack@eecs.umich.edu    /// Dump the current event data
1563520Sgblack@eecs.umich.edu    void dump();
1573520Sgblack@eecs.umich.edu
1583520Sgblack@eecs.umich.edu    /*
1595565Snate@binkert.org     * This member function is invoked when the event is processed
1605565Snate@binkert.org     * (occurs).  There is no default implementation; each subclass
1615565Snate@binkert.org     * must provide its own implementation.  The event is not
1625565Snate@binkert.org     * automatically deleted after it is processed (to allow for
1635565Snate@binkert.org     * statically allocated event objects).
1645565Snate@binkert.org     *
1655565Snate@binkert.org     * If the AutoDestroy flag is set, the object is deleted once it
1665565Snate@binkert.org     * is processed.
1675565Snate@binkert.org     */
1685565Snate@binkert.org    virtual void process() = 0;
1693633Sktlim@umich.edu
1703633Sktlim@umich.edu    void annotate(unsigned value) { annotated_value = value; };
1715565Snate@binkert.org    unsigned annotation() { return annotated_value; }
1725565Snate@binkert.org
1735565Snate@binkert.org    /// Squash the current event
1745565Snate@binkert.org    void squash() { setFlags(Squashed); }
1755565Snate@binkert.org
1765565Snate@binkert.org    /// Check whether the event is squashed
1775565Snate@binkert.org    bool squashed() { return getFlags(Squashed); }
1785565Snate@binkert.org
1795565Snate@binkert.org    /// Get the time that the event is scheduled
1805565Snate@binkert.org    Tick when() const { return _when; }
1814103Ssaidi@eecs.umich.edu
1825565Snate@binkert.org    /// Get the event priority
1834103Ssaidi@eecs.umich.edu    int priority() const { return _priority; }
1845565Snate@binkert.org
1855565Snate@binkert.org    struct priority_compare :
1865565Snate@binkert.org    public std::binary_function<Event *, Event *, bool>
1875565Snate@binkert.org    {
1885565Snate@binkert.org        bool operator()(const Event *l, const Event *r) const {
1895565Snate@binkert.org            return l->when() >= r->when() || l->priority() >= r->priority();
1905565Snate@binkert.org        }
1915565Snate@binkert.org    };
1925565Snate@binkert.org
1933520Sgblack@eecs.umich.edu    virtual void serialize(std::ostream &os);
1945565Snate@binkert.org    virtual void unserialize(Checkpoint *cp, const std::string &section);
1955565Snate@binkert.org};
1965565Snate@binkert.org
1975565Snate@binkert.orgtemplate <class T, void (T::* F)()>
198void
199DelayFunction(Tick when, T *object)
200{
201    class DelayEvent : public Event
202    {
203      private:
204        T *object;
205
206      public:
207        DelayEvent(Tick when, T *o)
208            : Event(&mainEventQueue), object(o)
209            { setFlags(AutoDestroy); schedule(when); }
210        void process() { (object->*F)(); }
211        const char *description() { return "delay"; }
212    };
213
214    new DelayEvent(when, object);
215}
216
217/*
218 * Queue of events sorted in time order
219 */
220class EventQueue : public Serializeable
221{
222  private:
223    Event *head;
224
225    // only used to hold value between nameChildren() and serialize()
226    int numAutoSerializeEvents;
227
228    void insert(Event *event);
229    void remove(Event *event);
230
231  public:
232
233    // constructor
234    EventQueue(const std::string &n)
235        : Serializeable(n), head(NULL), numAutoSerializeEvents(-1)
236    {}
237
238    // schedule the given event on this queue
239    void schedule(Event *ev);
240    void deschedule(Event *ev);
241    void reschedule(Event *ev);
242
243    Tick nextTick() { return head->when(); }
244    void serviceOne();
245
246    // process all events up to the given timestamp.  we inline a
247    // quick test to see if there are any events to process; if so,
248    // call the internal out-of-line version to process them all.
249    void serviceEvents(Tick when) {
250        while (!empty()) {
251            if (nextTick() > when)
252                break;
253
254            assert(head->when() >= when && "event scheduled in the past");
255            serviceOne();
256        }
257    }
258
259    // default: process all events up to 'now' (curTick)
260    void serviceEvents() { serviceEvents(curTick); }
261
262    // return true if no events are queued
263    bool empty() { return head == NULL; }
264
265    void dump();
266
267    Tick nextEventTime() { return empty() ? curTick : head->when(); }
268
269    virtual void nameChildren();
270    virtual void serialize(std::ostream &os);
271    virtual void unserialize(Checkpoint *cp, const std::string &section);
272};
273
274
275//////////////////////
276//
277// inline functions
278//
279// can't put these inside declaration due to circular dependence
280// between Event and EventQueue classes.
281//
282//////////////////////
283
284// schedule at specified time (place on event queue specified via
285// constructor)
286inline void
287Event::schedule(Tick t)
288{
289    assert(!scheduled());
290    setFlags(Scheduled);
291#if TRACING_ON
292    when_scheduled = curTick;
293#endif
294    _when = t;
295    queue->schedule(this);
296}
297
298inline void
299Event::schedule(Tick t, int p)
300{
301    _priority = p;
302    schedule(t);
303}
304
305inline void
306Event::deschedule()
307{
308    assert(scheduled());
309
310    clearFlags(Squashed);
311    clearFlags(Scheduled);
312    queue->deschedule(this);
313}
314
315inline void
316Event::reschedule(Tick t)
317{
318    assert(scheduled());
319    clearFlags(Squashed);
320
321#if TRACING_ON
322    when_scheduled = curTick;
323#endif
324    _when = t;
325    queue->reschedule(this);
326}
327
328inline void
329Event::reschedule(Tick t, int p)
330{
331    _priority = p;
332    reschedule(t);
333}
334
335inline void
336EventQueue::schedule(Event *event)
337{
338    insert(event);
339    if (DTRACE(Event))
340        event->trace("scheduled");
341}
342
343inline void
344EventQueue::deschedule(Event *event)
345{
346    remove(event);
347    if (DTRACE(Event))
348        event->trace("descheduled");
349}
350
351inline void
352EventQueue::reschedule(Event *event)
353{
354    remove(event);
355    insert(event);
356    if (DTRACE(Event))
357        event->trace("rescheduled");
358}
359
360
361//////////////////////
362//
363// Main Event Queue
364//
365// Events on this queue are processed at the *beginning* of each
366// cycle, before the pipeline simulation is performed.
367//
368// defined in eventq.cc
369//
370//////////////////////
371extern EventQueue mainEventQueue;
372
373#endif // __EVENTQ_HH__
374