eventq.hh revision 265
16313Sgblack@eecs.umich.edu/* 27093Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan 37093Sgblack@eecs.umich.edu * All rights reserved. 47093Sgblack@eecs.umich.edu * 57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146313Sgblack@eecs.umich.edu * this software without specific prior written permission. 156313Sgblack@eecs.umich.edu * 166313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276313Sgblack@eecs.umich.edu */ 286313Sgblack@eecs.umich.edu 296313Sgblack@eecs.umich.edu/* @file 306313Sgblack@eecs.umich.edu * EventQueue interfaces 316313Sgblack@eecs.umich.edu */ 326313Sgblack@eecs.umich.edu 336313Sgblack@eecs.umich.edu#ifndef __EVENTQ_HH__ 346313Sgblack@eecs.umich.edu#define __EVENTQ_HH__ 356313Sgblack@eecs.umich.edu 366313Sgblack@eecs.umich.edu#include <assert.h> 376313Sgblack@eecs.umich.edu 386313Sgblack@eecs.umich.edu#include <algorithm> 396313Sgblack@eecs.umich.edu#include <map> 406313Sgblack@eecs.umich.edu#include <string> 416313Sgblack@eecs.umich.edu#include <vector> 426313Sgblack@eecs.umich.edu 436313Sgblack@eecs.umich.edu#include "sim/host.hh" // for Tick 446313Sgblack@eecs.umich.edu 456313Sgblack@eecs.umich.edu#include "base/fast_alloc.hh" 466333Sgblack@eecs.umich.edu#include "sim/serialize.hh" 476313Sgblack@eecs.umich.edu#include "base/trace.hh" 486313Sgblack@eecs.umich.edu 496333Sgblack@eecs.umich.educlass EventQueue; // forward declaration 506313Sgblack@eecs.umich.edu 516313Sgblack@eecs.umich.edu/* 526313Sgblack@eecs.umich.edu * An item on an event queue. The action caused by a given 536313Sgblack@eecs.umich.edu * event is specified by deriving a subclass and overriding the 546313Sgblack@eecs.umich.edu * process() member function. 556313Sgblack@eecs.umich.edu */ 566313Sgblack@eecs.umich.educlass Event : public Serializeable, public FastAlloc 576313Sgblack@eecs.umich.edu{ 586333Sgblack@eecs.umich.edu friend class EventQueue; 596718Sgblack@eecs.umich.edu 606718Sgblack@eecs.umich.edu private: 616718Sgblack@eecs.umich.edu /// queue to which this event belongs (though it may or may not be 626718Sgblack@eecs.umich.edu /// scheduled on this queue yet) 636718Sgblack@eecs.umich.edu EventQueue *queue; 646718Sgblack@eecs.umich.edu 656718Sgblack@eecs.umich.edu Event *next; 666718Sgblack@eecs.umich.edu 676718Sgblack@eecs.umich.edu Tick _when; //!< timestamp when event should be processed 686718Sgblack@eecs.umich.edu int _priority; //!< event priority 696718Sgblack@eecs.umich.edu char _flags; 706718Sgblack@eecs.umich.edu 716718Sgblack@eecs.umich.edu protected: 726718Sgblack@eecs.umich.edu enum Flags { 736718Sgblack@eecs.umich.edu None = 0x0, 746718Sgblack@eecs.umich.edu Squashed = 0x1, 756718Sgblack@eecs.umich.edu Scheduled = 0x2, 766718Sgblack@eecs.umich.edu AutoDelete = 0x4, 776718Sgblack@eecs.umich.edu AutoSerialize = 0x8 786723Sgblack@eecs.umich.edu }; 796723Sgblack@eecs.umich.edu 806723Sgblack@eecs.umich.edu bool getFlags(Flags f) const { return (_flags & f) == f; } 816718Sgblack@eecs.umich.edu void setFlags(Flags f) { _flags |= f; } 826718Sgblack@eecs.umich.edu void clearFlags(Flags f) { _flags &= ~f; } 836718Sgblack@eecs.umich.edu 846718Sgblack@eecs.umich.edu protected: 856718Sgblack@eecs.umich.edu EventQueue *theQueue() const { return queue; } 866718Sgblack@eecs.umich.edu 876718Sgblack@eecs.umich.edu#if TRACING_ON 886718Sgblack@eecs.umich.edu Tick when_created; //!< Keep track of creation time For debugging 896718Sgblack@eecs.umich.edu Tick when_scheduled; //!< Keep track of creation time For debugging 906718Sgblack@eecs.umich.edu 916313Sgblack@eecs.umich.edu virtual void trace(const char *action); //!< trace event activity 926313Sgblack@eecs.umich.edu#else 936333Sgblack@eecs.umich.edu void trace(const char *) {} 946333Sgblack@eecs.umich.edu#endif 956401Sgblack@eecs.umich.edu 966401Sgblack@eecs.umich.edu unsigned annotated_value; 976719Sgblack@eecs.umich.edu 986401Sgblack@eecs.umich.edu public: 996718Sgblack@eecs.umich.edu 1006735Sgblack@eecs.umich.edu static const std::string defaultName; 1016735Sgblack@eecs.umich.edu 1026735Sgblack@eecs.umich.edu /* 1036735Sgblack@eecs.umich.edu * Event constructor 1046735Sgblack@eecs.umich.edu * @param queue that the event gets scheduled on 1056735Sgblack@eecs.umich.edu */ 1066735Sgblack@eecs.umich.edu Event(EventQueue *q, int p = 0) 1077270Sgblack@eecs.umich.edu : queue(q), next(NULL), _priority(p), _flags(None), 1086735Sgblack@eecs.umich.edu#if TRACING_ON 1096401Sgblack@eecs.umich.edu when_created(curTick), when_scheduled(0), 1106333Sgblack@eecs.umich.edu#endif 1116313Sgblack@eecs.umich.edu annotated_value(0) 1126333Sgblack@eecs.umich.edu { 1136333Sgblack@eecs.umich.edu } 1146333Sgblack@eecs.umich.edu 1156333Sgblack@eecs.umich.edu ~Event() {} 1166745Sgblack@eecs.umich.edu 1176745Sgblack@eecs.umich.edu virtual std::string name() const { 1186745Sgblack@eecs.umich.edu return csprintf("%s_%x", defaultName, (uintptr_t)this); 1196745Sgblack@eecs.umich.edu } 1206745Sgblack@eecs.umich.edu 1216745Sgblack@eecs.umich.edu /// Determine if the current event is scheduled 1226745Sgblack@eecs.umich.edu bool scheduled() const { return getFlags(Scheduled); } 1236745Sgblack@eecs.umich.edu 1246745Sgblack@eecs.umich.edu /// Schedule the event with the current priority or default priority 1256745Sgblack@eecs.umich.edu void schedule(Tick t); 1266745Sgblack@eecs.umich.edu 1276745Sgblack@eecs.umich.edu /// Schedule the event with a specific priority 1286745Sgblack@eecs.umich.edu void schedule(Tick t, int priority); 1296745Sgblack@eecs.umich.edu 1306745Sgblack@eecs.umich.edu /// Reschedule the event with the current priority 1316745Sgblack@eecs.umich.edu void reschedule(Tick t); 1326745Sgblack@eecs.umich.edu 1336745Sgblack@eecs.umich.edu /// Reschedule the event with a specific priority 1346745Sgblack@eecs.umich.edu void reschedule(Tick t, int priority); 1356745Sgblack@eecs.umich.edu 1366745Sgblack@eecs.umich.edu /// Remove the event from the current schedule 1376333Sgblack@eecs.umich.edu void deschedule(); 1386333Sgblack@eecs.umich.edu 1396313Sgblack@eecs.umich.edu /// Return a C string describing the event. This string should 1406333Sgblack@eecs.umich.edu /// *not* be dynamically allocated; just a const char array 1416333Sgblack@eecs.umich.edu /// describing the event class. 1426333Sgblack@eecs.umich.edu virtual const char *description(); 1437093Sgblack@eecs.umich.edu 1447093Sgblack@eecs.umich.edu /// Dump the current event data 1457093Sgblack@eecs.umich.edu void dump(); 1467093Sgblack@eecs.umich.edu 1477093Sgblack@eecs.umich.edu /* 1487093Sgblack@eecs.umich.edu * This member function is invoked when the event is processed 1497093Sgblack@eecs.umich.edu * (occurs). There is no default implementation; each subclass 1507093Sgblack@eecs.umich.edu * must provide its own implementation. The event is not 1517093Sgblack@eecs.umich.edu * automatically deleted after it is processed (to allow for 1527093Sgblack@eecs.umich.edu * statically allocated event objects). 1537093Sgblack@eecs.umich.edu * 1547093Sgblack@eecs.umich.edu * If the AutoDestroy flag is set, the object is deleted once it 1557093Sgblack@eecs.umich.edu * is processed. 1567259Sgblack@eecs.umich.edu */ 1577259Sgblack@eecs.umich.edu virtual void process() = 0; 1587259Sgblack@eecs.umich.edu 1597259Sgblack@eecs.umich.edu void annotate(unsigned value) { annotated_value = value; }; 1607259Sgblack@eecs.umich.edu unsigned annotation() { return annotated_value; } 1616745Sgblack@eecs.umich.edu 1626333Sgblack@eecs.umich.edu /// Squash the current event 1636333Sgblack@eecs.umich.edu void squash() { setFlags(Squashed); } 1646333Sgblack@eecs.umich.edu 1656333Sgblack@eecs.umich.edu /// Check whether the event is squashed 1666333Sgblack@eecs.umich.edu bool squashed() { return getFlags(Squashed); } 1676333Sgblack@eecs.umich.edu 1686745Sgblack@eecs.umich.edu /// Get the time that the event is scheduled 1696745Sgblack@eecs.umich.edu Tick when() const { return _when; } 1706745Sgblack@eecs.umich.edu 1716745Sgblack@eecs.umich.edu /// Get the event priority 1726745Sgblack@eecs.umich.edu int priority() const { return _priority; } 1736745Sgblack@eecs.umich.edu 1746745Sgblack@eecs.umich.edu struct priority_compare : 1756745Sgblack@eecs.umich.edu public std::binary_function<Event *, Event *, bool> 1766745Sgblack@eecs.umich.edu { 1776745Sgblack@eecs.umich.edu bool operator()(const Event *l, const Event *r) const { 1786745Sgblack@eecs.umich.edu return l->when() >= r->when() || l->priority() >= r->priority(); 1796745Sgblack@eecs.umich.edu } 1806745Sgblack@eecs.umich.edu }; 1816745Sgblack@eecs.umich.edu 1826745Sgblack@eecs.umich.edu virtual void serialize(std::ostream &os); 1836745Sgblack@eecs.umich.edu virtual void unserialize(Checkpoint *cp, const std::string §ion); 1846745Sgblack@eecs.umich.edu}; 1856745Sgblack@eecs.umich.edu 1866745Sgblack@eecs.umich.edutemplate <class T, void (T::* F)()> 1876745Sgblack@eecs.umich.eduvoid 1886745Sgblack@eecs.umich.eduDelayFunction(Tick when, T *object) 1896745Sgblack@eecs.umich.edu{ 1906745Sgblack@eecs.umich.edu class DelayEvent : public Event 1916745Sgblack@eecs.umich.edu { 1926745Sgblack@eecs.umich.edu private: 1936745Sgblack@eecs.umich.edu T *object; 1946745Sgblack@eecs.umich.edu 1956745Sgblack@eecs.umich.edu public: 1966745Sgblack@eecs.umich.edu DelayEvent(Tick when, T *o) 1976333Sgblack@eecs.umich.edu : Event(&mainEventQueue), object(o) 1986333Sgblack@eecs.umich.edu { setFlags(AutoDestroy); schedule(when); } 1996333Sgblack@eecs.umich.edu void process() { (object->*F)(); } 2006333Sgblack@eecs.umich.edu const char *description() { return "delay"; } 2016333Sgblack@eecs.umich.edu }; 2026333Sgblack@eecs.umich.edu 2036718Sgblack@eecs.umich.edu new DelayEvent(when, object); 2046718Sgblack@eecs.umich.edu} 2057093Sgblack@eecs.umich.edu 2067093Sgblack@eecs.umich.edu/* 2077093Sgblack@eecs.umich.edu * Queue of events sorted in time order 2087093Sgblack@eecs.umich.edu */ 2097093Sgblack@eecs.umich.educlass EventQueue : public Serializeable 2107093Sgblack@eecs.umich.edu{ 2117093Sgblack@eecs.umich.edu protected: 2127093Sgblack@eecs.umich.edu std::string objName; 2136718Sgblack@eecs.umich.edu 2147259Sgblack@eecs.umich.edu private: 2157259Sgblack@eecs.umich.edu Event *head; 2167259Sgblack@eecs.umich.edu 2177259Sgblack@eecs.umich.edu void insert(Event *event); 2187259Sgblack@eecs.umich.edu void remove(Event *event); 2196745Sgblack@eecs.umich.edu 2206333Sgblack@eecs.umich.edu public: 2216313Sgblack@eecs.umich.edu 2226313Sgblack@eecs.umich.edu // constructor 2236313Sgblack@eecs.umich.edu EventQueue(const std::string &n) 2246313Sgblack@eecs.umich.edu : objName(n), head(NULL) 2256718Sgblack@eecs.umich.edu {} 2266718Sgblack@eecs.umich.edu 2276718Sgblack@eecs.umich.edu virtual std::string name() const { return objName; } 2286726Sgblack@eecs.umich.edu 2296726Sgblack@eecs.umich.edu // schedule the given event on this queue 2306718Sgblack@eecs.umich.edu void schedule(Event *ev); 2316726Sgblack@eecs.umich.edu void deschedule(Event *ev); 2326726Sgblack@eecs.umich.edu void reschedule(Event *ev); 2336718Sgblack@eecs.umich.edu 2346718Sgblack@eecs.umich.edu Tick nextTick() { return head->when(); } 2356313Sgblack@eecs.umich.edu void serviceOne(); 2366313Sgblack@eecs.umich.edu 2376313Sgblack@eecs.umich.edu // process all events up to the given timestamp. we inline a 2386313Sgblack@eecs.umich.edu // quick test to see if there are any events to process; if so, 2396313Sgblack@eecs.umich.edu // call the internal out-of-line version to process them all. 2406313Sgblack@eecs.umich.edu void serviceEvents(Tick when) { 2416313Sgblack@eecs.umich.edu while (!empty()) { 2426313Sgblack@eecs.umich.edu if (nextTick() > when) 2436678Sgblack@eecs.umich.edu break; 2446333Sgblack@eecs.umich.edu 2456678Sgblack@eecs.umich.edu assert(head->when() >= when && "event scheduled in the past"); 2466678Sgblack@eecs.umich.edu serviceOne(); 2476333Sgblack@eecs.umich.edu } 2486313Sgblack@eecs.umich.edu } 2496313Sgblack@eecs.umich.edu 2506313Sgblack@eecs.umich.edu // default: process all events up to 'now' (curTick) 2516313Sgblack@eecs.umich.edu void serviceEvents() { serviceEvents(curTick); } 2526313Sgblack@eecs.umich.edu 2536313Sgblack@eecs.umich.edu // return true if no events are queued 2546313Sgblack@eecs.umich.edu bool empty() { return head == NULL; } 2556313Sgblack@eecs.umich.edu 2566313Sgblack@eecs.umich.edu void dump(); 257 258 Tick nextEventTime() { return empty() ? curTick : head->when(); } 259 260 virtual void serialize(std::ostream &os); 261 virtual void unserialize(Checkpoint *cp, const std::string §ion); 262}; 263 264 265////////////////////// 266// 267// inline functions 268// 269// can't put these inside declaration due to circular dependence 270// between Event and EventQueue classes. 271// 272////////////////////// 273 274// schedule at specified time (place on event queue specified via 275// constructor) 276inline void 277Event::schedule(Tick t) 278{ 279 assert(!scheduled()); 280 setFlags(Scheduled); 281#if TRACING_ON 282 when_scheduled = curTick; 283#endif 284 _when = t; 285 queue->schedule(this); 286} 287 288inline void 289Event::schedule(Tick t, int p) 290{ 291 _priority = p; 292 schedule(t); 293} 294 295inline void 296Event::deschedule() 297{ 298 assert(scheduled()); 299 300 clearFlags(Squashed); 301 clearFlags(Scheduled); 302 queue->deschedule(this); 303} 304 305inline void 306Event::reschedule(Tick t) 307{ 308 assert(scheduled()); 309 clearFlags(Squashed); 310 311#if TRACING_ON 312 when_scheduled = curTick; 313#endif 314 _when = t; 315 queue->reschedule(this); 316} 317 318inline void 319Event::reschedule(Tick t, int p) 320{ 321 _priority = p; 322 reschedule(t); 323} 324 325inline void 326EventQueue::schedule(Event *event) 327{ 328 insert(event); 329 if (DTRACE(Event)) 330 event->trace("scheduled"); 331} 332 333inline void 334EventQueue::deschedule(Event *event) 335{ 336 remove(event); 337 if (DTRACE(Event)) 338 event->trace("descheduled"); 339} 340 341inline void 342EventQueue::reschedule(Event *event) 343{ 344 remove(event); 345 insert(event); 346 if (DTRACE(Event)) 347 event->trace("rescheduled"); 348} 349 350 351////////////////////// 352// 353// Main Event Queue 354// 355// Events on this queue are processed at the *beginning* of each 356// cycle, before the pipeline simulation is performed. 357// 358// defined in eventq.cc 359// 360////////////////////// 361extern EventQueue mainEventQueue; 362 363#endif // __EVENTQ_HH__ 364