eventq.hh revision 217
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 ~Event() {} 116 117 /// Determine if the current event is scheduled 118 bool scheduled() const { return getFlags(Scheduled); } 119 120 /// Schedule the event with the current priority or default priority 121 void schedule(Tick t); 122 123 /// Schedule the event with a specific priority 124 void schedule(Tick t, int priority); 125 126 /// Reschedule the event with the current priority 127 void reschedule(Tick t); 128 129 /// Reschedule the event with a specific priority 130 void reschedule(Tick t, int priority); 131 132 /// Remove the event from the current schedule 133 void deschedule(); 134 135 /// Return a C string describing the event. This string should 136 /// *not* be dynamically allocated; just a const char array 137 /// describing the event class. 138 virtual const char *description(); 139 140 /// Dump the current event data 141 void dump(); 142 143 /* 144 * This member function is invoked when the event is processed 145 * (occurs). There is no default implementation; each subclass 146 * must provide its own implementation. The event is not 147 * automatically deleted after it is processed (to allow for 148 * statically allocated event objects). 149 * 150 * If the AutoDestroy flag is set, the object is deleted once it 151 * is processed. 152 */ 153 virtual void process() = 0; 154 155 void annotate(unsigned value) { annotated_value = value; }; 156 unsigned annotation() { return annotated_value; } 157 158 /// Squash the current event 159 void squash() { setFlags(Squashed); } 160 161 /// Check whether the event is squashed 162 bool squashed() { return getFlags(Squashed); } 163 164 /// Get the time that the event is scheduled 165 Tick when() const { return _when; } 166 167 /// Get the event priority 168 int priority() const { return _priority; } 169 170 struct priority_compare : 171 public std::binary_function<Event *, Event *, bool> 172 { 173 bool operator()(const Event *l, const Event *r) const { 174 return l->when() >= r->when() || l->priority() >= r->priority(); 175 } 176 }; 177}; 178 179template <class T, void (T::* F)()> 180void 181DelayFunction(Tick when, T *object) 182{ 183 class DelayEvent : public Event 184 { 185 private: 186 T *object; 187 188 public: 189 DelayEvent(Tick when, T *o) 190 : Event(&mainEventQueue), object(o) 191 { setFlags(AutoDestroy); schedule(when); } 192 void process() { (object->*F)(); } 193 const char *description() { return "delay"; } 194 }; 195 196 new DelayEvent(when, object); 197} 198 199/* 200 * Queue of events sorted in time order 201 */ 202class EventQueue : public Serializeable 203{ 204 private: 205 Event *head; 206 207 void insert(Event *event); 208 void remove(Event *event); 209 210 public: 211 212 // constructor 213 EventQueue(const std::string &n) 214 : Serializeable(n), head(NULL) 215 {} 216 217 // schedule the given event on this queue 218 void schedule(Event *ev); 219 void deschedule(Event *ev); 220 void reschedule(Event *ev); 221 222 Tick nextTick() { return head->when(); } 223 void serviceOne(); 224 225 // process all events up to the given timestamp. we inline a 226 // quick test to see if there are any events to process; if so, 227 // call the internal out-of-line version to process them all. 228 void serviceEvents(Tick when) { 229 while (!empty()) { 230 if (nextTick() > when) 231 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(std::ostream &os); 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