eventq.hh revision 2632:1bb2f91485ea
1/* 2 * Copyright (c) 2000-2005 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 __SIM_EVENTQ_HH__ 34#define __SIM_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 "base/trace.hh" 47#include "sim/serialize.hh" 48 49class EventQueue; // forward declaration 50 51////////////////////// 52// 53// Main Event Queue 54// 55// Events on this queue are processed at the *beginning* of each 56// cycle, before the pipeline simulation is performed. 57// 58// defined in eventq.cc 59// 60////////////////////// 61extern EventQueue mainEventQueue; 62 63 64/* 65 * An item on an event queue. The action caused by a given 66 * event is specified by deriving a subclass and overriding the 67 * process() member function. 68 */ 69class Event : public Serializable, public FastAlloc 70{ 71 friend class EventQueue; 72 73 private: 74 /// queue to which this event belongs (though it may or may not be 75 /// scheduled on this queue yet) 76 EventQueue *queue; 77 78 Event *next; 79 80 Tick _when; //!< timestamp when event should be processed 81 int _priority; //!< event priority 82 char _flags; 83 84 protected: 85 enum Flags { 86 None = 0x0, 87 Squashed = 0x1, 88 Scheduled = 0x2, 89 AutoDelete = 0x4, 90 AutoSerialize = 0x8 91 }; 92 93 bool getFlags(Flags f) const { return (_flags & f) == f; } 94 void setFlags(Flags f) { _flags |= f; } 95 void clearFlags(Flags f) { _flags &= ~f; } 96 97 protected: 98 EventQueue *theQueue() const { return queue; } 99 100#if TRACING_ON 101 Tick when_created; //!< Keep track of creation time For debugging 102 Tick when_scheduled; //!< Keep track of creation time For debugging 103 104 virtual void trace(const char *action); //!< trace event activity 105#else 106 void trace(const char *) {} 107#endif 108 109 unsigned annotated_value; 110 111 public: 112 113 /// Event priorities, to provide tie-breakers for events scheduled 114 /// at the same cycle. Most events are scheduled at the default 115 /// priority; these values are used to control events that need to 116 /// be ordered within a cycle. 117 enum Priority { 118 /// Breakpoints should happen before anything else, so we 119 /// don't miss any action when debugging. 120 Debug_Break_Pri = -100, 121 122 /// For some reason "delayed" inter-cluster writebacks are 123 /// scheduled before regular writebacks (which have default 124 /// priority). Steve? 125 Delayed_Writeback_Pri = -1, 126 127 /// Default is zero for historical reasons. 128 Default_Pri = 0, 129 130 /// CPU switches schedule the new CPU's tick event for the 131 /// same cycle (after unscheduling the old CPU's tick event). 132 /// The switch needs to come before any tick events to make 133 /// sure we don't tick both CPUs in the same cycle. 134 CPU_Switch_Pri = 31, 135 136 /// Serailization needs to occur before tick events also, so 137 /// that a serialize/unserialize is identical to an on-line 138 /// CPU switch. 139 Serialize_Pri = 32, 140 141 /// CPU ticks must come after other associated CPU events 142 /// (such as writebacks). 143 CPU_Tick_Pri = 50, 144 145 /// Statistics events (dump, reset, etc.) come after 146 /// everything else, but before exit. 147 Stat_Event_Pri = 90, 148 149 /// If we want to exit on this cycle, it's the very last thing 150 /// we do. 151 Sim_Exit_Pri = 100 152 }; 153 154 /* 155 * Event constructor 156 * @param queue that the event gets scheduled on 157 */ 158 Event(EventQueue *q, Priority p = Default_Pri) 159 : queue(q), next(NULL), _priority(p), _flags(None), 160#if TRACING_ON 161 when_created(curTick), when_scheduled(0), 162#endif 163 annotated_value(0) 164 { 165 } 166 167 ~Event() {} 168 169 virtual const std::string name() const { 170 return csprintf("Event_%x", (uintptr_t)this); 171 } 172 173 /// Determine if the current event is scheduled 174 bool scheduled() const { return getFlags(Scheduled); } 175 176 /// Schedule the event with the current priority or default priority 177 void schedule(Tick t); 178 179 /// Reschedule the event with the current priority 180 void reschedule(Tick t); 181 182 /// Remove the event from the current schedule 183 void deschedule(); 184 185 /// Return a C string describing the event. This string should 186 /// *not* be dynamically allocated; just a const char array 187 /// describing the event class. 188 virtual const char *description(); 189 190 /// Dump the current event data 191 void dump(); 192 193 /* 194 * This member function is invoked when the event is processed 195 * (occurs). There is no default implementation; each subclass 196 * must provide its own implementation. The event is not 197 * automatically deleted after it is processed (to allow for 198 * statically allocated event objects). 199 * 200 * If the AutoDestroy flag is set, the object is deleted once it 201 * is processed. 202 */ 203 virtual void process() = 0; 204 205 void annotate(unsigned value) { annotated_value = value; }; 206 unsigned annotation() { return annotated_value; } 207 208 /// Squash the current event 209 void squash() { setFlags(Squashed); } 210 211 /// Check whether the event is squashed 212 bool squashed() { return getFlags(Squashed); } 213 214 /// Get the time that the event is scheduled 215 Tick when() const { return _when; } 216 217 /// Get the event priority 218 int priority() const { return _priority; } 219 220 struct priority_compare : 221 public std::binary_function<Event *, Event *, bool> 222 { 223 bool operator()(const Event *l, const Event *r) const { 224 return l->when() >= r->when() || l->priority() >= r->priority(); 225 } 226 }; 227 228 virtual void serialize(std::ostream &os); 229 virtual void unserialize(Checkpoint *cp, const std::string §ion); 230}; 231 232template <class T, void (T::* F)()> 233void 234DelayFunction(Tick when, T *object) 235{ 236 class DelayEvent : public Event 237 { 238 private: 239 T *object; 240 241 public: 242 DelayEvent(Tick when, T *o) 243 : Event(&mainEventQueue), object(o) 244 { setFlags(this->AutoDestroy); schedule(when); } 245 void process() { (object->*F)(); } 246 const char *description() { return "delay"; } 247 }; 248 249 new DelayEvent(when, object); 250} 251 252template <class T, void (T::* F)()> 253class EventWrapper : public Event 254{ 255 private: 256 T *object; 257 258 public: 259 EventWrapper(T *obj, bool del = false, EventQueue *q = &mainEventQueue, 260 Priority p = Default_Pri) 261 : Event(q, p), object(obj) 262 { 263 if (del) 264 setFlags(AutoDelete); 265 } 266 void process() { (object->*F)(); } 267}; 268 269/* 270 * Queue of events sorted in time order 271 */ 272class EventQueue : public Serializable 273{ 274 protected: 275 std::string objName; 276 277 private: 278 Event *head; 279 280 void insert(Event *event); 281 void remove(Event *event); 282 283 public: 284 285 // constructor 286 EventQueue(const std::string &n) 287 : objName(n), head(NULL) 288 {} 289 290 virtual const std::string name() const { return objName; } 291 292 // schedule the given event on this queue 293 void schedule(Event *ev); 294 void deschedule(Event *ev); 295 void reschedule(Event *ev); 296 297 Tick nextTick() { return head->when(); } 298 void serviceOne(); 299 300 // process all events up to the given timestamp. we inline a 301 // quick test to see if there are any events to process; if so, 302 // call the internal out-of-line version to process them all. 303 void serviceEvents(Tick when) { 304 while (!empty()) { 305 if (nextTick() > when) 306 break; 307 308 /** 309 * @todo this assert is a good bug catcher. I need to 310 * make it true again. 311 */ 312 //assert(head->when() >= when && "event scheduled in the past"); 313 serviceOne(); 314 } 315 } 316 317 // default: process all events up to 'now' (curTick) 318 void serviceEvents() { serviceEvents(curTick); } 319 320 // return true if no events are queued 321 bool empty() { return head == NULL; } 322 323 void dump(); 324 325 Tick nextEventTime() { return empty() ? curTick : head->when(); } 326 327 virtual void serialize(std::ostream &os); 328 virtual void unserialize(Checkpoint *cp, const std::string §ion); 329}; 330 331 332////////////////////// 333// 334// inline functions 335// 336// can't put these inside declaration due to circular dependence 337// between Event and EventQueue classes. 338// 339////////////////////// 340 341// schedule at specified time (place on event queue specified via 342// constructor) 343inline void 344Event::schedule(Tick t) 345{ 346 assert(!scheduled()); 347 assert(t >= curTick); 348 349 setFlags(Scheduled); 350#if TRACING_ON 351 when_scheduled = curTick; 352#endif 353 _when = t; 354 queue->schedule(this); 355} 356 357inline void 358Event::deschedule() 359{ 360 assert(scheduled()); 361 362 clearFlags(Squashed); 363 clearFlags(Scheduled); 364 queue->deschedule(this); 365} 366 367inline void 368Event::reschedule(Tick t) 369{ 370 assert(scheduled()); 371 clearFlags(Squashed); 372 373#if TRACING_ON 374 when_scheduled = curTick; 375#endif 376 _when = t; 377 queue->reschedule(this); 378} 379 380inline void 381EventQueue::schedule(Event *event) 382{ 383 insert(event); 384 if (DTRACE(Event)) 385 event->trace("scheduled"); 386} 387 388inline void 389EventQueue::deschedule(Event *event) 390{ 391 remove(event); 392 if (DTRACE(Event)) 393 event->trace("descheduled"); 394} 395 396inline void 397EventQueue::reschedule(Event *event) 398{ 399 remove(event); 400 insert(event); 401 if (DTRACE(Event)) 402 event->trace("rescheduled"); 403} 404 405 406 407#endif // __SIM_EVENTQ_HH__ 408