eventq.hh revision 9554:406fbcf60223
14120Sgblack@eecs.umich.edu/* 24120Sgblack@eecs.umich.edu * Copyright (c) 2000-2005 The Regents of The University of Michigan 37087Snate@binkert.org * All rights reserved. 47087Snate@binkert.org * 57087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 67087Snate@binkert.org * modification, are permitted provided that the following conditions are 77087Snate@binkert.org * met: redistributions of source code must retain the above copyright 87087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 117087Snate@binkert.org * documentation and/or other materials provided with the distribution; 127087Snate@binkert.org * neither the name of the copyright holders nor the names of its 137087Snate@binkert.org * contributors may be used to endorse or promote products derived from 147087Snate@binkert.org * this software without specific prior written permission. 154120Sgblack@eecs.umich.edu * 164120Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174120Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184120Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194120Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204120Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214120Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224120Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234120Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244120Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254120Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264120Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274120Sgblack@eecs.umich.edu * 284120Sgblack@eecs.umich.edu * Authors: Steve Reinhardt 294120Sgblack@eecs.umich.edu * Nathan Binkert 304120Sgblack@eecs.umich.edu */ 314120Sgblack@eecs.umich.edu 324120Sgblack@eecs.umich.edu/* @file 334120Sgblack@eecs.umich.edu * EventQueue interfaces 344120Sgblack@eecs.umich.edu */ 354120Sgblack@eecs.umich.edu 364120Sgblack@eecs.umich.edu#ifndef __SIM_EVENTQ_HH__ 374120Sgblack@eecs.umich.edu#define __SIM_EVENTQ_HH__ 384120Sgblack@eecs.umich.edu 394120Sgblack@eecs.umich.edu#include <algorithm> 404120Sgblack@eecs.umich.edu#include <cassert> 414120Sgblack@eecs.umich.edu#include <climits> 424120Sgblack@eecs.umich.edu#include <iosfwd> 434202Sbinkertn@umich.edu#include <string> 445069Sgblack@eecs.umich.edu 454202Sbinkertn@umich.edu#include "base/flags.hh" 465659Sgblack@eecs.umich.edu#include "base/misc.hh" 479022Sgblack@eecs.umich.edu#include "base/types.hh" 489023Sgblack@eecs.umich.edu#include "debug/Event.hh" 494601Sgblack@eecs.umich.edu#include "sim/serialize.hh" 505124Sgblack@eecs.umich.edu 517966Sgblack@eecs.umich.educlass EventQueue; // forward declaration 525083Sgblack@eecs.umich.edu 534679Sgblack@eecs.umich.eduextern EventQueue mainEventQueue; 546515Sgblack@eecs.umich.edu 555083Sgblack@eecs.umich.edu/* 564679Sgblack@eecs.umich.edu * An item on an event queue. The action caused by a given 574679Sgblack@eecs.umich.edu * event is specified by deriving a subclass and overriding the 588745Sgblack@eecs.umich.edu * process() member function. 596313Sgblack@eecs.umich.edu * 608771Sgblack@eecs.umich.edu * Caution, the order of members is chosen to maximize data packing. 618771Sgblack@eecs.umich.edu */ 628771Sgblack@eecs.umich.educlass Event : public Serializable 636365Sgblack@eecs.umich.edu{ 645124Sgblack@eecs.umich.edu friend class EventQueue; 658752Sgblack@eecs.umich.edu 668771Sgblack@eecs.umich.edu protected: 6710553Salexandru.dutu@amd.com typedef unsigned short FlagsType; 684202Sbinkertn@umich.edu typedef ::Flags<FlagsType> Flags; 698771Sgblack@eecs.umich.edu 708771Sgblack@eecs.umich.edu static const FlagsType PublicRead = 0x003f; // public readable flags 714997Sgblack@eecs.umich.edu static const FlagsType PublicWrite = 0x001d; // public writable flags 727624Sgblack@eecs.umich.edu static const FlagsType Squashed = 0x0001; // has been squashed 735135Sgblack@eecs.umich.edu static const FlagsType Scheduled = 0x0002; // has been scheduled 748753Sgblack@eecs.umich.edu static const FlagsType AutoDelete = 0x0004; // delete after dispatch 754997Sgblack@eecs.umich.edu static const FlagsType AutoSerialize = 0x0008; // must be serialized 769384SAndreas.Sandberg@arm.com static const FlagsType IsExitEvent = 0x0010; // special exit event 778745Sgblack@eecs.umich.edu static const FlagsType IsMainQueue = 0x0020; // on main event queue 786365Sgblack@eecs.umich.edu static const FlagsType Initialized = 0x7a40; // somewhat random bits 798771Sgblack@eecs.umich.edu static const FlagsType InitMask = 0xffc0; // mask for init bits 808740Sgblack@eecs.umich.edu 816365Sgblack@eecs.umich.edu bool 828740Sgblack@eecs.umich.edu initialized() const 838745Sgblack@eecs.umich.edu { 848752Sgblack@eecs.umich.edu return this && (flags & InitMask) == Initialized; 858752Sgblack@eecs.umich.edu } 869023Sgblack@eecs.umich.edu 878335Snate@binkert.org public: 884120Sgblack@eecs.umich.edu typedef int8_t Priority; 895069Sgblack@eecs.umich.edu 905081Sgblack@eecs.umich.edu private: 915081Sgblack@eecs.umich.edu // The event queue is now a linked list of linked lists. The 925081Sgblack@eecs.umich.edu // 'nextBin' pointer is to find the bin, where a bin is defined as 935081Sgblack@eecs.umich.edu // when+priority. All events in the same bin will be stored in a 945081Sgblack@eecs.umich.edu // second linked list (a stack) maintained by the 'nextInBin' 955081Sgblack@eecs.umich.edu // pointer. The list will be accessed in LIFO order. The end 965081Sgblack@eecs.umich.edu // result is that the insert/removal in 'nextBin' is 975081Sgblack@eecs.umich.edu // linear/constant, and the lookup/removal in 'nextInBin' is 985081Sgblack@eecs.umich.edu // constant/constant. Hopefully this is a significant improvement 995081Sgblack@eecs.umich.edu // over the current fully linear insertion. 1005081Sgblack@eecs.umich.edu Event *nextBin; 1015081Sgblack@eecs.umich.edu Event *nextInBin; 1025081Sgblack@eecs.umich.edu 1035081Sgblack@eecs.umich.edu static Event *insertBefore(Event *event, Event *curr); 1045081Sgblack@eecs.umich.edu static Event *removeItem(Event *event, Event *last); 1055081Sgblack@eecs.umich.edu 1065081Sgblack@eecs.umich.edu Tick _when; //!< timestamp when event should be processed 1075081Sgblack@eecs.umich.edu Priority _priority; //!< event priority 1085081Sgblack@eecs.umich.edu Flags flags; 1095081Sgblack@eecs.umich.edu 1105081Sgblack@eecs.umich.edu#ifndef NDEBUG 1115081Sgblack@eecs.umich.edu /// Global counter to generate unique IDs for Event instances 1125081Sgblack@eecs.umich.edu static Counter instanceCounter; 1135081Sgblack@eecs.umich.edu 1145081Sgblack@eecs.umich.edu /// This event's unique ID. We can also use pointer values for 1155081Sgblack@eecs.umich.edu /// this but they're not consistent across runs making debugging 1165081Sgblack@eecs.umich.edu /// more difficult. Thus we use a global counter value when 1175081Sgblack@eecs.umich.edu /// debugging. 1185081Sgblack@eecs.umich.edu Counter instance; 1195081Sgblack@eecs.umich.edu 1205081Sgblack@eecs.umich.edu /// queue to which this event belongs (though it may or may not be 1215081Sgblack@eecs.umich.edu /// scheduled on this queue yet) 1225081Sgblack@eecs.umich.edu EventQueue *queue; 1235081Sgblack@eecs.umich.edu#endif 1245081Sgblack@eecs.umich.edu 1255081Sgblack@eecs.umich.edu#ifdef EVENTQ_DEBUG 1265081Sgblack@eecs.umich.edu Tick whenCreated; //!< time created 1275081Sgblack@eecs.umich.edu Tick whenScheduled; //!< time scheduled 1285081Sgblack@eecs.umich.edu#endif 1295081Sgblack@eecs.umich.edu 1305081Sgblack@eecs.umich.edu void 1315081Sgblack@eecs.umich.edu setWhen(Tick when, EventQueue *q) 1325081Sgblack@eecs.umich.edu { 1335081Sgblack@eecs.umich.edu _when = when; 1345081Sgblack@eecs.umich.edu#ifndef NDEBUG 1355081Sgblack@eecs.umich.edu queue = q; 1365081Sgblack@eecs.umich.edu#endif 1375081Sgblack@eecs.umich.edu#ifdef EVENTQ_DEBUG 1385081Sgblack@eecs.umich.edu whenScheduled = curTick(); 1395081Sgblack@eecs.umich.edu#endif 1405081Sgblack@eecs.umich.edu } 1415081Sgblack@eecs.umich.edu 1425081Sgblack@eecs.umich.edu protected: 1435081Sgblack@eecs.umich.edu /// Accessor for flags. 1445081Sgblack@eecs.umich.edu Flags 1455680Sgblack@eecs.umich.edu getFlags() const 1465081Sgblack@eecs.umich.edu { 1475933Sgblack@eecs.umich.edu return flags & PublicRead; 1485173Sgblack@eecs.umich.edu } 1495359Sgblack@eecs.umich.edu 1505081Sgblack@eecs.umich.edu bool 1515149Sgblack@eecs.umich.edu isFlagSet(Flags _flags) const 1525298Sgblack@eecs.umich.edu { 1535081Sgblack@eecs.umich.edu assert(_flags.noneSet(~PublicRead)); 1545081Sgblack@eecs.umich.edu return flags.isSet(_flags); 1555081Sgblack@eecs.umich.edu } 1565081Sgblack@eecs.umich.edu 1575081Sgblack@eecs.umich.edu /// Accessor for flags. 1585081Sgblack@eecs.umich.edu void 1595081Sgblack@eecs.umich.edu setFlags(Flags _flags) 1605081Sgblack@eecs.umich.edu { 1615081Sgblack@eecs.umich.edu assert(_flags.noneSet(~PublicWrite)); 1625081Sgblack@eecs.umich.edu flags.set(_flags); 1635081Sgblack@eecs.umich.edu } 1645081Sgblack@eecs.umich.edu 1655081Sgblack@eecs.umich.edu void 1665081Sgblack@eecs.umich.edu clearFlags(Flags _flags) 1675081Sgblack@eecs.umich.edu { 1685081Sgblack@eecs.umich.edu assert(_flags.noneSet(~PublicWrite)); 1695081Sgblack@eecs.umich.edu flags.clear(_flags); 1705081Sgblack@eecs.umich.edu } 1715081Sgblack@eecs.umich.edu 1725081Sgblack@eecs.umich.edu void 1735081Sgblack@eecs.umich.edu clearFlags() 1745081Sgblack@eecs.umich.edu { 1755081Sgblack@eecs.umich.edu flags.clear(PublicWrite); 1765081Sgblack@eecs.umich.edu } 1775081Sgblack@eecs.umich.edu 1785081Sgblack@eecs.umich.edu // This function isn't really useful if TRACING_ON is not defined 1795081Sgblack@eecs.umich.edu virtual void trace(const char *action); //!< trace event activity 1805081Sgblack@eecs.umich.edu 1815081Sgblack@eecs.umich.edu public: 1825081Sgblack@eecs.umich.edu /// Event priorities, to provide tie-breakers for events scheduled 1835081Sgblack@eecs.umich.edu /// at the same cycle. Most events are scheduled at the default 1845081Sgblack@eecs.umich.edu /// priority; these values are used to control events that need to 1855081Sgblack@eecs.umich.edu /// be ordered within a cycle. 1865081Sgblack@eecs.umich.edu 1875081Sgblack@eecs.umich.edu /// Minimum priority 1885081Sgblack@eecs.umich.edu static const Priority Minimum_Pri = SCHAR_MIN; 1895081Sgblack@eecs.umich.edu 1905081Sgblack@eecs.umich.edu /// If we enable tracing on a particular cycle, do that as the 1915081Sgblack@eecs.umich.edu /// very first thing so we don't miss any of the events on 1925081Sgblack@eecs.umich.edu /// that cycle (even if we enter the debugger). 1935081Sgblack@eecs.umich.edu static const Priority Trace_Enable_Pri = -101; 1945081Sgblack@eecs.umich.edu 1955081Sgblack@eecs.umich.edu /// Breakpoints should happen before anything else (except 1965081Sgblack@eecs.umich.edu /// enabling trace output), so we don't miss any action when 1975081Sgblack@eecs.umich.edu /// debugging. 1985081Sgblack@eecs.umich.edu static const Priority Debug_Break_Pri = -100; 1995081Sgblack@eecs.umich.edu 2005081Sgblack@eecs.umich.edu /// CPU switches schedule the new CPU's tick event for the 2015081Sgblack@eecs.umich.edu /// same cycle (after unscheduling the old CPU's tick event). 2025081Sgblack@eecs.umich.edu /// The switch needs to come before any tick events to make 2035081Sgblack@eecs.umich.edu /// sure we don't tick both CPUs in the same cycle. 2045081Sgblack@eecs.umich.edu static const Priority CPU_Switch_Pri = -31; 2055081Sgblack@eecs.umich.edu 2065081Sgblack@eecs.umich.edu /// For some reason "delayed" inter-cluster writebacks are 2075081Sgblack@eecs.umich.edu /// scheduled before regular writebacks (which have default 2085081Sgblack@eecs.umich.edu /// priority). Steve? 2095081Sgblack@eecs.umich.edu static const Priority Delayed_Writeback_Pri = -1; 2105081Sgblack@eecs.umich.edu 2115081Sgblack@eecs.umich.edu /// Default is zero for historical reasons. 2125081Sgblack@eecs.umich.edu static const Priority Default_Pri = 0; 2135081Sgblack@eecs.umich.edu 2145081Sgblack@eecs.umich.edu /// Serailization needs to occur before tick events also, so 2155081Sgblack@eecs.umich.edu /// that a serialize/unserialize is identical to an on-line 2165081Sgblack@eecs.umich.edu /// CPU switch. 2175081Sgblack@eecs.umich.edu static const Priority Serialize_Pri = 32; 2185081Sgblack@eecs.umich.edu 2195081Sgblack@eecs.umich.edu /// CPU ticks must come after other associated CPU events 2205081Sgblack@eecs.umich.edu /// (such as writebacks). 2215081Sgblack@eecs.umich.edu static const Priority CPU_Tick_Pri = 50; 2225081Sgblack@eecs.umich.edu 2235081Sgblack@eecs.umich.edu /// Statistics events (dump, reset, etc.) come after 2245081Sgblack@eecs.umich.edu /// everything else, but before exit. 2255081Sgblack@eecs.umich.edu static const Priority Stat_Event_Pri = 90; 2265081Sgblack@eecs.umich.edu 2275081Sgblack@eecs.umich.edu /// Progress events come at the end. 2285081Sgblack@eecs.umich.edu static const Priority Progress_Event_Pri = 95; 2295081Sgblack@eecs.umich.edu 2305081Sgblack@eecs.umich.edu /// If we want to exit on this cycle, it's the very last thing 2315081Sgblack@eecs.umich.edu /// we do. 2325081Sgblack@eecs.umich.edu static const Priority Sim_Exit_Pri = 100; 2335081Sgblack@eecs.umich.edu 2345081Sgblack@eecs.umich.edu /// Maximum priority 2355081Sgblack@eecs.umich.edu static const Priority Maximum_Pri = SCHAR_MAX; 2365081Sgblack@eecs.umich.edu 2375081Sgblack@eecs.umich.edu /* 2385081Sgblack@eecs.umich.edu * Event constructor 2395081Sgblack@eecs.umich.edu * @param queue that the event gets scheduled on 2405081Sgblack@eecs.umich.edu */ 2415081Sgblack@eecs.umich.edu Event(Priority p = Default_Pri, Flags f = 0) 2425081Sgblack@eecs.umich.edu : nextBin(NULL), nextInBin(NULL), _priority(p), 2435081Sgblack@eecs.umich.edu flags(Initialized | f) 2445081Sgblack@eecs.umich.edu { 2455081Sgblack@eecs.umich.edu assert(f.noneSet(~PublicWrite)); 2465081Sgblack@eecs.umich.edu#ifndef NDEBUG 2475081Sgblack@eecs.umich.edu instance = ++instanceCounter; 2485081Sgblack@eecs.umich.edu queue = NULL; 2495081Sgblack@eecs.umich.edu#endif 2505081Sgblack@eecs.umich.edu#ifdef EVENTQ_DEBUG 2515081Sgblack@eecs.umich.edu whenCreated = curTick(); 2525081Sgblack@eecs.umich.edu whenScheduled = 0; 2535081Sgblack@eecs.umich.edu#endif 2545081Sgblack@eecs.umich.edu } 2555081Sgblack@eecs.umich.edu 2565081Sgblack@eecs.umich.edu virtual ~Event(); 2575081Sgblack@eecs.umich.edu virtual const std::string name() const; 2585081Sgblack@eecs.umich.edu 2595081Sgblack@eecs.umich.edu /// Return a C string describing the event. This string should 2605081Sgblack@eecs.umich.edu /// *not* be dynamically allocated; just a const char array 2615081Sgblack@eecs.umich.edu /// describing the event class. 2625081Sgblack@eecs.umich.edu virtual const char *description() const; 2635081Sgblack@eecs.umich.edu 2645081Sgblack@eecs.umich.edu /// Dump the current event data 2655081Sgblack@eecs.umich.edu void dump() const; 2665081Sgblack@eecs.umich.edu 2675081Sgblack@eecs.umich.edu public: 2685081Sgblack@eecs.umich.edu /* 2695081Sgblack@eecs.umich.edu * This member function is invoked when the event is processed 2705081Sgblack@eecs.umich.edu * (occurs). There is no default implementation; each subclass 2715081Sgblack@eecs.umich.edu * must provide its own implementation. The event is not 2725081Sgblack@eecs.umich.edu * automatically deleted after it is processed (to allow for 2735081Sgblack@eecs.umich.edu * statically allocated event objects). 2745081Sgblack@eecs.umich.edu * 2755081Sgblack@eecs.umich.edu * If the AutoDestroy flag is set, the object is deleted once it 2765081Sgblack@eecs.umich.edu * is processed. 2775081Sgblack@eecs.umich.edu */ 2785081Sgblack@eecs.umich.edu virtual void process() = 0; 2795081Sgblack@eecs.umich.edu 2805081Sgblack@eecs.umich.edu /// Determine if the current event is scheduled 2815081Sgblack@eecs.umich.edu bool scheduled() const { return flags.isSet(Scheduled); } 2825081Sgblack@eecs.umich.edu 2835081Sgblack@eecs.umich.edu /// Squash the current event 2845081Sgblack@eecs.umich.edu void squash() { flags.set(Squashed); } 2855081Sgblack@eecs.umich.edu 2865081Sgblack@eecs.umich.edu /// Check whether the event is squashed 2875081Sgblack@eecs.umich.edu bool squashed() const { return flags.isSet(Squashed); } 2885081Sgblack@eecs.umich.edu 2895081Sgblack@eecs.umich.edu /// See if this is a SimExitEvent (without resorting to RTTI) 2905081Sgblack@eecs.umich.edu bool isExitEvent() const { return flags.isSet(IsExitEvent); } 2915081Sgblack@eecs.umich.edu 2925081Sgblack@eecs.umich.edu /// Get the time that the event is scheduled 2935081Sgblack@eecs.umich.edu Tick when() const { return _when; } 2945081Sgblack@eecs.umich.edu 2955081Sgblack@eecs.umich.edu /// Get the event priority 2965081Sgblack@eecs.umich.edu Priority priority() const { return _priority; } 2975081Sgblack@eecs.umich.edu 2985081Sgblack@eecs.umich.edu#ifndef SWIG 2995081Sgblack@eecs.umich.edu virtual void serialize(std::ostream &os); 3005081Sgblack@eecs.umich.edu virtual void unserialize(Checkpoint *cp, const std::string §ion); 3015081Sgblack@eecs.umich.edu#endif 3025081Sgblack@eecs.umich.edu}; 3035081Sgblack@eecs.umich.edu 3045081Sgblack@eecs.umich.edu#ifndef SWIG 3055081Sgblack@eecs.umich.eduinline bool 3065081Sgblack@eecs.umich.eduoperator<(const Event &l, const Event &r) 3075081Sgblack@eecs.umich.edu{ 3085069Sgblack@eecs.umich.edu return l.when() < r.when() || 3094202Sbinkertn@umich.edu (l.when() == r.when() && l.priority() < r.priority()); 3104202Sbinkertn@umich.edu} 3114202Sbinkertn@umich.edu 3125069Sgblack@eecs.umich.eduinline bool 3135069Sgblack@eecs.umich.eduoperator>(const Event &l, const Event &r) 3145069Sgblack@eecs.umich.edu{ 315 return l.when() > r.when() || 316 (l.when() == r.when() && l.priority() > r.priority()); 317} 318 319inline bool 320operator<=(const Event &l, const Event &r) 321{ 322 return l.when() < r.when() || 323 (l.when() == r.when() && l.priority() <= r.priority()); 324} 325inline bool 326operator>=(const Event &l, const Event &r) 327{ 328 return l.when() > r.when() || 329 (l.when() == r.when() && l.priority() >= r.priority()); 330} 331 332inline bool 333operator==(const Event &l, const Event &r) 334{ 335 return l.when() == r.when() && l.priority() == r.priority(); 336} 337 338inline bool 339operator!=(const Event &l, const Event &r) 340{ 341 return l.when() != r.when() || l.priority() != r.priority(); 342} 343#endif 344 345/* 346 * Queue of events sorted in time order 347 */ 348class EventQueue : public Serializable 349{ 350 private: 351 std::string objName; 352 Event *head; 353 Tick _curTick; 354 355 void insert(Event *event); 356 void remove(Event *event); 357 358 EventQueue(const EventQueue &); 359 const EventQueue &operator=(const EventQueue &); 360 361 public: 362 EventQueue(const std::string &n); 363 364 virtual const std::string name() const { return objName; } 365 366 // schedule the given event on this queue 367 void schedule(Event *event, Tick when); 368 void deschedule(Event *event); 369 void reschedule(Event *event, Tick when, bool always = false); 370 371 Tick nextTick() const { return head->when(); } 372 void setCurTick(Tick newVal) { _curTick = newVal; } 373 Tick getCurTick() { return _curTick; } 374 375 Event *serviceOne(); 376 377 // process all events up to the given timestamp. we inline a 378 // quick test to see if there are any events to process; if so, 379 // call the internal out-of-line version to process them all. 380 void 381 serviceEvents(Tick when) 382 { 383 while (!empty()) { 384 if (nextTick() > when) 385 break; 386 387 /** 388 * @todo this assert is a good bug catcher. I need to 389 * make it true again. 390 */ 391 //assert(head->when() >= when && "event scheduled in the past"); 392 serviceOne(); 393 } 394 395 setCurTick(when); 396 } 397 398 // return true if no events are queued 399 bool empty() const { return head == NULL; } 400 401 void dump() const; 402 403 bool debugVerify() const; 404 405 /** 406 * function for replacing the head of the event queue, so that a 407 * different set of events can run without disturbing events that have 408 * already been scheduled. Already scheduled events can be processed 409 * by replacing the original head back. 410 * USING THIS FUNCTION CAN BE DANGEROUS TO THE HEALTH OF THE SIMULATOR. 411 * NOT RECOMMENDED FOR USE. 412 */ 413 Event* replaceHead(Event* s); 414 415#ifndef SWIG 416 virtual void serialize(std::ostream &os); 417 virtual void unserialize(Checkpoint *cp, const std::string §ion); 418#endif 419}; 420 421void dumpMainQueue(); 422 423#ifndef SWIG 424class EventManager 425{ 426 protected: 427 /** A pointer to this object's event queue */ 428 EventQueue *eventq; 429 430 public: 431 EventManager(EventManager &em) : eventq(em.eventq) {} 432 EventManager(EventManager *em) : eventq(em->eventq) {} 433 EventManager(EventQueue *eq) : eventq(eq) {} 434 435 EventQueue * 436 eventQueue() const 437 { 438 return eventq; 439 } 440 441 void 442 schedule(Event &event, Tick when) 443 { 444 eventq->schedule(&event, when); 445 } 446 447 void 448 deschedule(Event &event) 449 { 450 eventq->deschedule(&event); 451 } 452 453 void 454 reschedule(Event &event, Tick when, bool always = false) 455 { 456 eventq->reschedule(&event, when, always); 457 } 458 459 void 460 schedule(Event *event, Tick when) 461 { 462 eventq->schedule(event, when); 463 } 464 465 void 466 deschedule(Event *event) 467 { 468 eventq->deschedule(event); 469 } 470 471 void 472 reschedule(Event *event, Tick when, bool always = false) 473 { 474 eventq->reschedule(event, when, always); 475 } 476 477 void setCurTick(Tick newVal) { eventq->setCurTick(newVal); } 478}; 479 480template <class T, void (T::* F)()> 481void 482DelayFunction(EventQueue *eventq, Tick when, T *object) 483{ 484 class DelayEvent : public Event 485 { 486 private: 487 T *object; 488 489 public: 490 DelayEvent(T *o) 491 : Event(Default_Pri, AutoDelete), object(o) 492 { } 493 void process() { (object->*F)(); } 494 const char *description() const { return "delay"; } 495 }; 496 497 eventq->schedule(new DelayEvent(object), when); 498} 499 500template <class T, void (T::* F)()> 501class EventWrapper : public Event 502{ 503 private: 504 T *object; 505 506 public: 507 EventWrapper(T *obj, bool del = false, Priority p = Default_Pri) 508 : Event(p), object(obj) 509 { 510 if (del) 511 setFlags(AutoDelete); 512 } 513 514 EventWrapper(T &obj, bool del = false, Priority p = Default_Pri) 515 : Event(p), object(&obj) 516 { 517 if (del) 518 setFlags(AutoDelete); 519 } 520 521 void process() { (object->*F)(); } 522 523 const std::string 524 name() const 525 { 526 return object->name() + ".wrapped_event"; 527 } 528 529 const char *description() const { return "EventWrapped"; } 530}; 531#endif 532 533#endif // __SIM_EVENTQ_HH__ 534