eventq.hh revision 224
1/* 2 * Copyright (c) 2003 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* @file 30 * EventQueue interfaces 31 */ 32 33#ifndef __EVENTQ_HH__ 34#define __EVENTQ_HH__ 35 36#include <assert.h> 37 38#include <algorithm> 39#include <map> 40#include <string> 41#include <vector> 42 43#include "sim/host.hh" // for Tick 44 45#include "base/fast_alloc.hh" 46#include "sim/serialize.hh" 47#include "base/trace.hh" 48 49class EventQueue; // forward declaration 50 51/* 52 * An item on an event queue. The action caused by a given 53 * event is specified by deriving a subclass and overriding the 54 * process() member function. 55 */ 56class Event : public Serializeable, public FastAlloc 57{ 58 friend class EventQueue; 59 60 private: 61 /// queue to which this event belongs (though it may or may not be 62 /// scheduled on this queue yet) 63 EventQueue *queue; 64 65 Event *next; 66 67 Tick _when; //!< timestamp when event should be processed 68 int _priority; //!< event priority 69 char _flags; 70 71 protected: 72 enum Flags { 73 None = 0x0, 74 Squashed = 0x1, 75 Scheduled = 0x2, 76 AutoDelete = 0x4 77 }; 78 79 bool getFlags(Flags f) const { return (_flags & f) == f; } 80 void setFlags(Flags f) { _flags |= f; } 81 void clearFlags(Flags f) { _flags &= ~f; } 82 83 protected: 84 EventQueue *theQueue() const { return queue; } 85 86#if TRACING_ON 87 Tick when_created; //!< Keep track of creation time For debugging 88 Tick when_scheduled; //!< Keep track of creation time For debugging 89 90 virtual void trace(const char *action); //!< trace event activity 91#else 92 void trace(const char *) {} 93#endif 94 95 unsigned annotated_value; 96 97 public: 98 99 static const std::string defaultName; 100 101 /* 102 * Event constructor 103 * @param queue that the event gets scheduled on 104 */ 105 Event(EventQueue *q, int p = 0) 106 : Serializeable(defaultName), queue(q), next(NULL), 107 _priority(p), _flags(None), 108#if TRACING_ON 109 when_created(curTick), when_scheduled(0), 110#endif 111 annotated_value(0) 112 { 113 } 114 115 /* 116 * Event constructor 117 * @param queue that the event gets scheduled on 118 */ 119 Event(EventQueue *q, std::string _name, int p = 0) 120 : Serializeable(_name), queue(q), next(NULL), 121 _priority(p), _flags(None), 122#if TRACING_ON 123 when_created(curTick), when_scheduled(0), 124#endif 125 annotated_value(0) 126 { 127 } 128 129 ~Event() {} 130 131 /// Determine if the current event is scheduled 132 bool scheduled() const { return getFlags(Scheduled); } 133 134 /// Schedule the event with the current priority or default priority 135 void schedule(Tick t); 136 137 /// Schedule the event with a specific priority 138 void schedule(Tick t, int priority); 139 140 /// Reschedule the event with the current priority 141 void reschedule(Tick t); 142 143 /// Reschedule the event with a specific priority 144 void reschedule(Tick t, int priority); 145 146 /// Remove the event from the current schedule 147 void deschedule(); 148 149 /// Return a C string describing the event. This string should 150 /// *not* be dynamically allocated; just a const char array 151 /// describing the event class. 152 virtual const char *description(); 153 154 /// Dump the current event data 155 void dump(); 156 157 /* 158 * This member function is invoked when the event is processed 159 * (occurs). There is no default implementation; each subclass 160 * must provide its own implementation. The event is not 161 * automatically deleted after it is processed (to allow for 162 * statically allocated event objects). 163 * 164 * If the AutoDestroy flag is set, the object is deleted once it 165 * is processed. 166 */ 167 virtual void process() = 0; 168 169 void annotate(unsigned value) { annotated_value = value; }; 170 unsigned annotation() { return annotated_value; } 171 172 /// Squash the current event 173 void squash() { setFlags(Squashed); } 174 175 /// Check whether the event is squashed 176 bool squashed() { return getFlags(Squashed); } 177 178 /// Get the time that the event is scheduled 179 Tick when() const { return _when; } 180 181 /// Get the event priority 182 int priority() const { return _priority; } 183 184 struct priority_compare : 185 public std::binary_function<Event *, Event *, bool> 186 { 187 bool operator()(const Event *l, const Event *r) const { 188 return l->when() >= r->when() || l->priority() >= r->priority(); 189 } 190 }; 191 192 virtual void serialize(std::ostream &os); 193 virtual void unserialize(const IniFile *db, const std::string §ion); 194}; 195 196template <class T, void (T::* F)()> 197void 198DelayFunction(Tick when, T *object) 199{ 200 class DelayEvent : public Event 201 { 202 private: 203 T *object; 204 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