eventq.hh (9159:8adc048515b8) eventq.hh (9356:b279bad40aa3)
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 <algorithm>
40#include <cassert>
41#include <climits>
42#include <iosfwd>
43#include <string>
44
45#include "base/flags.hh"
46#include "base/misc.hh"
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 <algorithm>
40#include <cassert>
41#include <climits>
42#include <iosfwd>
43#include <string>
44
45#include "base/flags.hh"
46#include "base/misc.hh"
47#include "base/trace.hh"
48#include "base/types.hh"
49#include "debug/Event.hh"
50#include "sim/serialize.hh"
51
52class EventQueue; // forward declaration
53
54extern EventQueue mainEventQueue;
55
56/*
57 * An item on an event queue. The action caused by a given
58 * event is specified by deriving a subclass and overriding the
59 * process() member function.
60 *
61 * Caution, the order of members is chosen to maximize data packing.
62 */
63class Event : public Serializable
64{
65 friend class EventQueue;
66
67 protected:
68 typedef unsigned short FlagsType;
69 typedef ::Flags<FlagsType> Flags;
70
71 static const FlagsType PublicRead = 0x003f; // public readable flags
72 static const FlagsType PublicWrite = 0x001d; // public writable flags
73 static const FlagsType Squashed = 0x0001; // has been squashed
74 static const FlagsType Scheduled = 0x0002; // has been scheduled
75 static const FlagsType AutoDelete = 0x0004; // delete after dispatch
76 static const FlagsType AutoSerialize = 0x0008; // must be serialized
77 static const FlagsType IsExitEvent = 0x0010; // special exit event
78 static const FlagsType IsMainQueue = 0x0020; // on main event queue
79 static const FlagsType Initialized = 0x7a40; // somewhat random bits
80 static const FlagsType InitMask = 0xffc0; // mask for init bits
81
82 bool
83 initialized() const
84 {
85 return this && (flags & InitMask) == Initialized;
86 }
87
88 public:
89 typedef int8_t Priority;
90
91 private:
92 // The event queue is now a linked list of linked lists. The
93 // 'nextBin' pointer is to find the bin, where a bin is defined as
94 // when+priority. All events in the same bin will be stored in a
95 // second linked list (a stack) maintained by the 'nextInBin'
96 // pointer. The list will be accessed in LIFO order. The end
97 // result is that the insert/removal in 'nextBin' is
98 // linear/constant, and the lookup/removal in 'nextInBin' is
99 // constant/constant. Hopefully this is a significant improvement
100 // over the current fully linear insertion.
101 Event *nextBin;
102 Event *nextInBin;
103
104 static Event *insertBefore(Event *event, Event *curr);
105 static Event *removeItem(Event *event, Event *last);
106
107 Tick _when; //!< timestamp when event should be processed
108 Priority _priority; //!< event priority
109 Flags flags;
110
111#ifndef NDEBUG
112 /// Global counter to generate unique IDs for Event instances
113 static Counter instanceCounter;
114
115 /// This event's unique ID. We can also use pointer values for
116 /// this but they're not consistent across runs making debugging
117 /// more difficult. Thus we use a global counter value when
118 /// debugging.
119 Counter instance;
120
121 /// queue to which this event belongs (though it may or may not be
122 /// scheduled on this queue yet)
123 EventQueue *queue;
124#endif
125
126#ifdef EVENTQ_DEBUG
127 Tick whenCreated; //!< time created
128 Tick whenScheduled; //!< time scheduled
129#endif
130
131 void
132 setWhen(Tick when, EventQueue *q)
133 {
134 _when = when;
135#ifndef NDEBUG
136 queue = q;
137#endif
138#ifdef EVENTQ_DEBUG
139 whenScheduled = curTick();
140#endif
141 }
142
143 protected:
144 /// Accessor for flags.
145 Flags
146 getFlags() const
147 {
148 return flags & PublicRead;
149 }
150
151 bool
152 isFlagSet(Flags _flags) const
153 {
154 assert(_flags.noneSet(~PublicRead));
155 return flags.isSet(_flags);
156 }
157
158 /// Accessor for flags.
159 void
160 setFlags(Flags _flags)
161 {
162 assert(_flags.noneSet(~PublicWrite));
163 flags.set(_flags);
164 }
165
166 void
167 clearFlags(Flags _flags)
168 {
169 assert(_flags.noneSet(~PublicWrite));
170 flags.clear(_flags);
171 }
172
173 void
174 clearFlags()
175 {
176 flags.clear(PublicWrite);
177 }
178
179 // This function isn't really useful if TRACING_ON is not defined
180 virtual void trace(const char *action); //!< trace event activity
181
182 public:
183 /// Event priorities, to provide tie-breakers for events scheduled
184 /// at the same cycle. Most events are scheduled at the default
185 /// priority; these values are used to control events that need to
186 /// be ordered within a cycle.
187
188 /// Minimum priority
189 static const Priority Minimum_Pri = SCHAR_MIN;
190
191 /// If we enable tracing on a particular cycle, do that as the
192 /// very first thing so we don't miss any of the events on
193 /// that cycle (even if we enter the debugger).
194 static const Priority Trace_Enable_Pri = -101;
195
196 /// Breakpoints should happen before anything else (except
197 /// enabling trace output), so we don't miss any action when
198 /// debugging.
199 static const Priority Debug_Break_Pri = -100;
200
201 /// CPU switches schedule the new CPU's tick event for the
202 /// same cycle (after unscheduling the old CPU's tick event).
203 /// The switch needs to come before any tick events to make
204 /// sure we don't tick both CPUs in the same cycle.
205 static const Priority CPU_Switch_Pri = -31;
206
207 /// For some reason "delayed" inter-cluster writebacks are
208 /// scheduled before regular writebacks (which have default
209 /// priority). Steve?
210 static const Priority Delayed_Writeback_Pri = -1;
211
212 /// Default is zero for historical reasons.
213 static const Priority Default_Pri = 0;
214
215 /// Serailization needs to occur before tick events also, so
216 /// that a serialize/unserialize is identical to an on-line
217 /// CPU switch.
218 static const Priority Serialize_Pri = 32;
219
220 /// CPU ticks must come after other associated CPU events
221 /// (such as writebacks).
222 static const Priority CPU_Tick_Pri = 50;
223
224 /// Statistics events (dump, reset, etc.) come after
225 /// everything else, but before exit.
226 static const Priority Stat_Event_Pri = 90;
227
228 /// Progress events come at the end.
229 static const Priority Progress_Event_Pri = 95;
230
231 /// If we want to exit on this cycle, it's the very last thing
232 /// we do.
233 static const Priority Sim_Exit_Pri = 100;
234
235 /// Maximum priority
236 static const Priority Maximum_Pri = SCHAR_MAX;
237
238 /*
239 * Event constructor
240 * @param queue that the event gets scheduled on
241 */
242 Event(Priority p = Default_Pri, Flags f = 0)
243 : nextBin(NULL), nextInBin(NULL), _priority(p),
244 flags(Initialized | f)
245 {
246 assert(f.noneSet(~PublicWrite));
247#ifndef NDEBUG
248 instance = ++instanceCounter;
249 queue = NULL;
250#endif
251#ifdef EVENTQ_DEBUG
252 whenCreated = curTick();
253 whenScheduled = 0;
254#endif
255 }
256
257 virtual ~Event();
258 virtual const std::string name() const;
259
260 /// Return a C string describing the event. This string should
261 /// *not* be dynamically allocated; just a const char array
262 /// describing the event class.
263 virtual const char *description() const;
264
265 /// Dump the current event data
266 void dump() const;
267
268 public:
269 /*
270 * This member function is invoked when the event is processed
271 * (occurs). There is no default implementation; each subclass
272 * must provide its own implementation. The event is not
273 * automatically deleted after it is processed (to allow for
274 * statically allocated event objects).
275 *
276 * If the AutoDestroy flag is set, the object is deleted once it
277 * is processed.
278 */
279 virtual void process() = 0;
280
281 /// Determine if the current event is scheduled
282 bool scheduled() const { return flags.isSet(Scheduled); }
283
284 /// Squash the current event
285 void squash() { flags.set(Squashed); }
286
287 /// Check whether the event is squashed
288 bool squashed() const { return flags.isSet(Squashed); }
289
290 /// See if this is a SimExitEvent (without resorting to RTTI)
291 bool isExitEvent() const { return flags.isSet(IsExitEvent); }
292
293 /// Get the time that the event is scheduled
294 Tick when() const { return _when; }
295
296 /// Get the event priority
297 Priority priority() const { return _priority; }
298
299#ifndef SWIG
300 struct priority_compare
301 : public std::binary_function<Event *, Event *, bool>
302 {
303 bool
304 operator()(const Event *l, const Event *r) const
305 {
306 return l->when() >= r->when() || l->priority() >= r->priority();
307 }
308 };
309
310 virtual void serialize(std::ostream &os);
311 virtual void unserialize(Checkpoint *cp, const std::string &section);
312#endif
313};
314
315#ifndef SWIG
316inline bool
317operator<(const Event &l, const Event &r)
318{
319 return l.when() < r.when() ||
320 (l.when() == r.when() && l.priority() < r.priority());
321}
322
323inline bool
324operator>(const Event &l, const Event &r)
325{
326 return l.when() > r.when() ||
327 (l.when() == r.when() && l.priority() > r.priority());
328}
329
330inline bool
331operator<=(const Event &l, const Event &r)
332{
333 return l.when() < r.when() ||
334 (l.when() == r.when() && l.priority() <= r.priority());
335}
336inline bool
337operator>=(const Event &l, const Event &r)
338{
339 return l.when() > r.when() ||
340 (l.when() == r.when() && l.priority() >= r.priority());
341}
342
343inline bool
344operator==(const Event &l, const Event &r)
345{
346 return l.when() == r.when() && l.priority() == r.priority();
347}
348
349inline bool
350operator!=(const Event &l, const Event &r)
351{
352 return l.when() != r.when() || l.priority() != r.priority();
353}
354#endif
355
356/*
357 * Queue of events sorted in time order
358 */
359class EventQueue : public Serializable
360{
361 private:
362 std::string objName;
363 Event *head;
47#include "base/types.hh"
48#include "debug/Event.hh"
49#include "sim/serialize.hh"
50
51class EventQueue; // forward declaration
52
53extern EventQueue mainEventQueue;
54
55/*
56 * An item on an event queue. The action caused by a given
57 * event is specified by deriving a subclass and overriding the
58 * process() member function.
59 *
60 * Caution, the order of members is chosen to maximize data packing.
61 */
62class Event : public Serializable
63{
64 friend class EventQueue;
65
66 protected:
67 typedef unsigned short FlagsType;
68 typedef ::Flags<FlagsType> Flags;
69
70 static const FlagsType PublicRead = 0x003f; // public readable flags
71 static const FlagsType PublicWrite = 0x001d; // public writable flags
72 static const FlagsType Squashed = 0x0001; // has been squashed
73 static const FlagsType Scheduled = 0x0002; // has been scheduled
74 static const FlagsType AutoDelete = 0x0004; // delete after dispatch
75 static const FlagsType AutoSerialize = 0x0008; // must be serialized
76 static const FlagsType IsExitEvent = 0x0010; // special exit event
77 static const FlagsType IsMainQueue = 0x0020; // on main event queue
78 static const FlagsType Initialized = 0x7a40; // somewhat random bits
79 static const FlagsType InitMask = 0xffc0; // mask for init bits
80
81 bool
82 initialized() const
83 {
84 return this && (flags & InitMask) == Initialized;
85 }
86
87 public:
88 typedef int8_t Priority;
89
90 private:
91 // The event queue is now a linked list of linked lists. The
92 // 'nextBin' pointer is to find the bin, where a bin is defined as
93 // when+priority. All events in the same bin will be stored in a
94 // second linked list (a stack) maintained by the 'nextInBin'
95 // pointer. The list will be accessed in LIFO order. The end
96 // result is that the insert/removal in 'nextBin' is
97 // linear/constant, and the lookup/removal in 'nextInBin' is
98 // constant/constant. Hopefully this is a significant improvement
99 // over the current fully linear insertion.
100 Event *nextBin;
101 Event *nextInBin;
102
103 static Event *insertBefore(Event *event, Event *curr);
104 static Event *removeItem(Event *event, Event *last);
105
106 Tick _when; //!< timestamp when event should be processed
107 Priority _priority; //!< event priority
108 Flags flags;
109
110#ifndef NDEBUG
111 /// Global counter to generate unique IDs for Event instances
112 static Counter instanceCounter;
113
114 /// This event's unique ID. We can also use pointer values for
115 /// this but they're not consistent across runs making debugging
116 /// more difficult. Thus we use a global counter value when
117 /// debugging.
118 Counter instance;
119
120 /// queue to which this event belongs (though it may or may not be
121 /// scheduled on this queue yet)
122 EventQueue *queue;
123#endif
124
125#ifdef EVENTQ_DEBUG
126 Tick whenCreated; //!< time created
127 Tick whenScheduled; //!< time scheduled
128#endif
129
130 void
131 setWhen(Tick when, EventQueue *q)
132 {
133 _when = when;
134#ifndef NDEBUG
135 queue = q;
136#endif
137#ifdef EVENTQ_DEBUG
138 whenScheduled = curTick();
139#endif
140 }
141
142 protected:
143 /// Accessor for flags.
144 Flags
145 getFlags() const
146 {
147 return flags & PublicRead;
148 }
149
150 bool
151 isFlagSet(Flags _flags) const
152 {
153 assert(_flags.noneSet(~PublicRead));
154 return flags.isSet(_flags);
155 }
156
157 /// Accessor for flags.
158 void
159 setFlags(Flags _flags)
160 {
161 assert(_flags.noneSet(~PublicWrite));
162 flags.set(_flags);
163 }
164
165 void
166 clearFlags(Flags _flags)
167 {
168 assert(_flags.noneSet(~PublicWrite));
169 flags.clear(_flags);
170 }
171
172 void
173 clearFlags()
174 {
175 flags.clear(PublicWrite);
176 }
177
178 // This function isn't really useful if TRACING_ON is not defined
179 virtual void trace(const char *action); //!< trace event activity
180
181 public:
182 /// Event priorities, to provide tie-breakers for events scheduled
183 /// at the same cycle. Most events are scheduled at the default
184 /// priority; these values are used to control events that need to
185 /// be ordered within a cycle.
186
187 /// Minimum priority
188 static const Priority Minimum_Pri = SCHAR_MIN;
189
190 /// If we enable tracing on a particular cycle, do that as the
191 /// very first thing so we don't miss any of the events on
192 /// that cycle (even if we enter the debugger).
193 static const Priority Trace_Enable_Pri = -101;
194
195 /// Breakpoints should happen before anything else (except
196 /// enabling trace output), so we don't miss any action when
197 /// debugging.
198 static const Priority Debug_Break_Pri = -100;
199
200 /// CPU switches schedule the new CPU's tick event for the
201 /// same cycle (after unscheduling the old CPU's tick event).
202 /// The switch needs to come before any tick events to make
203 /// sure we don't tick both CPUs in the same cycle.
204 static const Priority CPU_Switch_Pri = -31;
205
206 /// For some reason "delayed" inter-cluster writebacks are
207 /// scheduled before regular writebacks (which have default
208 /// priority). Steve?
209 static const Priority Delayed_Writeback_Pri = -1;
210
211 /// Default is zero for historical reasons.
212 static const Priority Default_Pri = 0;
213
214 /// Serailization needs to occur before tick events also, so
215 /// that a serialize/unserialize is identical to an on-line
216 /// CPU switch.
217 static const Priority Serialize_Pri = 32;
218
219 /// CPU ticks must come after other associated CPU events
220 /// (such as writebacks).
221 static const Priority CPU_Tick_Pri = 50;
222
223 /// Statistics events (dump, reset, etc.) come after
224 /// everything else, but before exit.
225 static const Priority Stat_Event_Pri = 90;
226
227 /// Progress events come at the end.
228 static const Priority Progress_Event_Pri = 95;
229
230 /// If we want to exit on this cycle, it's the very last thing
231 /// we do.
232 static const Priority Sim_Exit_Pri = 100;
233
234 /// Maximum priority
235 static const Priority Maximum_Pri = SCHAR_MAX;
236
237 /*
238 * Event constructor
239 * @param queue that the event gets scheduled on
240 */
241 Event(Priority p = Default_Pri, Flags f = 0)
242 : nextBin(NULL), nextInBin(NULL), _priority(p),
243 flags(Initialized | f)
244 {
245 assert(f.noneSet(~PublicWrite));
246#ifndef NDEBUG
247 instance = ++instanceCounter;
248 queue = NULL;
249#endif
250#ifdef EVENTQ_DEBUG
251 whenCreated = curTick();
252 whenScheduled = 0;
253#endif
254 }
255
256 virtual ~Event();
257 virtual const std::string name() const;
258
259 /// Return a C string describing the event. This string should
260 /// *not* be dynamically allocated; just a const char array
261 /// describing the event class.
262 virtual const char *description() const;
263
264 /// Dump the current event data
265 void dump() const;
266
267 public:
268 /*
269 * This member function is invoked when the event is processed
270 * (occurs). There is no default implementation; each subclass
271 * must provide its own implementation. The event is not
272 * automatically deleted after it is processed (to allow for
273 * statically allocated event objects).
274 *
275 * If the AutoDestroy flag is set, the object is deleted once it
276 * is processed.
277 */
278 virtual void process() = 0;
279
280 /// Determine if the current event is scheduled
281 bool scheduled() const { return flags.isSet(Scheduled); }
282
283 /// Squash the current event
284 void squash() { flags.set(Squashed); }
285
286 /// Check whether the event is squashed
287 bool squashed() const { return flags.isSet(Squashed); }
288
289 /// See if this is a SimExitEvent (without resorting to RTTI)
290 bool isExitEvent() const { return flags.isSet(IsExitEvent); }
291
292 /// Get the time that the event is scheduled
293 Tick when() const { return _when; }
294
295 /// Get the event priority
296 Priority priority() const { return _priority; }
297
298#ifndef SWIG
299 struct priority_compare
300 : public std::binary_function<Event *, Event *, bool>
301 {
302 bool
303 operator()(const Event *l, const Event *r) const
304 {
305 return l->when() >= r->when() || l->priority() >= r->priority();
306 }
307 };
308
309 virtual void serialize(std::ostream &os);
310 virtual void unserialize(Checkpoint *cp, const std::string &section);
311#endif
312};
313
314#ifndef SWIG
315inline bool
316operator<(const Event &l, const Event &r)
317{
318 return l.when() < r.when() ||
319 (l.when() == r.when() && l.priority() < r.priority());
320}
321
322inline bool
323operator>(const Event &l, const Event &r)
324{
325 return l.when() > r.when() ||
326 (l.when() == r.when() && l.priority() > r.priority());
327}
328
329inline bool
330operator<=(const Event &l, const Event &r)
331{
332 return l.when() < r.when() ||
333 (l.when() == r.when() && l.priority() <= r.priority());
334}
335inline bool
336operator>=(const Event &l, const Event &r)
337{
338 return l.when() > r.when() ||
339 (l.when() == r.when() && l.priority() >= r.priority());
340}
341
342inline bool
343operator==(const Event &l, const Event &r)
344{
345 return l.when() == r.when() && l.priority() == r.priority();
346}
347
348inline bool
349operator!=(const Event &l, const Event &r)
350{
351 return l.when() != r.when() || l.priority() != r.priority();
352}
353#endif
354
355/*
356 * Queue of events sorted in time order
357 */
358class EventQueue : public Serializable
359{
360 private:
361 std::string objName;
362 Event *head;
363 Tick _curTick;
364
365 void insert(Event *event);
366 void remove(Event *event);
367
368 EventQueue(const EventQueue &);
369 const EventQueue &operator=(const EventQueue &);
370
371 public:
372 EventQueue(const std::string &n);
373
374 virtual const std::string name() const { return objName; }
375
376 // schedule the given event on this queue
377 void schedule(Event *event, Tick when);
378 void deschedule(Event *event);
379 void reschedule(Event *event, Tick when, bool always = false);
380
381 Tick nextTick() const { return head->when(); }
364
365 void insert(Event *event);
366 void remove(Event *event);
367
368 EventQueue(const EventQueue &);
369 const EventQueue &operator=(const EventQueue &);
370
371 public:
372 EventQueue(const std::string &n);
373
374 virtual const std::string name() const { return objName; }
375
376 // schedule the given event on this queue
377 void schedule(Event *event, Tick when);
378 void deschedule(Event *event);
379 void reschedule(Event *event, Tick when, bool always = false);
380
381 Tick nextTick() const { return head->when(); }
382 void setCurTick(Tick newVal) { _curTick = newVal; }
383 Tick getCurTick() { return _curTick; }
384
382 Event *serviceOne();
383
384 // process all events up to the given timestamp. we inline a
385 // quick test to see if there are any events to process; if so,
386 // call the internal out-of-line version to process them all.
387 void
388 serviceEvents(Tick when)
389 {
390 while (!empty()) {
391 if (nextTick() > when)
392 break;
393
394 /**
395 * @todo this assert is a good bug catcher. I need to
396 * make it true again.
397 */
398 //assert(head->when() >= when && "event scheduled in the past");
399 serviceOne();
400 }
385 Event *serviceOne();
386
387 // process all events up to the given timestamp. we inline a
388 // quick test to see if there are any events to process; if so,
389 // call the internal out-of-line version to process them all.
390 void
391 serviceEvents(Tick when)
392 {
393 while (!empty()) {
394 if (nextTick() > when)
395 break;
396
397 /**
398 * @todo this assert is a good bug catcher. I need to
399 * make it true again.
400 */
401 //assert(head->when() >= when && "event scheduled in the past");
402 serviceOne();
403 }
404
405 setCurTick(when);
401 }
402
403 // return true if no events are queued
404 bool empty() const { return head == NULL; }
405
406 void dump() const;
407
408 bool debugVerify() const;
409
410 /**
411 * function for replacing the head of the event queue, so that a
412 * different set of events can run without disturbing events that have
413 * already been scheduled. Already scheduled events can be processed
414 * by replacing the original head back.
415 * USING THIS FUNCTION CAN BE DANGEROUS TO THE HEALTH OF THE SIMULATOR.
416 * NOT RECOMMENDED FOR USE.
417 */
418 Event* replaceHead(Event* s);
419
420#ifndef SWIG
421 virtual void serialize(std::ostream &os);
422 virtual void unserialize(Checkpoint *cp, const std::string &section);
423#endif
424};
425
426#ifndef SWIG
427class EventManager
428{
429 protected:
430 /** A pointer to this object's event queue */
431 EventQueue *eventq;
432
433 public:
434 EventManager(EventManager &em) : eventq(em.eventq) {}
435 EventManager(EventManager *em) : eventq(em->eventq) {}
436 EventManager(EventQueue *eq) : eventq(eq) {}
437
438 EventQueue *
439 eventQueue() const
440 {
441 return eventq;
442 }
443
444 void
445 schedule(Event &event, Tick when)
446 {
447 eventq->schedule(&event, when);
448 }
449
450 void
451 deschedule(Event &event)
452 {
453 eventq->deschedule(&event);
454 }
455
456 void
457 reschedule(Event &event, Tick when, bool always = false)
458 {
459 eventq->reschedule(&event, when, always);
460 }
461
462 void
463 schedule(Event *event, Tick when)
464 {
465 eventq->schedule(event, when);
466 }
467
468 void
469 deschedule(Event *event)
470 {
471 eventq->deschedule(event);
472 }
473
474 void
475 reschedule(Event *event, Tick when, bool always = false)
476 {
477 eventq->reschedule(event, when, always);
478 }
406 }
407
408 // return true if no events are queued
409 bool empty() const { return head == NULL; }
410
411 void dump() const;
412
413 bool debugVerify() const;
414
415 /**
416 * function for replacing the head of the event queue, so that a
417 * different set of events can run without disturbing events that have
418 * already been scheduled. Already scheduled events can be processed
419 * by replacing the original head back.
420 * USING THIS FUNCTION CAN BE DANGEROUS TO THE HEALTH OF THE SIMULATOR.
421 * NOT RECOMMENDED FOR USE.
422 */
423 Event* replaceHead(Event* s);
424
425#ifndef SWIG
426 virtual void serialize(std::ostream &os);
427 virtual void unserialize(Checkpoint *cp, const std::string &section);
428#endif
429};
430
431#ifndef SWIG
432class EventManager
433{
434 protected:
435 /** A pointer to this object's event queue */
436 EventQueue *eventq;
437
438 public:
439 EventManager(EventManager &em) : eventq(em.eventq) {}
440 EventManager(EventManager *em) : eventq(em->eventq) {}
441 EventManager(EventQueue *eq) : eventq(eq) {}
442
443 EventQueue *
444 eventQueue() const
445 {
446 return eventq;
447 }
448
449 void
450 schedule(Event &event, Tick when)
451 {
452 eventq->schedule(&event, when);
453 }
454
455 void
456 deschedule(Event &event)
457 {
458 eventq->deschedule(&event);
459 }
460
461 void
462 reschedule(Event &event, Tick when, bool always = false)
463 {
464 eventq->reschedule(&event, when, always);
465 }
466
467 void
468 schedule(Event *event, Tick when)
469 {
470 eventq->schedule(event, when);
471 }
472
473 void
474 deschedule(Event *event)
475 {
476 eventq->deschedule(event);
477 }
478
479 void
480 reschedule(Event *event, Tick when, bool always = false)
481 {
482 eventq->reschedule(event, when, always);
483 }
484
485 void setCurTick(Tick newVal) { eventq->setCurTick(newVal); }
479};
480
486};
487
481inline void
482EventQueue::schedule(Event *event, Tick when)
483{
484 assert(when >= curTick());
485 assert(!event->scheduled());
486 assert(event->initialized());
487
488 event->setWhen(when, this);
489 insert(event);
490 event->flags.set(Event::Scheduled);
491 if (this == &mainEventQueue)
492 event->flags.set(Event::IsMainQueue);
493 else
494 event->flags.clear(Event::IsMainQueue);
495
496 if (DTRACE(Event))
497 event->trace("scheduled");
498}
499
500inline void
501EventQueue::deschedule(Event *event)
502{
503 assert(event->scheduled());
504 assert(event->initialized());
505
506 remove(event);
507
508 event->flags.clear(Event::Squashed);
509 event->flags.clear(Event::Scheduled);
510
511 if (DTRACE(Event))
512 event->trace("descheduled");
513
514 if (event->flags.isSet(Event::AutoDelete))
515 delete event;
516}
517
518inline void
519EventQueue::reschedule(Event *event, Tick when, bool always)
520{
521 assert(when >= curTick());
522 assert(always || event->scheduled());
523 assert(event->initialized());
524
525 if (event->scheduled())
526 remove(event);
527
528 event->setWhen(when, this);
529 insert(event);
530 event->flags.clear(Event::Squashed);
531 event->flags.set(Event::Scheduled);
532 if (this == &mainEventQueue)
533 event->flags.set(Event::IsMainQueue);
534 else
535 event->flags.clear(Event::IsMainQueue);
536
537 if (DTRACE(Event))
538 event->trace("rescheduled");
539}
540
541template <class T, void (T::* F)()>
542void
543DelayFunction(EventQueue *eventq, Tick when, T *object)
544{
545 class DelayEvent : public Event
546 {
547 private:
548 T *object;
549
550 public:
551 DelayEvent(T *o)
552 : Event(Default_Pri, AutoDelete), object(o)
553 { }
554 void process() { (object->*F)(); }
555 const char *description() const { return "delay"; }
556 };
557
558 eventq->schedule(new DelayEvent(object), when);
559}
560
561template <class T, void (T::* F)()>
562class EventWrapper : public Event
563{
564 private:
565 T *object;
566
567 public:
568 EventWrapper(T *obj, bool del = false, Priority p = Default_Pri)
569 : Event(p), object(obj)
570 {
571 if (del)
572 setFlags(AutoDelete);
573 }
574
575 EventWrapper(T &obj, bool del = false, Priority p = Default_Pri)
576 : Event(p), object(&obj)
577 {
578 if (del)
579 setFlags(AutoDelete);
580 }
581
582 void process() { (object->*F)(); }
583
584 const std::string
585 name() const
586 {
587 return object->name() + ".wrapped_event";
588 }
589
590 const char *description() const { return "EventWrapped"; }
591};
592#endif
593
594#endif // __SIM_EVENTQ_HH__
488template <class T, void (T::* F)()>
489void
490DelayFunction(EventQueue *eventq, Tick when, T *object)
491{
492 class DelayEvent : public Event
493 {
494 private:
495 T *object;
496
497 public:
498 DelayEvent(T *o)
499 : Event(Default_Pri, AutoDelete), object(o)
500 { }
501 void process() { (object->*F)(); }
502 const char *description() const { return "delay"; }
503 };
504
505 eventq->schedule(new DelayEvent(object), when);
506}
507
508template <class T, void (T::* F)()>
509class EventWrapper : public Event
510{
511 private:
512 T *object;
513
514 public:
515 EventWrapper(T *obj, bool del = false, Priority p = Default_Pri)
516 : Event(p), object(obj)
517 {
518 if (del)
519 setFlags(AutoDelete);
520 }
521
522 EventWrapper(T &obj, bool del = false, Priority p = Default_Pri)
523 : Event(p), object(&obj)
524 {
525 if (del)
526 setFlags(AutoDelete);
527 }
528
529 void process() { (object->*F)(); }
530
531 const std::string
532 name() const
533 {
534 return object->name() + ".wrapped_event";
535 }
536
537 const char *description() const { return "EventWrapped"; }
538};
539#endif
540
541#endif // __SIM_EVENTQ_HH__