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