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