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