eventq.hh revision 224
14661Sksewell@umich.edu/*
25268Sksewell@umich.edu * Copyright (c) 2003 The Regents of The University of Michigan
35268Sksewell@umich.edu * All rights reserved.
44661Sksewell@umich.edu *
55268Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
65268Sksewell@umich.edu * modification, are permitted provided that the following conditions are
75268Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
85268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
95268Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
105268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
115268Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
125268Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
135268Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
145268Sksewell@umich.edu * this software without specific prior written permission.
154661Sksewell@umich.edu *
165268Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175268Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185268Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195268Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205268Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215268Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225268Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235268Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245268Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255268Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265268Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274661Sksewell@umich.edu */
284661Sksewell@umich.edu
294661Sksewell@umich.edu/* @file
304661Sksewell@umich.edu * EventQueue interfaces
314661Sksewell@umich.edu */
324661Sksewell@umich.edu
334661Sksewell@umich.edu#ifndef __EVENTQ_HH__
344661Sksewell@umich.edu#define __EVENTQ_HH__
354661Sksewell@umich.edu
364661Sksewell@umich.edu#include <assert.h>
376216Snate@binkert.org
384661Sksewell@umich.edu#include <algorithm>
394661Sksewell@umich.edu#include <map>
404661Sksewell@umich.edu#include <string>
414661Sksewell@umich.edu#include <vector>
424661Sksewell@umich.edu
434661Sksewell@umich.edu#include "sim/host.hh"	// for Tick
445558Snate@binkert.org
455558Snate@binkert.org#include "base/fast_alloc.hh"
465558Snate@binkert.org#include "sim/serialize.hh"
475558Snate@binkert.org#include "base/trace.hh"
485558Snate@binkert.org
495558Snate@binkert.orgclass EventQueue;	// forward declaration
505558Snate@binkert.org
514661Sksewell@umich.edu/*
524661Sksewell@umich.edu * An item on an event queue.  The action caused by a given
535558Snate@binkert.org * event is specified by deriving a subclass and overriding the
545558Snate@binkert.org * process() member function.
555558Snate@binkert.org */
565558Snate@binkert.orgclass Event : public Serializeable, public FastAlloc
575558Snate@binkert.org{
585558Snate@binkert.org    friend class EventQueue;
595558Snate@binkert.org
605558Snate@binkert.org  private:
615558Snate@binkert.org    /// queue to which this event belongs (though it may or may not be
625558Snate@binkert.org    /// scheduled on this queue yet)
635558Snate@binkert.org    EventQueue *queue;
645558Snate@binkert.org
655558Snate@binkert.org    Event *next;
665558Snate@binkert.org
675558Snate@binkert.org    Tick _when;	//!< timestamp when event should be processed
685558Snate@binkert.org    int _priority;	//!< event priority
695558Snate@binkert.org    char _flags;
705558Snate@binkert.org
715558Snate@binkert.org  protected:
725558Snate@binkert.org    enum Flags {
735558Snate@binkert.org        None = 0x0,
745558Snate@binkert.org        Squashed = 0x1,
755558Snate@binkert.org        Scheduled = 0x2,
765558Snate@binkert.org        AutoDelete = 0x4
775558Snate@binkert.org    };
785558Snate@binkert.org
795558Snate@binkert.org    bool getFlags(Flags f) const { return (_flags & f) == f; }
805558Snate@binkert.org    void setFlags(Flags f) { _flags |= f; }
815558Snate@binkert.org    void clearFlags(Flags f) { _flags &= ~f; }
825558Snate@binkert.org
835558Snate@binkert.org  protected:
845558Snate@binkert.org    EventQueue *theQueue() const { return queue; }
855558Snate@binkert.org
865558Snate@binkert.org#if TRACING_ON
875558Snate@binkert.org    Tick when_created;	//!< Keep track of creation time For debugging
885558Snate@binkert.org    Tick when_scheduled;	//!< Keep track of creation time For debugging
895558Snate@binkert.org
905558Snate@binkert.org    virtual void trace(const char *action);	//!< trace event activity
915558Snate@binkert.org#else
925558Snate@binkert.org    void trace(const char *) {}
935558Snate@binkert.org#endif
945558Snate@binkert.org
955558Snate@binkert.org    unsigned annotated_value;
965558Snate@binkert.org
975558Snate@binkert.org  public:
985558Snate@binkert.org
995558Snate@binkert.org    static const std::string defaultName;
1005558Snate@binkert.org
1015558Snate@binkert.org    /*
1025558Snate@binkert.org     * Event constructor
1035558Snate@binkert.org     * @param queue that the event gets scheduled on
1045558Snate@binkert.org     */
1055558Snate@binkert.org    Event(EventQueue *q, int p = 0)
1065558Snate@binkert.org        : Serializeable(defaultName), queue(q), next(NULL),
1075558Snate@binkert.org          _priority(p), _flags(None),
1085558Snate@binkert.org#if TRACING_ON
1095558Snate@binkert.org          when_created(curTick), when_scheduled(0),
1105558Snate@binkert.org#endif
1115558Snate@binkert.org          annotated_value(0)
1125558Snate@binkert.org    {
1135558Snate@binkert.org    }
1145558Snate@binkert.org
1155558Snate@binkert.org    /*
1165558Snate@binkert.org     * Event constructor
1175558Snate@binkert.org     * @param queue that the event gets scheduled on
1185558Snate@binkert.org     */
1195558Snate@binkert.org    Event(EventQueue *q, std::string _name, int p = 0)
1205558Snate@binkert.org        : Serializeable(_name), queue(q), next(NULL),
1215558Snate@binkert.org          _priority(p), _flags(None),
1225558Snate@binkert.org#if TRACING_ON
1235558Snate@binkert.org          when_created(curTick), when_scheduled(0),
1245558Snate@binkert.org#endif
1255558Snate@binkert.org          annotated_value(0)
1265558Snate@binkert.org    {
1275558Snate@binkert.org    }
1285558Snate@binkert.org
1295558Snate@binkert.org    ~Event() {}
1305558Snate@binkert.org
1315558Snate@binkert.org    /// Determine if the current event is scheduled
1325558Snate@binkert.org    bool scheduled() const { return getFlags(Scheduled); }
1335558Snate@binkert.org
1345558Snate@binkert.org    /// Schedule the event with the current priority or default priority
1355558Snate@binkert.org    void schedule(Tick t);
1365558Snate@binkert.org
1375558Snate@binkert.org    /// Schedule the event with a specific priority
1385558Snate@binkert.org    void schedule(Tick t, int priority);
1395558Snate@binkert.org
1405558Snate@binkert.org    /// Reschedule the event with the current priority
1415558Snate@binkert.org    void reschedule(Tick t);
1425558Snate@binkert.org
1435558Snate@binkert.org    /// Reschedule the event with a specific priority
1445558Snate@binkert.org    void reschedule(Tick t, int priority);
1455558Snate@binkert.org
1465558Snate@binkert.org    /// Remove the event from the current schedule
1475558Snate@binkert.org    void deschedule();
1485558Snate@binkert.org
1495558Snate@binkert.org    /// Return a C string describing the event.  This string should
1505558Snate@binkert.org    /// *not* be dynamically allocated; just a const char array
1515558Snate@binkert.org    /// describing the event class.
1525558Snate@binkert.org    virtual const char *description();
1535558Snate@binkert.org
1545558Snate@binkert.org    /// Dump the current event data
1555558Snate@binkert.org    void dump();
1565558Snate@binkert.org
1575558Snate@binkert.org    /*
1585558Snate@binkert.org     * This member function is invoked when the event is processed
1595558Snate@binkert.org     * (occurs).  There is no default implementation; each subclass
1605558Snate@binkert.org     * must provide its own implementation.  The event is not
1615558Snate@binkert.org     * automatically deleted after it is processed (to allow for
1625558Snate@binkert.org     * statically allocated event objects).
1635558Snate@binkert.org     *
1645558Snate@binkert.org     * If the AutoDestroy flag is set, the object is deleted once it
1655558Snate@binkert.org     * is processed.
1665558Snate@binkert.org     */
1675558Snate@binkert.org    virtual void process() = 0;
1685558Snate@binkert.org
1695558Snate@binkert.org    void annotate(unsigned value) { annotated_value = value; };
1705558Snate@binkert.org    unsigned annotation() { return annotated_value; }
1715558Snate@binkert.org
1725558Snate@binkert.org    /// Squash the current event
1735558Snate@binkert.org    void squash() { setFlags(Squashed); }
1745558Snate@binkert.org
1755558Snate@binkert.org    /// Check whether the event is squashed
1765558Snate@binkert.org    bool squashed() { return getFlags(Squashed); }
1775558Snate@binkert.org
1785558Snate@binkert.org    /// Get the time that the event is scheduled
1795558Snate@binkert.org    Tick when() const { return _when; }
1805558Snate@binkert.org
1815558Snate@binkert.org    /// Get the event priority
1825558Snate@binkert.org    int priority() const { return _priority; }
1835558Snate@binkert.org
1845558Snate@binkert.org    struct priority_compare :
1855558Snate@binkert.org    public std::binary_function<Event *, Event *, bool>
1865558Snate@binkert.org    {
1875558Snate@binkert.org        bool operator()(const Event *l, const Event *r) const {
1885558Snate@binkert.org            return l->when() >= r->when() || l->priority() >= r->priority();
1895558Snate@binkert.org        }
1905558Snate@binkert.org    };
1915558Snate@binkert.org
1925558Snate@binkert.org    virtual void serialize(std::ostream &os);
1935558Snate@binkert.org    virtual void unserialize(const IniFile *db, const std::string &section);
1945558Snate@binkert.org};
1955558Snate@binkert.org
1965558Snate@binkert.orgtemplate <class T, void (T::* F)()>
1975558Snate@binkert.orgvoid
1985558Snate@binkert.orgDelayFunction(Tick when, T *object)
1995558Snate@binkert.org{
2005558Snate@binkert.org    class DelayEvent : public Event
2015558Snate@binkert.org    {
2025558Snate@binkert.org      private:
2035558Snate@binkert.org        T *object;
2045558Snate@binkert.org
205      public:
206        DelayEvent(Tick when, T *o)
207            : Event(&mainEventQueue), object(o)
208            { setFlags(AutoDestroy); schedule(when); }
209        void process() { (object->*F)(); }
210        const char *description() { return "delay"; }
211    };
212
213    new DelayEvent(when, object);
214}
215
216/*
217 * Queue of events sorted in time order
218 */
219class EventQueue : public Serializeable
220{
221  private:
222    Event *head;
223
224    void insert(Event *event);
225    void remove(Event *event);
226
227  public:
228
229    // constructor
230    EventQueue(const std::string &n)
231        : Serializeable(n), head(NULL)
232    {}
233
234    // schedule the given event on this queue
235    void schedule(Event *ev);
236    void deschedule(Event *ev);
237    void reschedule(Event *ev);
238
239    Tick nextTick() { return head->when(); }
240    void serviceOne();
241
242    // process all events up to the given timestamp.  we inline a
243    // quick test to see if there are any events to process; if so,
244    // call the internal out-of-line version to process them all.
245    void serviceEvents(Tick when) {
246        while (!empty()) {
247            if (nextTick() > when)
248                break;
249
250            assert(head->when() >= when && "event scheduled in the past");
251            serviceOne();
252        }
253    }
254
255    // default: process all events up to 'now' (curTick)
256    void serviceEvents() { serviceEvents(curTick); }
257
258    // return true if no events are queued
259    bool empty() { return head == NULL; }
260
261    void dump();
262
263    Tick nextEventTime() { return empty() ? curTick : head->when(); }
264
265    virtual void nameChildren();
266    virtual void serialize(std::ostream &os);
267};
268
269
270//////////////////////
271//
272// inline functions
273//
274// can't put these inside declaration due to circular dependence
275// between Event and EventQueue classes.
276//
277//////////////////////
278
279// schedule at specified time (place on event queue specified via
280// constructor)
281inline void
282Event::schedule(Tick t)
283{
284    assert(!scheduled());
285    setFlags(Scheduled);
286#if TRACING_ON
287    when_scheduled = curTick;
288#endif
289    _when = t;
290    queue->schedule(this);
291}
292
293inline void
294Event::schedule(Tick t, int p)
295{
296    _priority = p;
297    schedule(t);
298}
299
300inline void
301Event::deschedule()
302{
303    assert(scheduled());
304
305    clearFlags(Squashed);
306    clearFlags(Scheduled);
307    queue->deschedule(this);
308}
309
310inline void
311Event::reschedule(Tick t)
312{
313    assert(scheduled());
314    clearFlags(Squashed);
315
316#if TRACING_ON
317    when_scheduled = curTick;
318#endif
319    _when = t;
320    queue->reschedule(this);
321}
322
323inline void
324Event::reschedule(Tick t, int p)
325{
326    _priority = p;
327    reschedule(t);
328}
329
330inline void
331EventQueue::schedule(Event *event)
332{
333    insert(event);
334    if (DTRACE(Event))
335        event->trace("scheduled");
336}
337
338inline void
339EventQueue::deschedule(Event *event)
340{
341    remove(event);
342    if (DTRACE(Event))
343        event->trace("descheduled");
344}
345
346inline void
347EventQueue::reschedule(Event *event)
348{
349    remove(event);
350    insert(event);
351    if (DTRACE(Event))
352        event->trace("rescheduled");
353}
354
355
356//////////////////////
357//
358// Main Event Queue
359//
360// Events on this queue are processed at the *beginning* of each
361// cycle, before the pipeline simulation is performed.
362//
363// defined in eventq.cc
364//
365//////////////////////
366extern EventQueue mainEventQueue;
367
368#endif // __EVENTQ_HH__
369