eventq.hh revision 8648
12SN/A/* 21762SN/A * Copyright (c) 2000-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 292665Ssaidi@eecs.umich.edu * Nathan Binkert 302SN/A */ 312SN/A 322SN/A/* @file 332SN/A * EventQueue interfaces 342SN/A */ 352SN/A 361354SN/A#ifndef __SIM_EVENTQ_HH__ 371354SN/A#define __SIM_EVENTQ_HH__ 382SN/A 392SN/A#include <algorithm> 405501Snate@binkert.org#include <cassert> 415546Snate@binkert.org#include <climits> 427004Snate@binkert.org#include <iosfwd> 432SN/A#include <string> 442SN/A 4556SN/A#include "base/fast_alloc.hh" 465769Snate@binkert.org#include "base/flags.hh" 472361SN/A#include "base/misc.hh" 481354SN/A#include "base/trace.hh" 496216Snate@binkert.org#include "base/types.hh" 508232Snate@binkert.org#include "debug/Event.hh" 5156SN/A#include "sim/serialize.hh" 522SN/A 535543Ssaidi@eecs.umich.educlass EventQueue; // forward declaration 542SN/A 551354SN/Aextern EventQueue mainEventQueue; 561354SN/A 572SN/A/* 582SN/A * An item on an event queue. The action caused by a given 592SN/A * event is specified by deriving a subclass and overriding the 602SN/A * process() member function. 615501Snate@binkert.org * 625501Snate@binkert.org * Caution, the order of members is chosen to maximize data packing. 632SN/A */ 64395SN/Aclass Event : public Serializable, public FastAlloc 652SN/A{ 662SN/A friend class EventQueue; 672SN/A 685769Snate@binkert.org protected: 695769Snate@binkert.org typedef short FlagsType; 705769Snate@binkert.org typedef ::Flags<FlagsType> Flags; 715769Snate@binkert.org 727059Snate@binkert.org static const FlagsType PublicRead = 0x003f; // public readable flags 737059Snate@binkert.org static const FlagsType PublicWrite = 0x001d; // public writable flags 747059Snate@binkert.org static const FlagsType Squashed = 0x0001; // has been squashed 757059Snate@binkert.org static const FlagsType Scheduled = 0x0002; // has been scheduled 767059Snate@binkert.org static const FlagsType AutoDelete = 0x0004; // delete after dispatch 777059Snate@binkert.org static const FlagsType AutoSerialize = 0x0008; // must be serialized 787059Snate@binkert.org static const FlagsType IsExitEvent = 0x0010; // special exit event 797059Snate@binkert.org static const FlagsType IsMainQueue = 0x0020; // on main event queue 807059Snate@binkert.org static const FlagsType Initialized = 0x7a40; // somewhat random bits 817059Snate@binkert.org static const FlagsType InitMask = 0xffc0; // mask for init bits 827059Snate@binkert.org 837059Snate@binkert.org bool 847059Snate@binkert.org initialized() const 857059Snate@binkert.org { 867059Snate@binkert.org return this && (flags & InitMask) == Initialized; 877059Snate@binkert.org } 885769Snate@binkert.org 897058Snate@binkert.org public: 907058Snate@binkert.org typedef int8_t Priority; 917058Snate@binkert.org 922SN/A private: 935502Snate@binkert.org // The event queue is now a linked list of linked lists. The 945502Snate@binkert.org // 'nextBin' pointer is to find the bin, where a bin is defined as 955502Snate@binkert.org // when+priority. All events in the same bin will be stored in a 965503Snate@binkert.org // second linked list (a stack) maintained by the 'nextInBin' 975503Snate@binkert.org // pointer. The list will be accessed in LIFO order. The end 985502Snate@binkert.org // result is that the insert/removal in 'nextBin' is 995502Snate@binkert.org // linear/constant, and the lookup/removal in 'nextInBin' is 1005502Snate@binkert.org // constant/constant. Hopefully this is a significant improvement 1015502Snate@binkert.org // over the current fully linear insertion. 1025502Snate@binkert.org Event *nextBin; 1035502Snate@binkert.org Event *nextInBin; 1045502Snate@binkert.org 1055602Snate@binkert.org static Event *insertBefore(Event *event, Event *curr); 1065602Snate@binkert.org static Event *removeItem(Event *event, Event *last); 1075501Snate@binkert.org 1085543Ssaidi@eecs.umich.edu Tick _when; //!< timestamp when event should be processed 1097058Snate@binkert.org Priority _priority; //!< event priority 1105769Snate@binkert.org Flags flags; 1114016Sstever@eecs.umich.edu 1124016Sstever@eecs.umich.edu#ifndef NDEBUG 1134016Sstever@eecs.umich.edu /// Global counter to generate unique IDs for Event instances 1144016Sstever@eecs.umich.edu static Counter instanceCounter; 1154016Sstever@eecs.umich.edu 1164016Sstever@eecs.umich.edu /// This event's unique ID. We can also use pointer values for 1174016Sstever@eecs.umich.edu /// this but they're not consistent across runs making debugging 1184016Sstever@eecs.umich.edu /// more difficult. Thus we use a global counter value when 1194016Sstever@eecs.umich.edu /// debugging. 1205501Snate@binkert.org Counter instance; 1215605Snate@binkert.org 1225605Snate@binkert.org /// queue to which this event belongs (though it may or may not be 1235605Snate@binkert.org /// scheduled on this queue yet) 1245605Snate@binkert.org EventQueue *queue; 1255501Snate@binkert.org#endif 1264016Sstever@eecs.umich.edu 1275577SSteve.Reinhardt@amd.com#ifdef EVENTQ_DEBUG 1285501Snate@binkert.org Tick whenCreated; //!< time created 1295501Snate@binkert.org Tick whenScheduled; //!< time scheduled 1305501Snate@binkert.org#endif 1315502Snate@binkert.org 1325502Snate@binkert.org void 1335605Snate@binkert.org setWhen(Tick when, EventQueue *q) 1345502Snate@binkert.org { 1355502Snate@binkert.org _when = when; 1365605Snate@binkert.org#ifndef NDEBUG 1375605Snate@binkert.org queue = q; 1385605Snate@binkert.org#endif 1395577SSteve.Reinhardt@amd.com#ifdef EVENTQ_DEBUG 1407823Ssteve.reinhardt@amd.com whenScheduled = curTick(); 1415502Snate@binkert.org#endif 1425502Snate@binkert.org } 1435502Snate@binkert.org 1442SN/A protected: 1455769Snate@binkert.org /// Accessor for flags. 1465769Snate@binkert.org Flags 1475769Snate@binkert.org getFlags() const 1485769Snate@binkert.org { 1495769Snate@binkert.org return flags & PublicRead; 1505769Snate@binkert.org } 1512SN/A 1528581Ssteve.reinhardt@amd.com bool 1538581Ssteve.reinhardt@amd.com isFlagSet(Flags _flags) const 1545769Snate@binkert.org { 1557059Snate@binkert.org assert(_flags.noneSet(~PublicRead)); 1565769Snate@binkert.org return flags.isSet(_flags); 1575769Snate@binkert.org } 1582SN/A 1595769Snate@binkert.org /// Accessor for flags. 1605769Snate@binkert.org void 1615769Snate@binkert.org setFlags(Flags _flags) 1625769Snate@binkert.org { 1635769Snate@binkert.org assert(_flags.noneSet(~PublicWrite)); 1645769Snate@binkert.org flags.set(_flags); 1655769Snate@binkert.org } 1665769Snate@binkert.org 1675769Snate@binkert.org void 1685769Snate@binkert.org clearFlags(Flags _flags) 1695769Snate@binkert.org { 1705769Snate@binkert.org assert(_flags.noneSet(~PublicWrite)); 1715769Snate@binkert.org flags.clear(_flags); 1725769Snate@binkert.org } 1735769Snate@binkert.org 1745769Snate@binkert.org void 1755769Snate@binkert.org clearFlags() 1765769Snate@binkert.org { 1775769Snate@binkert.org flags.clear(PublicWrite); 1785769Snate@binkert.org } 1795769Snate@binkert.org 1805501Snate@binkert.org // This function isn't really useful if TRACING_ON is not defined 1815543Ssaidi@eecs.umich.edu virtual void trace(const char *action); //!< trace event activity 1822SN/A 1832SN/A public: 184396SN/A /// Event priorities, to provide tie-breakers for events scheduled 185396SN/A /// at the same cycle. Most events are scheduled at the default 186396SN/A /// priority; these values are used to control events that need to 187396SN/A /// be ordered within a cycle. 1885501Snate@binkert.org 1897058Snate@binkert.org /// Minimum priority 1907058Snate@binkert.org static const Priority Minimum_Pri = SCHAR_MIN; 1913329Sstever@eecs.umich.edu 1927058Snate@binkert.org /// If we enable tracing on a particular cycle, do that as the 1937058Snate@binkert.org /// very first thing so we don't miss any of the events on 1947058Snate@binkert.org /// that cycle (even if we enter the debugger). 1957058Snate@binkert.org static const Priority Trace_Enable_Pri = -101; 196396SN/A 1977058Snate@binkert.org /// Breakpoints should happen before anything else (except 1987058Snate@binkert.org /// enabling trace output), so we don't miss any action when 1997058Snate@binkert.org /// debugging. 2007058Snate@binkert.org static const Priority Debug_Break_Pri = -100; 2013329Sstever@eecs.umich.edu 2027058Snate@binkert.org /// CPU switches schedule the new CPU's tick event for the 2037058Snate@binkert.org /// same cycle (after unscheduling the old CPU's tick event). 2047058Snate@binkert.org /// The switch needs to come before any tick events to make 2057058Snate@binkert.org /// sure we don't tick both CPUs in the same cycle. 2067058Snate@binkert.org static const Priority CPU_Switch_Pri = -31; 207396SN/A 2087058Snate@binkert.org /// For some reason "delayed" inter-cluster writebacks are 2097058Snate@binkert.org /// scheduled before regular writebacks (which have default 2107058Snate@binkert.org /// priority). Steve? 2117058Snate@binkert.org static const Priority Delayed_Writeback_Pri = -1; 212396SN/A 2137058Snate@binkert.org /// Default is zero for historical reasons. 2147058Snate@binkert.org static const Priority Default_Pri = 0; 215396SN/A 2167058Snate@binkert.org /// Serailization needs to occur before tick events also, so 2177058Snate@binkert.org /// that a serialize/unserialize is identical to an on-line 2187058Snate@binkert.org /// CPU switch. 2197058Snate@binkert.org static const Priority Serialize_Pri = 32; 220396SN/A 2217058Snate@binkert.org /// CPU ticks must come after other associated CPU events 2227058Snate@binkert.org /// (such as writebacks). 2237058Snate@binkert.org static const Priority CPU_Tick_Pri = 50; 224396SN/A 2257058Snate@binkert.org /// Statistics events (dump, reset, etc.) come after 2267058Snate@binkert.org /// everything else, but before exit. 2277058Snate@binkert.org static const Priority Stat_Event_Pri = 90; 2284075Sbinkertn@umich.edu 2297058Snate@binkert.org /// Progress events come at the end. 2307058Snate@binkert.org static const Priority Progress_Event_Pri = 95; 2315501Snate@binkert.org 2327058Snate@binkert.org /// If we want to exit on this cycle, it's the very last thing 2337058Snate@binkert.org /// we do. 2347058Snate@binkert.org static const Priority Sim_Exit_Pri = 100; 2357058Snate@binkert.org 2367058Snate@binkert.org /// Maximum priority 2377058Snate@binkert.org static const Priority Maximum_Pri = SCHAR_MAX; 238396SN/A 2392SN/A /* 2402SN/A * Event constructor 2412SN/A * @param queue that the event gets scheduled on 2422SN/A */ 2438581Ssteve.reinhardt@amd.com Event(Priority p = Default_Pri, Flags f = 0) 2448581Ssteve.reinhardt@amd.com : nextBin(NULL), nextInBin(NULL), _priority(p), 2458581Ssteve.reinhardt@amd.com flags(Initialized | f) 246224SN/A { 2478581Ssteve.reinhardt@amd.com assert(f.noneSet(~PublicWrite)); 2484016Sstever@eecs.umich.edu#ifndef NDEBUG 2495501Snate@binkert.org instance = ++instanceCounter; 2505605Snate@binkert.org queue = NULL; 2515501Snate@binkert.org#endif 2525501Snate@binkert.org#ifdef EVENTQ_DEBUG 2537823Ssteve.reinhardt@amd.com whenCreated = curTick(); 2545501Snate@binkert.org whenScheduled = 0; 2554016Sstever@eecs.umich.edu#endif 256224SN/A } 257224SN/A 2585768Snate@binkert.org virtual ~Event(); 2595768Snate@binkert.org virtual const std::string name() const; 260265SN/A 2615501Snate@binkert.org /// Return a C string describing the event. This string should 2625501Snate@binkert.org /// *not* be dynamically allocated; just a const char array 2635501Snate@binkert.org /// describing the event class. 2645501Snate@binkert.org virtual const char *description() const; 2655501Snate@binkert.org 2665501Snate@binkert.org /// Dump the current event data 2675501Snate@binkert.org void dump() const; 2685501Snate@binkert.org 2695501Snate@binkert.org public: 2705501Snate@binkert.org /* 2715501Snate@binkert.org * This member function is invoked when the event is processed 2725501Snate@binkert.org * (occurs). There is no default implementation; each subclass 2735501Snate@binkert.org * must provide its own implementation. The event is not 2745501Snate@binkert.org * automatically deleted after it is processed (to allow for 2755501Snate@binkert.org * statically allocated event objects). 2765501Snate@binkert.org * 2775501Snate@binkert.org * If the AutoDestroy flag is set, the object is deleted once it 2785501Snate@binkert.org * is processed. 2795501Snate@binkert.org */ 2805501Snate@binkert.org virtual void process() = 0; 2815501Snate@binkert.org 2822SN/A /// Determine if the current event is scheduled 2835769Snate@binkert.org bool scheduled() const { return flags.isSet(Scheduled); } 2842SN/A 2852SN/A /// Squash the current event 2865769Snate@binkert.org void squash() { flags.set(Squashed); } 2872SN/A 2882SN/A /// Check whether the event is squashed 2895769Snate@binkert.org bool squashed() const { return flags.isSet(Squashed); } 2902SN/A 2912667Sstever@eecs.umich.edu /// See if this is a SimExitEvent (without resorting to RTTI) 2925769Snate@binkert.org bool isExitEvent() const { return flags.isSet(IsExitEvent); } 2932667Sstever@eecs.umich.edu 2942SN/A /// Get the time that the event is scheduled 2952SN/A Tick when() const { return _when; } 2962SN/A 2972SN/A /// Get the event priority 2987058Snate@binkert.org Priority priority() const { return _priority; } 2992SN/A 3005605Snate@binkert.org#ifndef SWIG 3015501Snate@binkert.org struct priority_compare 3025501Snate@binkert.org : public std::binary_function<Event *, Event *, bool> 3032SN/A { 3045501Snate@binkert.org bool 3055501Snate@binkert.org operator()(const Event *l, const Event *r) const 3065501Snate@binkert.org { 3072SN/A return l->when() >= r->when() || l->priority() >= r->priority(); 3082SN/A } 3092SN/A }; 310224SN/A 311224SN/A virtual void serialize(std::ostream &os); 312237SN/A virtual void unserialize(Checkpoint *cp, const std::string §ion); 3135605Snate@binkert.org#endif 314571SN/A}; 315571SN/A 3167005Snate@binkert.org#ifndef SWIG 3177005Snate@binkert.orginline bool 3187005Snate@binkert.orgoperator<(const Event &l, const Event &r) 3197005Snate@binkert.org{ 3207005Snate@binkert.org return l.when() < r.when() || 3217005Snate@binkert.org (l.when() == r.when() && l.priority() < r.priority()); 3227005Snate@binkert.org} 3237005Snate@binkert.org 3247005Snate@binkert.orginline bool 3257005Snate@binkert.orgoperator>(const Event &l, const Event &r) 3267005Snate@binkert.org{ 3277005Snate@binkert.org return l.when() > r.when() || 3287005Snate@binkert.org (l.when() == r.when() && l.priority() > r.priority()); 3297005Snate@binkert.org} 3307005Snate@binkert.org 3317005Snate@binkert.orginline bool 3327005Snate@binkert.orgoperator<=(const Event &l, const Event &r) 3337005Snate@binkert.org{ 3347005Snate@binkert.org return l.when() < r.when() || 3357005Snate@binkert.org (l.when() == r.when() && l.priority() <= r.priority()); 3367005Snate@binkert.org} 3377005Snate@binkert.orginline bool 3387005Snate@binkert.orgoperator>=(const Event &l, const Event &r) 3397005Snate@binkert.org{ 3407005Snate@binkert.org return l.when() > r.when() || 3417005Snate@binkert.org (l.when() == r.when() && l.priority() >= r.priority()); 3427005Snate@binkert.org} 3437005Snate@binkert.org 3447005Snate@binkert.orginline bool 3457005Snate@binkert.orgoperator==(const Event &l, const Event &r) 3467005Snate@binkert.org{ 3477005Snate@binkert.org return l.when() == r.when() && l.priority() == r.priority(); 3487005Snate@binkert.org} 3497005Snate@binkert.org 3507005Snate@binkert.orginline bool 3517005Snate@binkert.orgoperator!=(const Event &l, const Event &r) 3527005Snate@binkert.org{ 3537005Snate@binkert.org return l.when() != r.when() || l.priority() != r.priority(); 3547005Snate@binkert.org} 3557005Snate@binkert.org#endif 3567005Snate@binkert.org 3572SN/A/* 3582SN/A * Queue of events sorted in time order 3592SN/A */ 360395SN/Aclass EventQueue : public Serializable 3612SN/A{ 3625605Snate@binkert.org private: 363265SN/A std::string objName; 3642SN/A Event *head; 3652SN/A 3662SN/A void insert(Event *event); 3672SN/A void remove(Event *event); 3682SN/A 3697063Snate@binkert.org EventQueue(const EventQueue &); 3707063Snate@binkert.org const EventQueue &operator=(const EventQueue &); 3717063Snate@binkert.org 3722SN/A public: 3737063Snate@binkert.org EventQueue(const std::string &n); 3742SN/A 375512SN/A virtual const std::string name() const { return objName; } 376265SN/A 3772SN/A // schedule the given event on this queue 3785738Snate@binkert.org void schedule(Event *event, Tick when); 3795738Snate@binkert.org void deschedule(Event *event); 3805738Snate@binkert.org void reschedule(Event *event, Tick when, bool always = false); 3812SN/A 3825501Snate@binkert.org Tick nextTick() const { return head->when(); } 3832667Sstever@eecs.umich.edu Event *serviceOne(); 3842SN/A 3852SN/A // process all events up to the given timestamp. we inline a 3862SN/A // quick test to see if there are any events to process; if so, 3872SN/A // call the internal out-of-line version to process them all. 3885501Snate@binkert.org void 3895501Snate@binkert.org serviceEvents(Tick when) 3905501Snate@binkert.org { 3912SN/A while (!empty()) { 3922SN/A if (nextTick() > when) 3932SN/A break; 3942SN/A 3951634SN/A /** 3961634SN/A * @todo this assert is a good bug catcher. I need to 3971634SN/A * make it true again. 3981634SN/A */ 3991634SN/A //assert(head->when() >= when && "event scheduled in the past"); 4002SN/A serviceOne(); 4012SN/A } 4022SN/A } 4032SN/A 4042SN/A // return true if no events are queued 4055501Snate@binkert.org bool empty() const { return head == NULL; } 4062SN/A 4075501Snate@binkert.org void dump() const; 4082SN/A 4095502Snate@binkert.org bool debugVerify() const; 4105502Snate@binkert.org 4118648Snilay@cs.wisc.edu /** 4128648Snilay@cs.wisc.edu * function for replacing the head of the event queue, so that a 4138648Snilay@cs.wisc.edu * different set of events can run without disturbing events that have 4148648Snilay@cs.wisc.edu * already been scheduled. Already scheduled events can be processed 4158648Snilay@cs.wisc.edu * by replacing the original head back. 4168648Snilay@cs.wisc.edu * USING THIS FUNCTION CAN BE DANGEROUS TO THE HEALTH OF THE SIMULATOR. 4178648Snilay@cs.wisc.edu * NOT RECOMMENDED FOR USE. 4188648Snilay@cs.wisc.edu */ 4198648Snilay@cs.wisc.edu Event* replaceHead(Event* s); 4208648Snilay@cs.wisc.edu 4215605Snate@binkert.org#ifndef SWIG 422217SN/A virtual void serialize(std::ostream &os); 423237SN/A virtual void unserialize(Checkpoint *cp, const std::string §ion); 4245605Snate@binkert.org#endif 4252SN/A}; 4262SN/A 4275605Snate@binkert.org#ifndef SWIG 4285605Snate@binkert.orgclass EventManager 4295605Snate@binkert.org{ 4305605Snate@binkert.org protected: 4315605Snate@binkert.org /** A pointer to this object's event queue */ 4325605Snate@binkert.org EventQueue *eventq; 4332SN/A 4345605Snate@binkert.org public: 4355605Snate@binkert.org EventManager(EventManager &em) : eventq(em.queue()) {} 4365605Snate@binkert.org EventManager(EventManager *em) : eventq(em ? em->queue() : NULL) {} 4375605Snate@binkert.org EventManager(EventQueue *eq) : eventq(eq) {} 4382SN/A 4395605Snate@binkert.org EventQueue * 4405605Snate@binkert.org queue() const 4415605Snate@binkert.org { 4425605Snate@binkert.org return eventq; 4435605Snate@binkert.org } 4445605Snate@binkert.org 4457060Snate@binkert.org operator EventQueue *() const 4467060Snate@binkert.org { 4477060Snate@binkert.org return eventq; 4487060Snate@binkert.org } 4497060Snate@binkert.org 4505605Snate@binkert.org void 4515605Snate@binkert.org schedule(Event &event, Tick when) 4525605Snate@binkert.org { 4535605Snate@binkert.org eventq->schedule(&event, when); 4545605Snate@binkert.org } 4555605Snate@binkert.org 4565605Snate@binkert.org void 4575605Snate@binkert.org deschedule(Event &event) 4585605Snate@binkert.org { 4595605Snate@binkert.org eventq->deschedule(&event); 4605605Snate@binkert.org } 4615605Snate@binkert.org 4625605Snate@binkert.org void 4635605Snate@binkert.org reschedule(Event &event, Tick when, bool always = false) 4645605Snate@binkert.org { 4655605Snate@binkert.org eventq->reschedule(&event, when, always); 4665605Snate@binkert.org } 4675605Snate@binkert.org 4685605Snate@binkert.org void 4695605Snate@binkert.org schedule(Event *event, Tick when) 4705605Snate@binkert.org { 4715605Snate@binkert.org eventq->schedule(event, when); 4725605Snate@binkert.org } 4735605Snate@binkert.org 4745605Snate@binkert.org void 4755605Snate@binkert.org deschedule(Event *event) 4765605Snate@binkert.org { 4775605Snate@binkert.org eventq->deschedule(event); 4785605Snate@binkert.org } 4795605Snate@binkert.org 4805605Snate@binkert.org void 4815605Snate@binkert.org reschedule(Event *event, Tick when, bool always = false) 4825605Snate@binkert.org { 4835605Snate@binkert.org eventq->reschedule(event, when, always); 4845605Snate@binkert.org } 4855605Snate@binkert.org}; 4865605Snate@binkert.org 4872SN/Ainline void 4885605Snate@binkert.orgEventQueue::schedule(Event *event, Tick when) 4892SN/A{ 4908186Sksewell@umich.edu // Typecasting Tick->Utick here since gcc 4918186Sksewell@umich.edu // complains about signed overflow 4927823Ssteve.reinhardt@amd.com assert((UTick)when >= (UTick)curTick()); 4935605Snate@binkert.org assert(!event->scheduled()); 4947059Snate@binkert.org assert(event->initialized()); 4955605Snate@binkert.org 4965605Snate@binkert.org event->setWhen(when, this); 4975605Snate@binkert.org insert(event); 4985769Snate@binkert.org event->flags.set(Event::Scheduled); 4995605Snate@binkert.org if (this == &mainEventQueue) 5005769Snate@binkert.org event->flags.set(Event::IsMainQueue); 5015605Snate@binkert.org else 5025769Snate@binkert.org event->flags.clear(Event::IsMainQueue); 5035605Snate@binkert.org 5045605Snate@binkert.org if (DTRACE(Event)) 5055605Snate@binkert.org event->trace("scheduled"); 5062SN/A} 5072SN/A 5082SN/Ainline void 5095605Snate@binkert.orgEventQueue::deschedule(Event *event) 5102SN/A{ 5115605Snate@binkert.org assert(event->scheduled()); 5127059Snate@binkert.org assert(event->initialized()); 5135605Snate@binkert.org 5145605Snate@binkert.org remove(event); 5155605Snate@binkert.org 5165769Snate@binkert.org event->flags.clear(Event::Squashed); 5175769Snate@binkert.org event->flags.clear(Event::Scheduled); 5185605Snate@binkert.org 5195769Snate@binkert.org if (event->flags.isSet(Event::AutoDelete)) 5205605Snate@binkert.org delete event; 5215605Snate@binkert.org 5225605Snate@binkert.org if (DTRACE(Event)) 5235605Snate@binkert.org event->trace("descheduled"); 5242SN/A} 5252SN/A 5262SN/Ainline void 5275605Snate@binkert.orgEventQueue::reschedule(Event *event, Tick when, bool always) 5282SN/A{ 5298186Sksewell@umich.edu // Typecasting Tick->Utick here since gcc 5308186Sksewell@umich.edu // complains about signed overflow 5318186Sksewell@umich.edu assert((UTick)when >= (UTick)curTick()); 5325605Snate@binkert.org assert(always || event->scheduled()); 5337059Snate@binkert.org assert(event->initialized()); 5345605Snate@binkert.org 5355605Snate@binkert.org if (event->scheduled()) 5365605Snate@binkert.org remove(event); 5375605Snate@binkert.org 5385605Snate@binkert.org event->setWhen(when, this); 5395605Snate@binkert.org insert(event); 5405769Snate@binkert.org event->flags.clear(Event::Squashed); 5415769Snate@binkert.org event->flags.set(Event::Scheduled); 5425605Snate@binkert.org if (this == &mainEventQueue) 5435769Snate@binkert.org event->flags.set(Event::IsMainQueue); 5445605Snate@binkert.org else 5455769Snate@binkert.org event->flags.clear(Event::IsMainQueue); 5465605Snate@binkert.org 5475605Snate@binkert.org if (DTRACE(Event)) 5485605Snate@binkert.org event->trace("rescheduled"); 5492SN/A} 5502SN/A 5517005Snate@binkert.orgtemplate <class T, void (T::* F)()> 5527005Snate@binkert.orgvoid 5537005Snate@binkert.orgDelayFunction(EventQueue *eventq, Tick when, T *object) 5545502Snate@binkert.org{ 5557005Snate@binkert.org class DelayEvent : public Event 5567005Snate@binkert.org { 5577005Snate@binkert.org private: 5587005Snate@binkert.org T *object; 5597005Snate@binkert.org 5607005Snate@binkert.org public: 5617005Snate@binkert.org DelayEvent(T *o) 5628581Ssteve.reinhardt@amd.com : Event(Default_Pri, AutoDelete), object(o) 5638581Ssteve.reinhardt@amd.com { } 5647005Snate@binkert.org void process() { (object->*F)(); } 5657005Snate@binkert.org const char *description() const { return "delay"; } 5667005Snate@binkert.org }; 5677005Snate@binkert.org 5687005Snate@binkert.org eventq->schedule(new DelayEvent(object), when); 5695502Snate@binkert.org} 5705502Snate@binkert.org 5717005Snate@binkert.orgtemplate <class T, void (T::* F)()> 5727005Snate@binkert.orgclass EventWrapper : public Event 5735502Snate@binkert.org{ 5747005Snate@binkert.org private: 5757005Snate@binkert.org T *object; 5765502Snate@binkert.org 5777005Snate@binkert.org public: 5787005Snate@binkert.org EventWrapper(T *obj, bool del = false, Priority p = Default_Pri) 5797005Snate@binkert.org : Event(p), object(obj) 5807005Snate@binkert.org { 5817005Snate@binkert.org if (del) 5827005Snate@binkert.org setFlags(AutoDelete); 5837005Snate@binkert.org } 5845502Snate@binkert.org 5857066Snate@binkert.org EventWrapper(T &obj, bool del = false, Priority p = Default_Pri) 5867066Snate@binkert.org : Event(p), object(&obj) 5877066Snate@binkert.org { 5887066Snate@binkert.org if (del) 5897066Snate@binkert.org setFlags(AutoDelete); 5907066Snate@binkert.org } 5917066Snate@binkert.org 5927005Snate@binkert.org void process() { (object->*F)(); } 5935502Snate@binkert.org 5947005Snate@binkert.org const std::string 5957005Snate@binkert.org name() const 5967005Snate@binkert.org { 5977005Snate@binkert.org return object->name() + ".wrapped_event"; 5987005Snate@binkert.org } 5997005Snate@binkert.org 6007005Snate@binkert.org const char *description() const { return "EventWrapped"; } 6017005Snate@binkert.org}; 6025605Snate@binkert.org#endif 6032SN/A 6041354SN/A#endif // __SIM_EVENTQ_HH__ 605