eventq.hh revision 237
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 AutoSerialize = 0x8 78 }; 79 80 bool getFlags(Flags f) const { return (_flags & f) == f; } 81 void setFlags(Flags f) { _flags |= f; } 82 void clearFlags(Flags f) { _flags &= ~f; } 83 84 protected: 85 EventQueue *theQueue() const { return queue; } 86 87#if TRACING_ON 88 Tick when_created; //!< Keep track of creation time For debugging 89 Tick when_scheduled; //!< Keep track of creation time For debugging 90 91 virtual void trace(const char *action); //!< trace event activity 92#else 93 void trace(const char *) {} 94#endif 95 96 unsigned annotated_value; 97 98 public: 99 100 static const std::string defaultName; 101 102 /* 103 * Event constructor 104 * @param queue that the event gets scheduled on 105 */ 106 Event(EventQueue *q, int p = 0) 107 : Serializeable(defaultName), queue(q), next(NULL), 108 _priority(p), _flags(None), 109#if TRACING_ON 110 when_created(curTick), when_scheduled(0), 111#endif 112 annotated_value(0) 113 { 114 } 115 116 /* 117 * Event constructor 118 * @param queue that the event gets scheduled on 119 */ 120 Event(EventQueue *q, std::string _name, int p = 0) 121 : Serializeable(_name), queue(q), next(NULL), 122 _priority(p), _flags(None), 123#if TRACING_ON 124 when_created(curTick), when_scheduled(0), 125#endif 126 annotated_value(0) 127 { 128 } 129 130 ~Event() {} 131 132 /// Determine if the current event is scheduled 133 bool scheduled() const { return getFlags(Scheduled); } 134 135 /// Schedule the event with the current priority or default priority 136 void schedule(Tick t); 137 138 /// Schedule the event with a specific priority 139 void schedule(Tick t, int priority); 140 141 /// Reschedule the event with the current priority 142 void reschedule(Tick t); 143 144 /// Reschedule the event with a specific priority 145 void reschedule(Tick t, int priority); 146 147 /// Remove the event from the current schedule 148 void deschedule(); 149 150 /// Return a C string describing the event. This string should 151 /// *not* be dynamically allocated; just a const char array 152 /// describing the event class. 153 virtual const char *description(); 154 155 /// Dump the current event data 156 void dump(); 157 158 /* 159 * This member function is invoked when the event is processed 160 * (occurs). There is no default implementation; each subclass 161 * must provide its own implementation. The event is not 162 * automatically deleted after it is processed (to allow for 163 * statically allocated event objects). 164 * 165 * If the AutoDestroy flag is set, the object is deleted once it 166 * is processed. 167 */ 168 virtual void process() = 0; 169 170 void annotate(unsigned value) { annotated_value = value; }; 171 unsigned annotation() { return annotated_value; } 172 173 /// Squash the current event 174 void squash() { setFlags(Squashed); } 175 176 /// Check whether the event is squashed 177 bool squashed() { return getFlags(Squashed); } 178 179 /// Get the time that the event is scheduled 180 Tick when() const { return _when; } 181 182 /// Get the event priority 183 int priority() const { return _priority; } 184 185 struct priority_compare : 186 public std::binary_function<Event *, Event *, bool> 187 { 188 bool operator()(const Event *l, const Event *r) const { 189 return l->when() >= r->when() || l->priority() >= r->priority(); 190 } 191 }; 192 193 virtual void serialize(std::ostream &os); 194 virtual void unserialize(Checkpoint *cp, const std::string §ion); 195}; 196 197template <class T, void (T::* F)()> 198void 199DelayFunction(Tick when, T *object) 200{ 201 class DelayEvent : public Event 202 { 203 private: 204 T *object; 205 206 public: 207 DelayEvent(Tick when, T *o) 208 : Event(&mainEventQueue), object(o) 209 { setFlags(AutoDestroy); schedule(when); } 210 void process() { (object->*F)(); } 211 const char *description() { return "delay"; } 212 }; 213 214 new DelayEvent(when, object); 215} 216 217/* 218 * Queue of events sorted in time order 219 */ 220class EventQueue : public Serializeable 221{ 222 private: 223 Event *head; 224 225 // only used to hold value between nameChildren() and serialize() 226 int numAutoSerializeEvents; 227 228 void insert(Event *event); 229 void remove(Event *event); 230 231 public: 232 233 // constructor 234 EventQueue(const std::string &n) 235 : Serializeable(n), head(NULL), numAutoSerializeEvents(-1) 236 {} 237 238 // schedule the given event on this queue 239 void schedule(Event *ev); 240 void deschedule(Event *ev); 241 void reschedule(Event *ev); 242 243 Tick nextTick() { return head->when(); } 244 void serviceOne(); 245 246 // process all events up to the given timestamp. we inline a 247 // quick test to see if there are any events to process; if so, 248 // call the internal out-of-line version to process them all. 249 void serviceEvents(Tick when) { 250 while (!empty()) { 251 if (nextTick() > when) 252 break; 253 254 assert(head->when() >= when && "event scheduled in the past"); 255 serviceOne(); 256 } 257 } 258 259 // default: process all events up to 'now' (curTick) 260 void serviceEvents() { serviceEvents(curTick); } 261 262 // return true if no events are queued 263 bool empty() { return head == NULL; } 264 265 void dump(); 266 267 Tick nextEventTime() { return empty() ? curTick : head->when(); } 268 269 virtual void nameChildren(); 270 virtual void serialize(std::ostream &os); 271 virtual void unserialize(Checkpoint *cp, const std::string §ion); 272}; 273 274 275////////////////////// 276// 277// inline functions 278// 279// can't put these inside declaration due to circular dependence 280// between Event and EventQueue classes. 281// 282////////////////////// 283 284// schedule at specified time (place on event queue specified via 285// constructor) 286inline void 287Event::schedule(Tick t) 288{ 289 assert(!scheduled()); 290 setFlags(Scheduled); 291#if TRACING_ON 292 when_scheduled = curTick; 293#endif 294 _when = t; 295 queue->schedule(this); 296} 297 298inline void 299Event::schedule(Tick t, int p) 300{ 301 _priority = p; 302 schedule(t); 303} 304 305inline void 306Event::deschedule() 307{ 308 assert(scheduled()); 309 310 clearFlags(Squashed); 311 clearFlags(Scheduled); 312 queue->deschedule(this); 313} 314 315inline void 316Event::reschedule(Tick t) 317{ 318 assert(scheduled()); 319 clearFlags(Squashed); 320 321#if TRACING_ON 322 when_scheduled = curTick; 323#endif 324 _when = t; 325 queue->reschedule(this); 326} 327 328inline void 329Event::reschedule(Tick t, int p) 330{ 331 _priority = p; 332 reschedule(t); 333} 334 335inline void 336EventQueue::schedule(Event *event) 337{ 338 insert(event); 339 if (DTRACE(Event)) 340 event->trace("scheduled"); 341} 342 343inline void 344EventQueue::deschedule(Event *event) 345{ 346 remove(event); 347 if (DTRACE(Event)) 348 event->trace("descheduled"); 349} 350 351inline void 352EventQueue::reschedule(Event *event) 353{ 354 remove(event); 355 insert(event); 356 if (DTRACE(Event)) 357 event->trace("rescheduled"); 358} 359 360 361////////////////////// 362// 363// Main Event Queue 364// 365// Events on this queue are processed at the *beginning* of each 366// cycle, before the pipeline simulation is performed. 367// 368// defined in eventq.cc 369// 370////////////////////// 371extern EventQueue mainEventQueue; 372 373#endif // __EVENTQ_HH__ 374