eventq.hh revision 395
17118Sgblack@eecs.umich.edu/*
27118Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan
37118Sgblack@eecs.umich.edu * All rights reserved.
47118Sgblack@eecs.umich.edu *
57118Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67118Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77118Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87118Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97118Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107118Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117118Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127118Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137118Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147118Sgblack@eecs.umich.edu * this software without specific prior written permission.
156253Sgblack@eecs.umich.edu *
166253Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176253Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186253Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196253Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206253Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216253Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226253Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236253Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246253Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256253Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266253Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276253Sgblack@eecs.umich.edu */
286253Sgblack@eecs.umich.edu
296253Sgblack@eecs.umich.edu/* @file
306253Sgblack@eecs.umich.edu * EventQueue interfaces
316253Sgblack@eecs.umich.edu */
326253Sgblack@eecs.umich.edu
336253Sgblack@eecs.umich.edu#ifndef __EVENTQ_HH__
346253Sgblack@eecs.umich.edu#define __EVENTQ_HH__
356253Sgblack@eecs.umich.edu
366253Sgblack@eecs.umich.edu#include <assert.h>
376253Sgblack@eecs.umich.edu
386253Sgblack@eecs.umich.edu#include <algorithm>
396253Sgblack@eecs.umich.edu#include <map>
406253Sgblack@eecs.umich.edu#include <string>
416253Sgblack@eecs.umich.edu#include <vector>
426253Sgblack@eecs.umich.edu
436253Sgblack@eecs.umich.edu#include "sim/host.hh"	// for Tick
446253Sgblack@eecs.umich.edu
456253Sgblack@eecs.umich.edu#include "base/fast_alloc.hh"
467205Sgblack@eecs.umich.edu#include "sim/serialize.hh"
477205Sgblack@eecs.umich.edu#include "base/trace.hh"
486253Sgblack@eecs.umich.edu
496253Sgblack@eecs.umich.educlass EventQueue;	// forward declaration
507118Sgblack@eecs.umich.edu
517428Sgblack@eecs.umich.edu/*
527428Sgblack@eecs.umich.edu * An item on an event queue.  The action caused by a given
537428Sgblack@eecs.umich.edu * event is specified by deriving a subclass and overriding the
547428Sgblack@eecs.umich.edu * process() member function.
557428Sgblack@eecs.umich.edu */
567428Sgblack@eecs.umich.educlass Event : public Serializable, public FastAlloc
577428Sgblack@eecs.umich.edu{
587428Sgblack@eecs.umich.edu    friend class EventQueue;
597428Sgblack@eecs.umich.edu
607428Sgblack@eecs.umich.edu  private:
617428Sgblack@eecs.umich.edu    /// queue to which this event belongs (though it may or may not be
627428Sgblack@eecs.umich.edu    /// scheduled on this queue yet)
637429SAli.Saidi@ARM.com    EventQueue *queue;
647428Sgblack@eecs.umich.edu
657428Sgblack@eecs.umich.edu    Event *next;
667429SAli.Saidi@ARM.com
677428Sgblack@eecs.umich.edu    Tick _when;	//!< timestamp when event should be processed
687428Sgblack@eecs.umich.edu    int _priority;	//!< event priority
697428Sgblack@eecs.umich.edu    char _flags;
707428Sgblack@eecs.umich.edu
717428Sgblack@eecs.umich.edu  protected:
727428Sgblack@eecs.umich.edu    enum Flags {
737428Sgblack@eecs.umich.edu        None = 0x0,
747428Sgblack@eecs.umich.edu        Squashed = 0x1,
757428Sgblack@eecs.umich.edu        Scheduled = 0x2,
767428Sgblack@eecs.umich.edu        AutoDelete = 0x4,
777428Sgblack@eecs.umich.edu        AutoSerialize = 0x8
787428Sgblack@eecs.umich.edu    };
797205Sgblack@eecs.umich.edu
807205Sgblack@eecs.umich.edu    bool getFlags(Flags f) const { return (_flags & f) == f; }
817205Sgblack@eecs.umich.edu    void setFlags(Flags f) { _flags |= f; }
827205Sgblack@eecs.umich.edu    void clearFlags(Flags f) { _flags &= ~f; }
837205Sgblack@eecs.umich.edu
847205Sgblack@eecs.umich.edu  protected:
857205Sgblack@eecs.umich.edu    EventQueue *theQueue() const { return queue; }
867205Sgblack@eecs.umich.edu
877205Sgblack@eecs.umich.edu#if TRACING_ON
887205Sgblack@eecs.umich.edu    Tick when_created;	//!< Keep track of creation time For debugging
897205Sgblack@eecs.umich.edu    Tick when_scheduled;	//!< Keep track of creation time For debugging
907205Sgblack@eecs.umich.edu
917205Sgblack@eecs.umich.edu    virtual void trace(const char *action);	//!< trace event activity
927205Sgblack@eecs.umich.edu#else
937291Sgblack@eecs.umich.edu    void trace(const char *) {}
947291Sgblack@eecs.umich.edu#endif
957291Sgblack@eecs.umich.edu
967291Sgblack@eecs.umich.edu    unsigned annotated_value;
977291Sgblack@eecs.umich.edu
987291Sgblack@eecs.umich.edu  public:
997291Sgblack@eecs.umich.edu
1007291Sgblack@eecs.umich.edu    /*
1017291Sgblack@eecs.umich.edu     * Event constructor
1027291Sgblack@eecs.umich.edu     * @param queue that the event gets scheduled on
1037291Sgblack@eecs.umich.edu     */
1047291Sgblack@eecs.umich.edu    Event(EventQueue *q, int p = 0)
1057291Sgblack@eecs.umich.edu        : queue(q), next(NULL), _priority(p), _flags(None),
1067291Sgblack@eecs.umich.edu#if TRACING_ON
1077291Sgblack@eecs.umich.edu          when_created(curTick), when_scheduled(0),
1087291Sgblack@eecs.umich.edu#endif
1097291Sgblack@eecs.umich.edu          annotated_value(0)
1107291Sgblack@eecs.umich.edu    {
1117291Sgblack@eecs.umich.edu    }
1127291Sgblack@eecs.umich.edu
1137291Sgblack@eecs.umich.edu    ~Event() {}
1147291Sgblack@eecs.umich.edu
1157291Sgblack@eecs.umich.edu    virtual std::string name() const {
1167291Sgblack@eecs.umich.edu        return csprintf("Event_%x", (uintptr_t)this);
1177291Sgblack@eecs.umich.edu    }
1187312Sgblack@eecs.umich.edu
1197312Sgblack@eecs.umich.edu    /// Determine if the current event is scheduled
1207312Sgblack@eecs.umich.edu    bool scheduled() const { return getFlags(Scheduled); }
1217312Sgblack@eecs.umich.edu
1227312Sgblack@eecs.umich.edu    /// Schedule the event with the current priority or default priority
1237312Sgblack@eecs.umich.edu    void schedule(Tick t);
1247312Sgblack@eecs.umich.edu
1257312Sgblack@eecs.umich.edu    /// Schedule the event with a specific priority
1267312Sgblack@eecs.umich.edu    void schedule(Tick t, int priority);
1277312Sgblack@eecs.umich.edu
1287312Sgblack@eecs.umich.edu    /// Reschedule the event with the current priority
1297312Sgblack@eecs.umich.edu    void reschedule(Tick t);
1307312Sgblack@eecs.umich.edu
1317312Sgblack@eecs.umich.edu    /// Reschedule the event with a specific priority
1327312Sgblack@eecs.umich.edu    void reschedule(Tick t, int priority);
1337312Sgblack@eecs.umich.edu
1347312Sgblack@eecs.umich.edu    /// Remove the event from the current schedule
1357312Sgblack@eecs.umich.edu    void deschedule();
1367312Sgblack@eecs.umich.edu
1377312Sgblack@eecs.umich.edu    /// Return a C string describing the event.  This string should
1387312Sgblack@eecs.umich.edu    /// *not* be dynamically allocated; just a const char array
1397312Sgblack@eecs.umich.edu    /// describing the event class.
1407312Sgblack@eecs.umich.edu    virtual const char *description();
1417313Sgblack@eecs.umich.edu
1427312Sgblack@eecs.umich.edu    /// Dump the current event data
1437312Sgblack@eecs.umich.edu    void dump();
1447312Sgblack@eecs.umich.edu
1457312Sgblack@eecs.umich.edu    /*
1467312Sgblack@eecs.umich.edu     * This member function is invoked when the event is processed
1477312Sgblack@eecs.umich.edu     * (occurs).  There is no default implementation; each subclass
1487312Sgblack@eecs.umich.edu     * must provide its own implementation.  The event is not
1497312Sgblack@eecs.umich.edu     * automatically deleted after it is processed (to allow for
1507312Sgblack@eecs.umich.edu     * statically allocated event objects).
1517312Sgblack@eecs.umich.edu     *
1527312Sgblack@eecs.umich.edu     * If the AutoDestroy flag is set, the object is deleted once it
1537312Sgblack@eecs.umich.edu     * is processed.
1547312Sgblack@eecs.umich.edu     */
1557312Sgblack@eecs.umich.edu    virtual void process() = 0;
1567312Sgblack@eecs.umich.edu
1577312Sgblack@eecs.umich.edu    void annotate(unsigned value) { annotated_value = value; };
1587312Sgblack@eecs.umich.edu    unsigned annotation() { return annotated_value; }
1597312Sgblack@eecs.umich.edu
1607312Sgblack@eecs.umich.edu    /// Squash the current event
1617312Sgblack@eecs.umich.edu    void squash() { setFlags(Squashed); }
1627312Sgblack@eecs.umich.edu
1637312Sgblack@eecs.umich.edu    /// Check whether the event is squashed
1647312Sgblack@eecs.umich.edu    bool squashed() { return getFlags(Squashed); }
1657312Sgblack@eecs.umich.edu
1667312Sgblack@eecs.umich.edu    /// Get the time that the event is scheduled
1677312Sgblack@eecs.umich.edu    Tick when() const { return _when; }
1687312Sgblack@eecs.umich.edu
1697312Sgblack@eecs.umich.edu    /// Get the event priority
1707312Sgblack@eecs.umich.edu    int priority() const { return _priority; }
1717312Sgblack@eecs.umich.edu
1727312Sgblack@eecs.umich.edu    struct priority_compare :
1737118Sgblack@eecs.umich.edu    public std::binary_function<Event *, Event *, bool>
1747132Sgblack@eecs.umich.edu    {
1757118Sgblack@eecs.umich.edu        bool operator()(const Event *l, const Event *r) const {
1767118Sgblack@eecs.umich.edu            return l->when() >= r->when() || l->priority() >= r->priority();
1777279Sgblack@eecs.umich.edu        }
1787118Sgblack@eecs.umich.edu    };
1797118Sgblack@eecs.umich.edu
1807118Sgblack@eecs.umich.edu    virtual void serialize(std::ostream &os);
1817118Sgblack@eecs.umich.edu    virtual void unserialize(Checkpoint *cp, const std::string &section);
1827118Sgblack@eecs.umich.edu};
1837118Sgblack@eecs.umich.edu
1847118Sgblack@eecs.umich.edutemplate <class T, void (T::* F)()>
1857118Sgblack@eecs.umich.eduvoid
1867118Sgblack@eecs.umich.eduDelayFunction(Tick when, T *object)
1877118Sgblack@eecs.umich.edu{
1887118Sgblack@eecs.umich.edu    class DelayEvent : public Event
1897118Sgblack@eecs.umich.edu    {
1907118Sgblack@eecs.umich.edu      private:
1917118Sgblack@eecs.umich.edu        T *object;
1927118Sgblack@eecs.umich.edu
1937118Sgblack@eecs.umich.edu      public:
1946253Sgblack@eecs.umich.edu        DelayEvent(Tick when, T *o)
195            : Event(&mainEventQueue), object(o)
196            { setFlags(AutoDestroy); schedule(when); }
197        void process() { (object->*F)(); }
198        const char *description() { return "delay"; }
199    };
200
201    new DelayEvent(when, object);
202}
203
204/*
205 * Queue of events sorted in time order
206 */
207class EventQueue : public Serializable
208{
209  protected:
210    std::string objName;
211
212  private:
213    Event *head;
214
215    void insert(Event *event);
216    void remove(Event *event);
217
218  public:
219
220    // constructor
221    EventQueue(const std::string &n)
222        : objName(n), head(NULL)
223    {}
224
225    virtual std::string name() const { return objName; }
226
227    // schedule the given event on this queue
228    void schedule(Event *ev);
229    void deschedule(Event *ev);
230    void reschedule(Event *ev);
231
232    Tick nextTick() { return head->when(); }
233    void serviceOne();
234
235    // process all events up to the given timestamp.  we inline a
236    // quick test to see if there are any events to process; if so,
237    // call the internal out-of-line version to process them all.
238    void serviceEvents(Tick when) {
239        while (!empty()) {
240            if (nextTick() > when)
241                break;
242
243            assert(head->when() >= when && "event scheduled in the past");
244            serviceOne();
245        }
246    }
247
248    // default: process all events up to 'now' (curTick)
249    void serviceEvents() { serviceEvents(curTick); }
250
251    // return true if no events are queued
252    bool empty() { return head == NULL; }
253
254    void dump();
255
256    Tick nextEventTime() { return empty() ? curTick : head->when(); }
257
258    virtual void serialize(std::ostream &os);
259    virtual void unserialize(Checkpoint *cp, const std::string &section);
260};
261
262
263//////////////////////
264//
265// inline functions
266//
267// can't put these inside declaration due to circular dependence
268// between Event and EventQueue classes.
269//
270//////////////////////
271
272// schedule at specified time (place on event queue specified via
273// constructor)
274inline void
275Event::schedule(Tick t)
276{
277    assert(!scheduled());
278    setFlags(Scheduled);
279#if TRACING_ON
280    when_scheduled = curTick;
281#endif
282    _when = t;
283    queue->schedule(this);
284}
285
286inline void
287Event::schedule(Tick t, int p)
288{
289    _priority = p;
290    schedule(t);
291}
292
293inline void
294Event::deschedule()
295{
296    assert(scheduled());
297
298    clearFlags(Squashed);
299    clearFlags(Scheduled);
300    queue->deschedule(this);
301}
302
303inline void
304Event::reschedule(Tick t)
305{
306    assert(scheduled());
307    clearFlags(Squashed);
308
309#if TRACING_ON
310    when_scheduled = curTick;
311#endif
312    _when = t;
313    queue->reschedule(this);
314}
315
316inline void
317Event::reschedule(Tick t, int p)
318{
319    _priority = p;
320    reschedule(t);
321}
322
323inline void
324EventQueue::schedule(Event *event)
325{
326    insert(event);
327    if (DTRACE(Event))
328        event->trace("scheduled");
329}
330
331inline void
332EventQueue::deschedule(Event *event)
333{
334    remove(event);
335    if (DTRACE(Event))
336        event->trace("descheduled");
337}
338
339inline void
340EventQueue::reschedule(Event *event)
341{
342    remove(event);
343    insert(event);
344    if (DTRACE(Event))
345        event->trace("rescheduled");
346}
347
348
349//////////////////////
350//
351// Main Event Queue
352//
353// Events on this queue are processed at the *beginning* of each
354// cycle, before the pipeline simulation is performed.
355//
356// defined in eventq.cc
357//
358//////////////////////
359extern EventQueue mainEventQueue;
360
361#endif // __EVENTQ_HH__
362