eventq.hh revision 2
13999Ssaidi@eecs.umich.edu/* 23395Shsul@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan 33395Shsul@eecs.umich.edu * All rights reserved. 43395Shsul@eecs.umich.edu * 53395Shsul@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 63395Shsul@eecs.umich.edu * modification, are permitted provided that the following conditions are 73395Shsul@eecs.umich.edu * met: redistributions of source code must retain the above copyright 83395Shsul@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 93395Shsul@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 103395Shsul@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 113395Shsul@eecs.umich.edu * documentation and/or other materials provided with the distribution; 123395Shsul@eecs.umich.edu * neither the name of the copyright holders nor the names of its 133395Shsul@eecs.umich.edu * contributors may be used to endorse or promote products derived from 143395Shsul@eecs.umich.edu * this software without specific prior written permission. 153395Shsul@eecs.umich.edu * 163395Shsul@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173395Shsul@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183395Shsul@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193395Shsul@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203395Shsul@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213395Shsul@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223395Shsul@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233395Shsul@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243395Shsul@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253395Shsul@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263395Shsul@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273395Shsul@eecs.umich.edu */ 283395Shsul@eecs.umich.edu 293395Shsul@eecs.umich.edu/* @file 303509Shsul@eecs.umich.edu * EventQueue interfaces 313395Shsul@eecs.umich.edu */ 323395Shsul@eecs.umich.edu 333395Shsul@eecs.umich.edu#ifndef __EVENTQ_HH__ 343448Shsul@eecs.umich.edu#define __EVENTQ_HH__ 353395Shsul@eecs.umich.edu 363481Shsul@eecs.umich.edu#include <assert.h> 373481Shsul@eecs.umich.edu 383481Shsul@eecs.umich.edu#include <algorithm> 393481Shsul@eecs.umich.edu#include <map> 403481Shsul@eecs.umich.edu#include <string> 413481Shsul@eecs.umich.edu#include <vector> 423681Sktlim@umich.edu 433681Sktlim@umich.edu#include "host.hh" // for Tick 443681Sktlim@umich.edu 453481Shsul@eecs.umich.edu#include "fast_alloc.hh" 463481Shsul@eecs.umich.edu#include "serialize.hh" 473481Shsul@eecs.umich.edu#include "trace.hh" 483481Shsul@eecs.umich.edu 493481Shsul@eecs.umich.educlass EventQueue; // forward declaration 503481Shsul@eecs.umich.edu 513481Shsul@eecs.umich.edu/* 523481Shsul@eecs.umich.edu * An item on an event queue. The action caused by a given 533481Shsul@eecs.umich.edu * event is specified by deriving a subclass and overriding the 543481Shsul@eecs.umich.edu * process() member function. 553481Shsul@eecs.umich.edu */ 563481Shsul@eecs.umich.educlass Event : public Serializeable, public FastAlloc 573481Shsul@eecs.umich.edu{ 583481Shsul@eecs.umich.edu friend class EventQueue; 593481Shsul@eecs.umich.edu 603481Shsul@eecs.umich.edu private: 613481Shsul@eecs.umich.edu /// queue to which this event belongs (though it may or may not be 623481Shsul@eecs.umich.edu /// scheduled on this queue yet) 633481Shsul@eecs.umich.edu EventQueue *queue; 643395Shsul@eecs.umich.edu 653395Shsul@eecs.umich.edu Event *next; 663395Shsul@eecs.umich.edu 674167Sbinkertn@umich.edu Tick _when; //!< timestamp when event should be processed 683395Shsul@eecs.umich.edu int _priority; //!< event priority 693395Shsul@eecs.umich.edu char _flags; 703395Shsul@eecs.umich.edu 713511Shsul@eecs.umich.edu protected: 723395Shsul@eecs.umich.edu enum Flags { 733395Shsul@eecs.umich.edu None = 0x0, 743395Shsul@eecs.umich.edu Squashed = 0x1, 755211Ssaidi@eecs.umich.edu Scheduled = 0x2, 765211Ssaidi@eecs.umich.edu AutoDelete = 0x4 773395Shsul@eecs.umich.edu }; 783395Shsul@eecs.umich.edu 793395Shsul@eecs.umich.edu bool getFlags(Flags f) const { return (_flags & f) == f; } 803395Shsul@eecs.umich.edu void setFlags(Flags f) { _flags |= f; } 813395Shsul@eecs.umich.edu void clearFlags(Flags f) { _flags &= ~f; } 823481Shsul@eecs.umich.edu 833481Shsul@eecs.umich.edu protected: 843481Shsul@eecs.umich.edu EventQueue *theQueue() const { return queue; } 853481Shsul@eecs.umich.edu 863481Shsul@eecs.umich.edu#if TRACING_ON 873481Shsul@eecs.umich.edu Tick when_created; //!< Keep track of creation time For debugging 883481Shsul@eecs.umich.edu Tick when_scheduled; //!< Keep track of creation time For debugging 893481Shsul@eecs.umich.edu 903481Shsul@eecs.umich.edu virtual void trace(const char *action); //!< trace event activity 913481Shsul@eecs.umich.edu#else 923481Shsul@eecs.umich.edu void trace(const char *) {} 933481Shsul@eecs.umich.edu#endif 943481Shsul@eecs.umich.edu 953481Shsul@eecs.umich.edu unsigned annotated_value; 963395Shsul@eecs.umich.edu 973395Shsul@eecs.umich.edu public: 983395Shsul@eecs.umich.edu 993395Shsul@eecs.umich.edu static const std::string defaultName; 1003478Shsul@eecs.umich.edu 1013395Shsul@eecs.umich.edu /* 1023478Shsul@eecs.umich.edu * Event constructor 1033395Shsul@eecs.umich.edu * @param queue that the event gets scheduled on 1043395Shsul@eecs.umich.edu */ 1053478Shsul@eecs.umich.edu Event(EventQueue *q, int p = 0) 1063395Shsul@eecs.umich.edu : Serializeable(defaultName), queue(q), next(NULL), 1073395Shsul@eecs.umich.edu _priority(p), _flags(None), 1083478Shsul@eecs.umich.edu#if TRACING_ON 1093395Shsul@eecs.umich.edu when_created(curTick), when_scheduled(0), 1103478Shsul@eecs.umich.edu#endif 1113480Shsul@eecs.umich.edu annotated_value(0) 1123514Sktlim@umich.edu { 1133481Shsul@eecs.umich.edu } 1143480Shsul@eecs.umich.edu 1153480Shsul@eecs.umich.edu ~Event() {} 1163480Shsul@eecs.umich.edu 1173395Shsul@eecs.umich.edu /// Determine if the current event is scheduled 1183478Shsul@eecs.umich.edu bool scheduled() const { return getFlags(Scheduled); } 1193514Sktlim@umich.edu 1203514Sktlim@umich.edu /// Schedule the event with the current priority or default priority 1213395Shsul@eecs.umich.edu void schedule(Tick t); 1223478Shsul@eecs.umich.edu 1233395Shsul@eecs.umich.edu /// Schedule the event with a specific priority 1243395Shsul@eecs.umich.edu void schedule(Tick t, int priority); 1253395Shsul@eecs.umich.edu 1263395Shsul@eecs.umich.edu /// Reschedule the event with the current priority 1273395Shsul@eecs.umich.edu void reschedule(Tick t); 1283395Shsul@eecs.umich.edu 1293395Shsul@eecs.umich.edu /// Reschedule the event with a specific priority 1303395Shsul@eecs.umich.edu void reschedule(Tick t, int priority); 1313395Shsul@eecs.umich.edu 1323395Shsul@eecs.umich.edu /// Remove the event from the current schedule 1333395Shsul@eecs.umich.edu void deschedule(); 1343395Shsul@eecs.umich.edu 1355073Ssaidi@eecs.umich.edu /// Return a C string describing the event. This string should 1363395Shsul@eecs.umich.edu /// *not* be dynamically allocated; just a const char array 1373395Shsul@eecs.umich.edu /// describing the event class. 1383395Shsul@eecs.umich.edu virtual const char *description(); 1393395Shsul@eecs.umich.edu 1403395Shsul@eecs.umich.edu /// Dump the current event data 1413395Shsul@eecs.umich.edu void dump(); 1423395Shsul@eecs.umich.edu 1433395Shsul@eecs.umich.edu /* 1443395Shsul@eecs.umich.edu * This member function is invoked when the event is processed 1453395Shsul@eecs.umich.edu * (occurs). There is no default implementation; each subclass 1463395Shsul@eecs.umich.edu * must provide its own implementation. The event is not 1473395Shsul@eecs.umich.edu * automatically deleted after it is processed (to allow for 1483395Shsul@eecs.umich.edu * statically allocated event objects). 1493999Ssaidi@eecs.umich.edu * 1503999Ssaidi@eecs.umich.edu * If the AutoDestroy flag is set, the object is deleted once it 1513999Ssaidi@eecs.umich.edu * is processed. 1523999Ssaidi@eecs.umich.edu */ 1533395Shsul@eecs.umich.edu virtual void process() = 0; 1543509Shsul@eecs.umich.edu 1553395Shsul@eecs.umich.edu void annotate(unsigned value) { annotated_value = value; }; 1563481Shsul@eecs.umich.edu unsigned annotation() { return annotated_value; } 1573395Shsul@eecs.umich.edu 1583395Shsul@eecs.umich.edu /// Squash the current event 1593395Shsul@eecs.umich.edu void squash() { setFlags(Squashed); } 1603395Shsul@eecs.umich.edu 1613395Shsul@eecs.umich.edu /// Check whether the event is squashed 1623395Shsul@eecs.umich.edu bool squashed() { return getFlags(Squashed); } 1633395Shsul@eecs.umich.edu 1643395Shsul@eecs.umich.edu /// Get the time that the event is scheduled 1653395Shsul@eecs.umich.edu Tick when() const { return _when; } 1663395Shsul@eecs.umich.edu 1673395Shsul@eecs.umich.edu /// Get the event priority 1683395Shsul@eecs.umich.edu int priority() const { return _priority; } 1693481Shsul@eecs.umich.edu 1703481Shsul@eecs.umich.edu struct priority_compare : 1715072Ssaidi@eecs.umich.edu public std::binary_function<Event *, Event *, bool> 1723481Shsul@eecs.umich.edu { 1735072Ssaidi@eecs.umich.edu bool operator()(const Event *l, const Event *r) const { 1743395Shsul@eecs.umich.edu return l->when() >= r->when() || l->priority() >= r->priority(); 1753395Shsul@eecs.umich.edu } 1763395Shsul@eecs.umich.edu }; 1773395Shsul@eecs.umich.edu}; 1783410Shsul@eecs.umich.edu 1793410Shsul@eecs.umich.edutemplate <class T, void (T::* F)()> 1803410Shsul@eecs.umich.eduvoid 1813395Shsul@eecs.umich.eduDelayFunction(Tick when, T *object) 1823395Shsul@eecs.umich.edu{ 1833395Shsul@eecs.umich.edu class DelayEvent : public Event 1843395Shsul@eecs.umich.edu { 1853395Shsul@eecs.umich.edu private: 1863395Shsul@eecs.umich.edu T *object; 1873395Shsul@eecs.umich.edu 1883395Shsul@eecs.umich.edu public: 1893395Shsul@eecs.umich.edu DelayEvent(Tick when, T *o) 1903395Shsul@eecs.umich.edu : Event(&mainEventQueue), object(o) 1913509Shsul@eecs.umich.edu { setFlags(AutoDestroy); schedule(when); } 1923395Shsul@eecs.umich.edu void process() { (object->*F)(); } 1933395Shsul@eecs.umich.edu const char *description() { return "delay"; } 1943395Shsul@eecs.umich.edu }; 1953395Shsul@eecs.umich.edu 1963999Ssaidi@eecs.umich.edu new DelayEvent(when, object); 1975185Ssaidi@eecs.umich.edu} 1983511Shsul@eecs.umich.edu 1993395Shsul@eecs.umich.edu/* 2003395Shsul@eecs.umich.edu * Queue of events sorted in time order 2013395Shsul@eecs.umich.edu */ 2023395Shsul@eecs.umich.educlass EventQueue : public Serializeable 2033395Shsul@eecs.umich.edu{ 2043395Shsul@eecs.umich.edu private: 2053395Shsul@eecs.umich.edu Event *head; 2063395Shsul@eecs.umich.edu 2073395Shsul@eecs.umich.edu void insert(Event *event); 2083509Shsul@eecs.umich.edu void remove(Event *event); 2093395Shsul@eecs.umich.edu 2103395Shsul@eecs.umich.edu public: 2115185Ssaidi@eecs.umich.edu 2123999Ssaidi@eecs.umich.edu // constructor 2133999Ssaidi@eecs.umich.edu EventQueue(const std::string &n) 2143999Ssaidi@eecs.umich.edu : Serializeable(n), head(NULL) 2153395Shsul@eecs.umich.edu {} 2163395Shsul@eecs.umich.edu 2173395Shsul@eecs.umich.edu // schedule the given event on this queue 2183395Shsul@eecs.umich.edu void schedule(Event *ev); 2193509Shsul@eecs.umich.edu void deschedule(Event *ev); 2203395Shsul@eecs.umich.edu void reschedule(Event *ev); 2213395Shsul@eecs.umich.edu 2223395Shsul@eecs.umich.edu Tick nextTick() { return head->when(); } 2233395Shsul@eecs.umich.edu void serviceOne(); 2243395Shsul@eecs.umich.edu 2253511Shsul@eecs.umich.edu // process all events up to the given timestamp. we inline a 2263395Shsul@eecs.umich.edu // quick test to see if there are any events to process; if so, 2273395Shsul@eecs.umich.edu // call the internal out-of-line version to process them all. 2283395Shsul@eecs.umich.edu void serviceEvents(Tick when) { 2293395Shsul@eecs.umich.edu while (!empty()) { 2303514Sktlim@umich.edu if (nextTick() > when) 2313395Shsul@eecs.umich.edu break; 232 233 assert(head->when() >= when && "event scheduled in the past"); 234 serviceOne(); 235 } 236 } 237 238 // default: process all events up to 'now' (curTick) 239 void serviceEvents() { serviceEvents(curTick); } 240 241 // return true if no events are queued 242 bool empty() { return head == NULL; } 243 244 void dump(); 245 246 Tick nextEventTime() { return empty() ? curTick : head->when(); } 247 248 virtual void nameChildren(); 249 virtual void serialize(); 250}; 251 252 253////////////////////// 254// 255// inline functions 256// 257// can't put these inside declaration due to circular dependence 258// between Event and EventQueue classes. 259// 260////////////////////// 261 262// schedule at specified time (place on event queue specified via 263// constructor) 264inline void 265Event::schedule(Tick t) 266{ 267 assert(!scheduled()); 268 setFlags(Scheduled); 269#if TRACING_ON 270 when_scheduled = curTick; 271#endif 272 _when = t; 273 queue->schedule(this); 274} 275 276inline void 277Event::schedule(Tick t, int p) 278{ 279 _priority = p; 280 schedule(t); 281} 282 283inline void 284Event::deschedule() 285{ 286 assert(scheduled()); 287 288 clearFlags(Squashed); 289 clearFlags(Scheduled); 290 queue->deschedule(this); 291} 292 293inline void 294Event::reschedule(Tick t) 295{ 296 assert(scheduled()); 297 clearFlags(Squashed); 298 299#if TRACING_ON 300 when_scheduled = curTick; 301#endif 302 _when = t; 303 queue->reschedule(this); 304} 305 306inline void 307Event::reschedule(Tick t, int p) 308{ 309 _priority = p; 310 reschedule(t); 311} 312 313inline void 314EventQueue::schedule(Event *event) 315{ 316 insert(event); 317 if (DTRACE(Event)) 318 event->trace("scheduled"); 319} 320 321inline void 322EventQueue::deschedule(Event *event) 323{ 324 remove(event); 325 if (DTRACE(Event)) 326 event->trace("descheduled"); 327} 328 329inline void 330EventQueue::reschedule(Event *event) 331{ 332 remove(event); 333 insert(event); 334 if (DTRACE(Event)) 335 event->trace("rescheduled"); 336} 337 338 339////////////////////// 340// 341// Main Event Queue 342// 343// Events on this queue are processed at the *beginning* of each 344// cycle, before the pipeline simulation is performed. 345// 346// defined in eventq.cc 347// 348////////////////////// 349extern EventQueue mainEventQueue; 350 351#endif // __EVENTQ_HH__ 352