eventq.hh revision 571
16145Snate@binkert.org/* 26239Snate@binkert.org * Copyright (c) 2003 The Regents of The University of Michigan 36239Snate@binkert.org * All rights reserved. 46145Snate@binkert.org * 56239Snate@binkert.org * Redistribution and use in source and binary forms, with or without 66239Snate@binkert.org * modification, are permitted provided that the following conditions are 76239Snate@binkert.org * met: redistributions of source code must retain the above copyright 86239Snate@binkert.org * notice, this list of conditions and the following disclaimer; 96239Snate@binkert.org * redistributions in binary form must reproduce the above copyright 106239Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 116239Snate@binkert.org * documentation and/or other materials provided with the distribution; 126239Snate@binkert.org * neither the name of the copyright holders nor the names of its 136239Snate@binkert.org * contributors may be used to endorse or promote products derived from 146239Snate@binkert.org * this software without specific prior written permission. 156145Snate@binkert.org * 166239Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176239Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186239Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196239Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206239Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216239Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226239Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236239Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246239Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256239Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266239Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276145Snate@binkert.org */ 286145Snate@binkert.org 297039Snate@binkert.org/* @file 307039Snate@binkert.org * EventQueue interfaces 316145Snate@binkert.org */ 328091Snilay@cs.wisc.edu 336145Snate@binkert.org#ifndef __EVENTQ_HH__ 348946Sandreas.hansson@arm.com#define __EVENTQ_HH__ 357002Snate@binkert.org 367002Snate@binkert.org#include <assert.h> 3711025Snilay@cs.wisc.edu 386145Snate@binkert.org#include <algorithm> 399362Snilay@cs.wisc.edu#include <map> 406145Snate@binkert.org#include <string> 4111025Snilay@cs.wisc.edu#include <vector> 4211025Snilay@cs.wisc.edu 4311025Snilay@cs.wisc.edu#include "sim/host.hh" // for Tick 4411025Snilay@cs.wisc.edu 4511025Snilay@cs.wisc.edu#include "base/fast_alloc.hh" 4611025Snilay@cs.wisc.edu#include "sim/serialize.hh" 4711025Snilay@cs.wisc.edu#include "base/trace.hh" 4811025Snilay@cs.wisc.edu 4911025Snilay@cs.wisc.educlass EventQueue; // forward declaration 5011118Snilay@cs.wisc.edu 516145Snate@binkert.org/* 527039Snate@binkert.org * 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 Serializable, 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 /// Event priorities, to provide tie-breakers for events scheduled 101 /// at the same cycle. Most events are scheduled at the default 102 /// priority; these values are used to control events that need to 103 /// be ordered within a cycle. 104 enum Priority { 105 /// Breakpoints should happen before anything else, so we 106 /// don't miss any action when debugging. 107 Debug_Break_Pri = -100, 108 109 /// For some reason "delayed" inter-cluster writebacks are 110 /// scheduled before regular writebacks (which have default 111 /// priority). Steve? 112 Delayed_Writeback_Pri = -1, 113 114 /// Default is zero for historical reasons. 115 Default_Pri = 0, 116 117 /// CPU switches schedule the new CPU's tick event for the 118 /// same cycle (after unscheduling the old CPU's tick event). 119 /// The switch needs to come before any tick events to make 120 /// sure we don't tick both CPUs in the same cycle. 121 CPU_Switch_Pri = 31, 122 123 /// Serailization needs to occur before tick events also, so 124 /// that a serialize/unserialize is identical to an on-line 125 /// CPU switch. 126 Serialize_Pri = 32, 127 128 /// CPU ticks must come after other associated CPU events 129 /// (such as writebacks). 130 CPU_Tick_Pri = 50, 131 132 /// Statistics events (dump, reset, etc.) come after 133 /// everything else, but before exit. 134 Stat_Event_Pri = 90, 135 136 /// If we want to exit on this cycle, it's the very last thing 137 /// we do. 138 Sim_Exit_Pri = 100 139 }; 140 141 /* 142 * Event constructor 143 * @param queue that the event gets scheduled on 144 */ 145 Event(EventQueue *q, Priority p = Default_Pri) 146 : queue(q), next(NULL), _priority(p), _flags(None), 147#if TRACING_ON 148 when_created(curTick), when_scheduled(0), 149#endif 150 annotated_value(0) 151 { 152 } 153 154 ~Event() {} 155 156 virtual const std::string name() const { 157 return csprintf("Event_%x", (uintptr_t)this); 158 } 159 160 /// Determine if the current event is scheduled 161 bool scheduled() const { return getFlags(Scheduled); } 162 163 /// Schedule the event with the current priority or default priority 164 void schedule(Tick t); 165 166 /// Reschedule the event with the current priority 167 void reschedule(Tick t); 168 169 /// Remove the event from the current schedule 170 void deschedule(); 171 172 /// Return a C string describing the event. This string should 173 /// *not* be dynamically allocated; just a const char array 174 /// describing the event class. 175 virtual const char *description(); 176 177 /// Dump the current event data 178 void dump(); 179 180 /* 181 * This member function is invoked when the event is processed 182 * (occurs). There is no default implementation; each subclass 183 * must provide its own implementation. The event is not 184 * automatically deleted after it is processed (to allow for 185 * statically allocated event objects). 186 * 187 * If the AutoDestroy flag is set, the object is deleted once it 188 * is processed. 189 */ 190 virtual void process() = 0; 191 192 void annotate(unsigned value) { annotated_value = value; }; 193 unsigned annotation() { return annotated_value; } 194 195 /// Squash the current event 196 void squash() { setFlags(Squashed); } 197 198 /// Check whether the event is squashed 199 bool squashed() { return getFlags(Squashed); } 200 201 /// Get the time that the event is scheduled 202 Tick when() const { return _when; } 203 204 /// Get the event priority 205 int priority() const { return _priority; } 206 207 struct priority_compare : 208 public std::binary_function<Event *, Event *, bool> 209 { 210 bool operator()(const Event *l, const Event *r) const { 211 return l->when() >= r->when() || l->priority() >= r->priority(); 212 } 213 }; 214 215 virtual void serialize(std::ostream &os); 216 virtual void unserialize(Checkpoint *cp, const std::string §ion); 217}; 218 219template <class T, void (T::* F)()> 220void 221DelayFunction(Tick when, T *object) 222{ 223 class DelayEvent : public Event 224 { 225 private: 226 T *object; 227 228 public: 229 DelayEvent(Tick when, T *o) 230 : Event(&mainEventQueue), object(o) 231 { setFlags(AutoDestroy); schedule(when); } 232 void process() { (object->*F)(); } 233 const char *description() { return "delay"; } 234 }; 235 236 new DelayEvent(when, object); 237} 238 239template <class T, void (T::* F)()> 240class EventWrapper : public Event 241{ 242 private: 243 T *object; 244 245 public: 246 EventWrapper(T *obj, EventQueue *q = &mainEventQueue, 247 Priority p = Default_Pri) 248 : Event(q, p), object(obj) 249 {} 250 void process() { (object->*F)(); } 251}; 252 253/* 254 * Queue of events sorted in time order 255 */ 256class EventQueue : public Serializable 257{ 258 protected: 259 std::string objName; 260 261 private: 262 Event *head; 263 264 void insert(Event *event); 265 void remove(Event *event); 266 267 public: 268 269 // constructor 270 EventQueue(const std::string &n) 271 : objName(n), head(NULL) 272 {} 273 274 virtual const std::string name() const { return objName; } 275 276 // schedule the given event on this queue 277 void schedule(Event *ev); 278 void deschedule(Event *ev); 279 void reschedule(Event *ev); 280 281 Tick nextTick() { return head->when(); } 282 void serviceOne(); 283 284 // process all events up to the given timestamp. we inline a 285 // quick test to see if there are any events to process; if so, 286 // call the internal out-of-line version to process them all. 287 void serviceEvents(Tick when) { 288 while (!empty()) { 289 if (nextTick() > when) 290 break; 291 292 assert(head->when() >= when && "event scheduled in the past"); 293 serviceOne(); 294 } 295 } 296 297 // default: process all events up to 'now' (curTick) 298 void serviceEvents() { serviceEvents(curTick); } 299 300 // return true if no events are queued 301 bool empty() { return head == NULL; } 302 303 void dump(); 304 305 Tick nextEventTime() { return empty() ? curTick : head->when(); } 306 307 virtual void serialize(std::ostream &os); 308 virtual void unserialize(Checkpoint *cp, const std::string §ion); 309}; 310 311 312////////////////////// 313// 314// inline functions 315// 316// can't put these inside declaration due to circular dependence 317// between Event and EventQueue classes. 318// 319////////////////////// 320 321// schedule at specified time (place on event queue specified via 322// constructor) 323inline void 324Event::schedule(Tick t) 325{ 326 assert(!scheduled()); 327 setFlags(Scheduled); 328#if TRACING_ON 329 when_scheduled = curTick; 330#endif 331 _when = t; 332 queue->schedule(this); 333} 334 335inline void 336Event::deschedule() 337{ 338 assert(scheduled()); 339 340 clearFlags(Squashed); 341 clearFlags(Scheduled); 342 queue->deschedule(this); 343} 344 345inline void 346Event::reschedule(Tick t) 347{ 348 assert(scheduled()); 349 clearFlags(Squashed); 350 351#if TRACING_ON 352 when_scheduled = curTick; 353#endif 354 _when = t; 355 queue->reschedule(this); 356} 357 358inline void 359EventQueue::schedule(Event *event) 360{ 361 insert(event); 362 if (DTRACE(Event)) 363 event->trace("scheduled"); 364} 365 366inline void 367EventQueue::deschedule(Event *event) 368{ 369 remove(event); 370 if (DTRACE(Event)) 371 event->trace("descheduled"); 372} 373 374inline void 375EventQueue::reschedule(Event *event) 376{ 377 remove(event); 378 insert(event); 379 if (DTRACE(Event)) 380 event->trace("rescheduled"); 381} 382 383 384////////////////////// 385// 386// Main Event Queue 387// 388// Events on this queue are processed at the *beginning* of each 389// cycle, before the pipeline simulation is performed. 390// 391// defined in eventq.cc 392// 393////////////////////// 394extern EventQueue mainEventQueue; 395 396#endif // __EVENTQ_HH__ 397