eventq.hh revision 270
11758SN/A/* 21762SN/A * Copyright (c) 2003 The Regents of The University of Michigan 31758SN/A * All rights reserved. 41758SN/A * 51758SN/A * Redistribution and use in source and binary forms, with or without 61758SN/A * modification, are permitted provided that the following conditions are 71758SN/A * met: redistributions of source code must retain the above copyright 81758SN/A * notice, this list of conditions and the following disclaimer; 91758SN/A * redistributions in binary form must reproduce the above copyright 101758SN/A * notice, this list of conditions and the following disclaimer in the 111758SN/A * documentation and/or other materials provided with the distribution; 121758SN/A * neither the name of the copyright holders nor the names of its 131758SN/A * contributors may be used to endorse or promote products derived from 141758SN/A * this software without specific prior written permission. 151758SN/A * 161758SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171758SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181758SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191758SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201758SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211758SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221758SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231758SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241758SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251758SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261758SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292665Ssaidi@eecs.umich.edu/* @file 301758SN/A * EventQueue interfaces 312SN/A */ 322984Sgblack@eecs.umich.edu 33732SN/A#ifndef __EVENTQ_HH__ 343565Sgblack@eecs.umich.edu#define __EVENTQ_HH__ 35732SN/A 362984Sgblack@eecs.umich.edu#include <assert.h> 375953Ssaidi@eecs.umich.edu 385882Snate@binkert.org#include <algorithm> 391717SN/A#include <map> 402683Sktlim@umich.edu#include <string> 412680Sktlim@umich.edu#include <vector> 422710Sstever@eecs.umich.edu 432SN/A#include "sim/host.hh" // for Tick 445568Snate@binkert.org 455566Snate@binkert.org#include "base/fast_alloc.hh" 4612406Sgabeblack@google.com#include "sim/serialize.hh" 4712406Sgabeblack@google.com#include "base/trace.hh" 4812406Sgabeblack@google.com 4912406Sgabeblack@google.comclass EventQueue; // forward declaration 5012406Sgabeblack@google.com 5112406Sgabeblack@google.com/* 5212406Sgabeblack@google.com * An item on an event queue. The action caused by a given 5312406Sgabeblack@google.com * event is specified by deriving a subclass and overriding the 5412406Sgabeblack@google.com * process() member function. 5512406Sgabeblack@google.com */ 5612406Sgabeblack@google.comclass Event : public Serializeable, public FastAlloc 5712406Sgabeblack@google.com{ 5812406Sgabeblack@google.com friend class EventQueue; 5912406Sgabeblack@google.com 6012406Sgabeblack@google.com private: 6112406Sgabeblack@google.com /// queue to which this event belongs (though it may or may not be 6212406Sgabeblack@google.com /// scheduled on this queue yet) 6312406Sgabeblack@google.com EventQueue *queue; 642SN/A 652SN/A Event *next; 662SN/A 672SN/A Tick _when; //!< timestamp when event should be processed 682SN/A int _priority; //!< event priority 695568Snate@binkert.org char _flags; 702SN/A 712680Sktlim@umich.edu protected: 72190SN/A enum Flags { 732680Sktlim@umich.edu None = 0x0, 742680Sktlim@umich.edu Squashed = 0x1, 752114SN/A Scheduled = 0x2, 765568Snate@binkert.org AutoDelete = 0x4, 772700Sktlim@umich.edu AutoSerialize = 0x8 787720Sgblack@eecs.umich.edu }; 792700Sktlim@umich.edu 802700Sktlim@umich.edu bool getFlags(Flags f) const { return (_flags & f) == f; } 812SN/A void setFlags(Flags f) { _flags |= f; } 822SN/A void clearFlags(Flags f) { _flags &= ~f; } 831133SN/A 84716SN/A protected: 855568Snate@binkert.org EventQueue *theQueue() const { return queue; } 86716SN/A 87716SN/A#if TRACING_ON 88739SN/A Tick when_created; //!< Keep track of creation time For debugging 89739SN/A Tick when_scheduled; //!< Keep track of creation time For debugging 902683Sktlim@umich.edu 912683Sktlim@umich.edu virtual void trace(const char *action); //!< trace event activity 92716SN/A#else 93716SN/A void trace(const char *) {} 944997Sgblack@eecs.umich.edu#endif 954997Sgblack@eecs.umich.edu 964997Sgblack@eecs.umich.edu unsigned annotated_value; 974997Sgblack@eecs.umich.edu 984997Sgblack@eecs.umich.edu public: 995568Snate@binkert.org 1004997Sgblack@eecs.umich.edu /* 1014997Sgblack@eecs.umich.edu * Event constructor 1024997Sgblack@eecs.umich.edu * @param queue that the event gets scheduled on 1034997Sgblack@eecs.umich.edu */ 1044997Sgblack@eecs.umich.edu Event(EventQueue *q, int p = 0) 1055568Snate@binkert.org : queue(q), next(NULL), _priority(p), _flags(None), 1064997Sgblack@eecs.umich.edu#if TRACING_ON 1074997Sgblack@eecs.umich.edu when_created(curTick), when_scheduled(0), 1084997Sgblack@eecs.umich.edu#endif 1094997Sgblack@eecs.umich.edu annotated_value(0) 1105568Snate@binkert.org { 1116330Sgblack@eecs.umich.edu } 1122159SN/A 1135543Ssaidi@eecs.umich.edu ~Event() {} 1142SN/A 1152SN/A virtual std::string name() const { 1165568Snate@binkert.org return csprintf("Event_%x", (uintptr_t)this); 1175568Snate@binkert.org } 1185568Snate@binkert.org 1195568Snate@binkert.org /// Determine if the current event is scheduled 1205568Snate@binkert.org bool scheduled() const { return getFlags(Scheduled); } 1215568Snate@binkert.org 1225568Snate@binkert.org /// Schedule the event with the current priority or default priority 1235568Snate@binkert.org void schedule(Tick t); 1245568Snate@binkert.org 1255568Snate@binkert.org /// Schedule the event with a specific priority 1265568Snate@binkert.org void schedule(Tick t, int priority); 1275568Snate@binkert.org 1285568Snate@binkert.org /// Reschedule the event with the current priority 1295568Snate@binkert.org void reschedule(Tick t); 1305568Snate@binkert.org 1315568Snate@binkert.org /// Reschedule the event with a specific priority 1325568Snate@binkert.org void reschedule(Tick t, int priority); 1335568Snate@binkert.org 1345568Snate@binkert.org /// Remove the event from the current schedule 1355568Snate@binkert.org void deschedule(); 1365568Snate@binkert.org 1375568Snate@binkert.org /// Return a C string describing the event. This string should 1385568Snate@binkert.org /// *not* be dynamically allocated; just a const char array 1395568Snate@binkert.org /// describing the event class. 1405568Snate@binkert.org virtual const char *description(); 1412SN/A 1425568Snate@binkert.org /// Dump the current event data 1435568Snate@binkert.org void dump(); 1445568Snate@binkert.org 1455568Snate@binkert.org /* 1465568Snate@binkert.org * This member function is invoked when the event is processed 1475568Snate@binkert.org * (occurs). There is no default implementation; each subclass 1485568Snate@binkert.org * must provide its own implementation. The event is not 1495568Snate@binkert.org * automatically deleted after it is processed (to allow for 1505568Snate@binkert.org * statically allocated event objects). 1515568Snate@binkert.org * 1525568Snate@binkert.org * If the AutoDestroy flag is set, the object is deleted once it 1535568Snate@binkert.org * is processed. 1545568Snate@binkert.org */ 1555568Snate@binkert.org virtual void process() = 0; 1565568Snate@binkert.org 1575568Snate@binkert.org void annotate(unsigned value) { annotated_value = value; }; 1585568Snate@binkert.org unsigned annotation() { return annotated_value; } 1592SN/A 1602SN/A /// Squash the current event 1612SN/A void squash() { setFlags(Squashed); } 1622SN/A 1635568Snate@binkert.org /// Check whether the event is squashed 164597SN/A bool squashed() { return getFlags(Squashed); } 1652680Sktlim@umich.edu 166597SN/A /// Get the time that the event is scheduled 167597SN/A Tick when() const { return _when; } 1685568Snate@binkert.org 1692SN/A /// Get the event priority 1702SN/A int priority() const { return _priority; } 1712SN/A 1725568Snate@binkert.org struct priority_compare : 1735568Snate@binkert.org public std::binary_function<Event *, Event *, bool> 1745568Snate@binkert.org { 1755568Snate@binkert.org bool operator()(const Event *l, const Event *r) const { 1765568Snate@binkert.org return l->when() >= r->when() || l->priority() >= r->priority(); 1772SN/A } 1782SN/A }; 1792SN/A 1805568Snate@binkert.org virtual void serialize(std::ostream &os); 1812SN/A virtual void unserialize(Checkpoint *cp, const std::string §ion); 18212406Sgabeblack@google.com}; 1832SN/A 1845004Sgblack@eecs.umich.edutemplate <class T, void (T::* F)()> 1855004Sgblack@eecs.umich.eduvoid 1865004Sgblack@eecs.umich.eduDelayFunction(Tick when, T *object) 1875004Sgblack@eecs.umich.edu{ 1885004Sgblack@eecs.umich.edu class DelayEvent : public Event 1895004Sgblack@eecs.umich.edu { 1905004Sgblack@eecs.umich.edu private: 1912SN/A T *object; 1922SN/A 1932SN/A public: 1942SN/A DelayEvent(Tick when, T *o) 1955568Snate@binkert.org : Event(&mainEventQueue), object(o) 1965568Snate@binkert.org { setFlags(AutoDestroy); schedule(when); } 1975568Snate@binkert.org void process() { (object->*F)(); } 1985568Snate@binkert.org const char *description() { return "delay"; } 1995568Snate@binkert.org }; 2005568Snate@binkert.org 2015568Snate@binkert.org new DelayEvent(when, object); 2025568Snate@binkert.org} 2035568Snate@binkert.org 2043468Sgblack@eecs.umich.edu/* 2052SN/A * Queue of events sorted in time order 2062SN/A */ 2072SN/Aclass EventQueue : public Serializeable 2082SN/A{ 2093468Sgblack@eecs.umich.edu protected: 2102SN/A std::string objName; 2112SN/A 2122SN/A private: 2132SN/A Event *head; 2142SN/A 2152SN/A void insert(Event *event); 2162SN/A void remove(Event *event); 2172SN/A 2182SN/A public: 2193468Sgblack@eecs.umich.edu 2206330Sgblack@eecs.umich.edu // constructor 2212SN/A EventQueue(const std::string &n) 2222SN/A : objName(n), head(NULL) 2235568Snate@binkert.org {} 2245568Snate@binkert.org 2255568Snate@binkert.org virtual std::string name() const { return objName; } 2265568Snate@binkert.org 2275568Snate@binkert.org // schedule the given event on this queue 2285568Snate@binkert.org void schedule(Event *ev); 2295568Snate@binkert.org void deschedule(Event *ev); 2305568Snate@binkert.org void reschedule(Event *ev); 2315568Snate@binkert.org 2325568Snate@binkert.org Tick nextTick() { return head->when(); } 2335568Snate@binkert.org void serviceOne(); 2345568Snate@binkert.org 2355568Snate@binkert.org // process all events up to the given timestamp. we inline a 2365568Snate@binkert.org // quick test to see if there are any events to process; if so, 2375568Snate@binkert.org // call the internal out-of-line version to process them all. 2385568Snate@binkert.org void serviceEvents(Tick when) { 2395568Snate@binkert.org while (!empty()) { 2405568Snate@binkert.org if (nextTick() > when) 2415568Snate@binkert.org break; 2425568Snate@binkert.org 2435568Snate@binkert.org assert(head->when() >= when && "event scheduled in the past"); 2445568Snate@binkert.org serviceOne(); 2455568Snate@binkert.org } 2465568Snate@binkert.org } 2475568Snate@binkert.org 2485568Snate@binkert.org // default: process all events up to 'now' (curTick) 2495568Snate@binkert.org void serviceEvents() { serviceEvents(curTick); } 2502SN/A 2512SN/A // return true if no events are queued 2522SN/A bool empty() { return head == NULL; } 2532SN/A 2545568Snate@binkert.org void dump(); 255596SN/A 256596SN/A Tick nextEventTime() { return empty() ? curTick : head->when(); } 257596SN/A 258596SN/A virtual void serialize(std::ostream &os); 259596SN/A virtual void unserialize(Checkpoint *cp, const std::string §ion); 260596SN/A}; 2615568Snate@binkert.org 262596SN/A 263596SN/A////////////////////// 264596SN/A// 265596SN/A// inline functions 266596SN/A// 267596SN/A// can't put these inside declaration due to circular dependence 2685568Snate@binkert.org// between Event and EventQueue classes. 2692SN/A// 2702680Sktlim@umich.edu////////////////////// 2718607Sgblack@eecs.umich.edu 2728607Sgblack@eecs.umich.edu// schedule at specified time (place on event queue specified via 2732SN/A// constructor) 2742SN/Ainline void 2755568Snate@binkert.orgEvent::schedule(Tick t) 2762SN/A{ 2772SN/A assert(!scheduled()); 2782SN/A setFlags(Scheduled); 2792SN/A#if TRACING_ON 2805568Snate@binkert.org when_scheduled = curTick; 2812SN/A#endif 2822SN/A _when = t; 2832SN/A queue->schedule(this); 2842SN/A} 2855568Snate@binkert.org 2865568Snate@binkert.orginline void 2872SN/AEvent::schedule(Tick t, int p) 2882SN/A{ 2892SN/A _priority = p; 2902SN/A schedule(t); 2915568Snate@binkert.org} 2922SN/A 2932SN/Ainline void 2942680Sktlim@umich.eduEvent::deschedule() 2952680Sktlim@umich.edu{ 2962SN/A assert(scheduled()); 2972SN/A 2985568Snate@binkert.org clearFlags(Squashed); 2992330SN/A clearFlags(Scheduled); 3002680Sktlim@umich.edu queue->deschedule(this); 3015568Snate@binkert.org} 3022341SN/A 3032680Sktlim@umich.eduinline void 3045568Snate@binkert.orgEvent::reschedule(Tick t) 3052330SN/A{ 3062SN/A assert(scheduled()); 3075568Snate@binkert.org clearFlags(Squashed); 3082SN/A 3092SN/A#if TRACING_ON 3102SN/A when_scheduled = curTick; 3112SN/A#endif 3125568Snate@binkert.org _when = t; 3132SN/A queue->reschedule(this); 3142SN/A} 3152SN/A 3162SN/Ainline void 3175568Snate@binkert.orgEvent::reschedule(Tick t, int p) 3182SN/A{ 3192SN/A _priority = p; 3202SN/A reschedule(t); 3212SN/A} 3225568Snate@binkert.org 3232SN/Ainline void 3242SN/AEventQueue::schedule(Event *event) 3252SN/A{ 3262SN/A insert(event); 3275568Snate@binkert.org if (DTRACE(Event)) 3282SN/A event->trace("scheduled"); 3292SN/A} 3302SN/A 3315568Snate@binkert.orginline void 3325568Snate@binkert.orgEventQueue::deschedule(Event *event) 3332SN/A{ 3342SN/A remove(event); 3352SN/A if (DTRACE(Event)) 3365568Snate@binkert.org event->trace("descheduled"); 3372SN/A} 3382SN/A 3392SN/Ainline void 3405568Snate@binkert.orgEventQueue::reschedule(Event *event) 3415568Snate@binkert.org{ 3422SN/A remove(event); 3432SN/A insert(event); 3442SN/A if (DTRACE(Event)) 3455568Snate@binkert.org event->trace("rescheduled"); 3462SN/A} 3472SN/A 3482SN/A 3495568Snate@binkert.org////////////////////// 3502SN/A// 3512SN/A// Main Event Queue 3522SN/A// 3535568Snate@binkert.org// Events on this queue are processed at the *beginning* of each 3545568Snate@binkert.org// cycle, before the pipeline simulation is performed. 3552SN/A// 3562SN/A// defined in eventq.cc 3572SN/A// 3582SN/A////////////////////// 3595568Snate@binkert.orgextern EventQueue mainEventQueue; 3605568Snate@binkert.org 3615568Snate@binkert.org#endif // __EVENTQ_HH__ 3625568Snate@binkert.org