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 §ion); 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 §ion); 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