eventq.hh revision 9983
12SN/A/* 21762SN/A * Copyright (c) 2000-2005 The Regents of The University of Michigan 39983Sstever@gmail.com * Copyright (c) 2013 Advanced Micro Devices, Inc. 49983Sstever@gmail.com * Copyright (c) 2013 Mark D. Hill and David A. Wood 52SN/A * All rights reserved. 62SN/A * 72SN/A * Redistribution and use in source and binary forms, with or without 82SN/A * modification, are permitted provided that the following conditions are 92SN/A * met: redistributions of source code must retain the above copyright 102SN/A * notice, this list of conditions and the following disclaimer; 112SN/A * redistributions in binary form must reproduce the above copyright 122SN/A * notice, this list of conditions and the following disclaimer in the 132SN/A * documentation and/or other materials provided with the distribution; 142SN/A * neither the name of the copyright holders nor the names of its 152SN/A * contributors may be used to endorse or promote products derived from 162SN/A * this software without specific prior written permission. 172SN/A * 182SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 192SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 202SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 212SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 222SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 232SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 242SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 252SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 262SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 272SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 282SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 292665Ssaidi@eecs.umich.edu * 302665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 312665Ssaidi@eecs.umich.edu * Nathan Binkert 322SN/A */ 332SN/A 342SN/A/* @file 352SN/A * EventQueue interfaces 362SN/A */ 372SN/A 381354SN/A#ifndef __SIM_EVENTQ_HH__ 391354SN/A#define __SIM_EVENTQ_HH__ 402SN/A 412SN/A#include <algorithm> 425501Snate@binkert.org#include <cassert> 435546Snate@binkert.org#include <climits> 447004Snate@binkert.org#include <iosfwd> 459983Sstever@gmail.com#include <mutex> 462SN/A#include <string> 472SN/A 485769Snate@binkert.org#include "base/flags.hh" 492361SN/A#include "base/misc.hh" 506216Snate@binkert.org#include "base/types.hh" 518232Snate@binkert.org#include "debug/Event.hh" 5256SN/A#include "sim/serialize.hh" 532SN/A 545543Ssaidi@eecs.umich.educlass EventQueue; // forward declaration 559983Sstever@gmail.comclass BaseGlobalEvent; 562SN/A 579983Sstever@gmail.com//! Simulation Quantum for multiple eventq simulation. 589983Sstever@gmail.com//! The quantum value is the period length after which the queues 599983Sstever@gmail.com//! synchronize themselves with each other. This means that any 609983Sstever@gmail.com//! event to scheduled on Queue A which is generated by an event on 619983Sstever@gmail.com//! Queue B should be at least simQuantum ticks away in future. 629983Sstever@gmail.comextern Tick simQuantum; 631354SN/A 649983Sstever@gmail.com//! Current number of allocated main event queues. 659983Sstever@gmail.comextern uint32_t numMainEventQueues; 669983Sstever@gmail.com 679983Sstever@gmail.com//! Array for main event queues. 689983Sstever@gmail.comextern std::vector<EventQueue *> mainEventQueue; 699983Sstever@gmail.com 709983Sstever@gmail.com#ifndef SWIG 719983Sstever@gmail.com//! The current event queue for the running thread. Access to this queue 729983Sstever@gmail.com//! does not require any locking from the thread. 739983Sstever@gmail.com 749983Sstever@gmail.comextern __thread EventQueue *_curEventQueue; 759983Sstever@gmail.com 769983Sstever@gmail.com#endif 779983Sstever@gmail.com 789983Sstever@gmail.com//! Current mode of execution: parallel / serial 799983Sstever@gmail.comextern bool inParallelMode; 809983Sstever@gmail.com 819983Sstever@gmail.com//! Function for returning eventq queue for the provided 829983Sstever@gmail.com//! index. The function allocates a new queue in case one 839983Sstever@gmail.com//! does not exist for the index, provided that the index 849983Sstever@gmail.com//! is with in bounds. 859983Sstever@gmail.comEventQueue *getEventQueue(uint32_t index); 869983Sstever@gmail.com 879983Sstever@gmail.cominline EventQueue *curEventQueue() { return _curEventQueue; } 889983Sstever@gmail.cominline void curEventQueue(EventQueue *q) { _curEventQueue = q; } 899983Sstever@gmail.com 909983Sstever@gmail.com/** 919983Sstever@gmail.com * Common base class for Event and GlobalEvent, so they can share flag 929983Sstever@gmail.com * and priority definitions and accessor functions. This class should 939983Sstever@gmail.com * not be used directly. 942SN/A */ 959983Sstever@gmail.comclass EventBase 962SN/A{ 975769Snate@binkert.org protected: 988902Sandreas.hansson@arm.com typedef unsigned short FlagsType; 995769Snate@binkert.org typedef ::Flags<FlagsType> Flags; 1005769Snate@binkert.org 1017059Snate@binkert.org static const FlagsType PublicRead = 0x003f; // public readable flags 1027059Snate@binkert.org static const FlagsType PublicWrite = 0x001d; // public writable flags 1037059Snate@binkert.org static const FlagsType Squashed = 0x0001; // has been squashed 1047059Snate@binkert.org static const FlagsType Scheduled = 0x0002; // has been scheduled 1057059Snate@binkert.org static const FlagsType AutoDelete = 0x0004; // delete after dispatch 1067059Snate@binkert.org static const FlagsType AutoSerialize = 0x0008; // must be serialized 1077059Snate@binkert.org static const FlagsType IsExitEvent = 0x0010; // special exit event 1087059Snate@binkert.org static const FlagsType IsMainQueue = 0x0020; // on main event queue 1097059Snate@binkert.org static const FlagsType Initialized = 0x7a40; // somewhat random bits 1107059Snate@binkert.org static const FlagsType InitMask = 0xffc0; // mask for init bits 1117059Snate@binkert.org 1127058Snate@binkert.org public: 1137058Snate@binkert.org typedef int8_t Priority; 1147058Snate@binkert.org 115396SN/A /// Event priorities, to provide tie-breakers for events scheduled 116396SN/A /// at the same cycle. Most events are scheduled at the default 117396SN/A /// priority; these values are used to control events that need to 118396SN/A /// be ordered within a cycle. 1195501Snate@binkert.org 1207058Snate@binkert.org /// Minimum priority 1217058Snate@binkert.org static const Priority Minimum_Pri = SCHAR_MIN; 1223329Sstever@eecs.umich.edu 1237058Snate@binkert.org /// If we enable tracing on a particular cycle, do that as the 1247058Snate@binkert.org /// very first thing so we don't miss any of the events on 1257058Snate@binkert.org /// that cycle (even if we enter the debugger). 1269979Satgutier@umich.edu static const Priority Debug_Enable_Pri = -101; 127396SN/A 1287058Snate@binkert.org /// Breakpoints should happen before anything else (except 1297058Snate@binkert.org /// enabling trace output), so we don't miss any action when 1307058Snate@binkert.org /// debugging. 1317058Snate@binkert.org static const Priority Debug_Break_Pri = -100; 1323329Sstever@eecs.umich.edu 1337058Snate@binkert.org /// CPU switches schedule the new CPU's tick event for the 1347058Snate@binkert.org /// same cycle (after unscheduling the old CPU's tick event). 1357058Snate@binkert.org /// The switch needs to come before any tick events to make 1367058Snate@binkert.org /// sure we don't tick both CPUs in the same cycle. 1377058Snate@binkert.org static const Priority CPU_Switch_Pri = -31; 138396SN/A 1397058Snate@binkert.org /// For some reason "delayed" inter-cluster writebacks are 1407058Snate@binkert.org /// scheduled before regular writebacks (which have default 1417058Snate@binkert.org /// priority). Steve? 1427058Snate@binkert.org static const Priority Delayed_Writeback_Pri = -1; 143396SN/A 1447058Snate@binkert.org /// Default is zero for historical reasons. 1457058Snate@binkert.org static const Priority Default_Pri = 0; 146396SN/A 1477058Snate@binkert.org /// Serailization needs to occur before tick events also, so 1487058Snate@binkert.org /// that a serialize/unserialize is identical to an on-line 1497058Snate@binkert.org /// CPU switch. 1507058Snate@binkert.org static const Priority Serialize_Pri = 32; 151396SN/A 1527058Snate@binkert.org /// CPU ticks must come after other associated CPU events 1537058Snate@binkert.org /// (such as writebacks). 1547058Snate@binkert.org static const Priority CPU_Tick_Pri = 50; 155396SN/A 1567058Snate@binkert.org /// Statistics events (dump, reset, etc.) come after 1577058Snate@binkert.org /// everything else, but before exit. 1587058Snate@binkert.org static const Priority Stat_Event_Pri = 90; 1594075Sbinkertn@umich.edu 1607058Snate@binkert.org /// Progress events come at the end. 1617058Snate@binkert.org static const Priority Progress_Event_Pri = 95; 1625501Snate@binkert.org 1637058Snate@binkert.org /// If we want to exit on this cycle, it's the very last thing 1647058Snate@binkert.org /// we do. 1657058Snate@binkert.org static const Priority Sim_Exit_Pri = 100; 1667058Snate@binkert.org 1677058Snate@binkert.org /// Maximum priority 1687058Snate@binkert.org static const Priority Maximum_Pri = SCHAR_MAX; 1699983Sstever@gmail.com}; 1709983Sstever@gmail.com 1719983Sstever@gmail.com/* 1729983Sstever@gmail.com * An item on an event queue. The action caused by a given 1739983Sstever@gmail.com * event is specified by deriving a subclass and overriding the 1749983Sstever@gmail.com * process() member function. 1759983Sstever@gmail.com * 1769983Sstever@gmail.com * Caution, the order of members is chosen to maximize data packing. 1779983Sstever@gmail.com */ 1789983Sstever@gmail.comclass Event : public EventBase, public Serializable 1799983Sstever@gmail.com{ 1809983Sstever@gmail.com friend class EventQueue; 1819983Sstever@gmail.com 1829983Sstever@gmail.com private: 1839983Sstever@gmail.com // The event queue is now a linked list of linked lists. The 1849983Sstever@gmail.com // 'nextBin' pointer is to find the bin, where a bin is defined as 1859983Sstever@gmail.com // when+priority. All events in the same bin will be stored in a 1869983Sstever@gmail.com // second linked list (a stack) maintained by the 'nextInBin' 1879983Sstever@gmail.com // pointer. The list will be accessed in LIFO order. The end 1889983Sstever@gmail.com // result is that the insert/removal in 'nextBin' is 1899983Sstever@gmail.com // linear/constant, and the lookup/removal in 'nextInBin' is 1909983Sstever@gmail.com // constant/constant. Hopefully this is a significant improvement 1919983Sstever@gmail.com // over the current fully linear insertion. 1929983Sstever@gmail.com Event *nextBin; 1939983Sstever@gmail.com Event *nextInBin; 1949983Sstever@gmail.com 1959983Sstever@gmail.com static Event *insertBefore(Event *event, Event *curr); 1969983Sstever@gmail.com static Event *removeItem(Event *event, Event *last); 1979983Sstever@gmail.com 1989983Sstever@gmail.com Tick _when; //!< timestamp when event should be processed 1999983Sstever@gmail.com Priority _priority; //!< event priority 2009983Sstever@gmail.com Flags flags; 2019983Sstever@gmail.com 2029983Sstever@gmail.com#ifndef NDEBUG 2039983Sstever@gmail.com /// Global counter to generate unique IDs for Event instances 2049983Sstever@gmail.com static Counter instanceCounter; 2059983Sstever@gmail.com 2069983Sstever@gmail.com /// This event's unique ID. We can also use pointer values for 2079983Sstever@gmail.com /// this but they're not consistent across runs making debugging 2089983Sstever@gmail.com /// more difficult. Thus we use a global counter value when 2099983Sstever@gmail.com /// debugging. 2109983Sstever@gmail.com Counter instance; 2119983Sstever@gmail.com 2129983Sstever@gmail.com /// queue to which this event belongs (though it may or may not be 2139983Sstever@gmail.com /// scheduled on this queue yet) 2149983Sstever@gmail.com EventQueue *queue; 2159983Sstever@gmail.com#endif 2169983Sstever@gmail.com 2179983Sstever@gmail.com#ifdef EVENTQ_DEBUG 2189983Sstever@gmail.com Tick whenCreated; //!< time created 2199983Sstever@gmail.com Tick whenScheduled; //!< time scheduled 2209983Sstever@gmail.com#endif 2219983Sstever@gmail.com 2229983Sstever@gmail.com void 2239983Sstever@gmail.com setWhen(Tick when, EventQueue *q) 2249983Sstever@gmail.com { 2259983Sstever@gmail.com _when = when; 2269983Sstever@gmail.com#ifndef NDEBUG 2279983Sstever@gmail.com queue = q; 2289983Sstever@gmail.com#endif 2299983Sstever@gmail.com#ifdef EVENTQ_DEBUG 2309983Sstever@gmail.com whenScheduled = curTick(); 2319983Sstever@gmail.com#endif 2329983Sstever@gmail.com } 2339983Sstever@gmail.com 2349983Sstever@gmail.com bool 2359983Sstever@gmail.com initialized() const 2369983Sstever@gmail.com { 2379983Sstever@gmail.com return this && (flags & InitMask) == Initialized; 2389983Sstever@gmail.com } 2399983Sstever@gmail.com 2409983Sstever@gmail.com protected: 2419983Sstever@gmail.com /// Accessor for flags. 2429983Sstever@gmail.com Flags 2439983Sstever@gmail.com getFlags() const 2449983Sstever@gmail.com { 2459983Sstever@gmail.com return flags & PublicRead; 2469983Sstever@gmail.com } 2479983Sstever@gmail.com 2489983Sstever@gmail.com bool 2499983Sstever@gmail.com isFlagSet(Flags _flags) const 2509983Sstever@gmail.com { 2519983Sstever@gmail.com assert(_flags.noneSet(~PublicRead)); 2529983Sstever@gmail.com return flags.isSet(_flags); 2539983Sstever@gmail.com } 2549983Sstever@gmail.com 2559983Sstever@gmail.com /// Accessor for flags. 2569983Sstever@gmail.com void 2579983Sstever@gmail.com setFlags(Flags _flags) 2589983Sstever@gmail.com { 2599983Sstever@gmail.com assert(_flags.noneSet(~PublicWrite)); 2609983Sstever@gmail.com flags.set(_flags); 2619983Sstever@gmail.com } 2629983Sstever@gmail.com 2639983Sstever@gmail.com void 2649983Sstever@gmail.com clearFlags(Flags _flags) 2659983Sstever@gmail.com { 2669983Sstever@gmail.com assert(_flags.noneSet(~PublicWrite)); 2679983Sstever@gmail.com flags.clear(_flags); 2689983Sstever@gmail.com } 2699983Sstever@gmail.com 2709983Sstever@gmail.com void 2719983Sstever@gmail.com clearFlags() 2729983Sstever@gmail.com { 2739983Sstever@gmail.com flags.clear(PublicWrite); 2749983Sstever@gmail.com } 2759983Sstever@gmail.com 2769983Sstever@gmail.com // This function isn't really useful if TRACING_ON is not defined 2779983Sstever@gmail.com virtual void trace(const char *action); //!< trace event activity 2789983Sstever@gmail.com 2799983Sstever@gmail.com public: 280396SN/A 2812SN/A /* 2822SN/A * Event constructor 2832SN/A * @param queue that the event gets scheduled on 2842SN/A */ 2858581Ssteve.reinhardt@amd.com Event(Priority p = Default_Pri, Flags f = 0) 2868581Ssteve.reinhardt@amd.com : nextBin(NULL), nextInBin(NULL), _priority(p), 2878581Ssteve.reinhardt@amd.com flags(Initialized | f) 288224SN/A { 2898581Ssteve.reinhardt@amd.com assert(f.noneSet(~PublicWrite)); 2904016Sstever@eecs.umich.edu#ifndef NDEBUG 2915501Snate@binkert.org instance = ++instanceCounter; 2925605Snate@binkert.org queue = NULL; 2935501Snate@binkert.org#endif 2945501Snate@binkert.org#ifdef EVENTQ_DEBUG 2957823Ssteve.reinhardt@amd.com whenCreated = curTick(); 2965501Snate@binkert.org whenScheduled = 0; 2974016Sstever@eecs.umich.edu#endif 298224SN/A } 299224SN/A 3005768Snate@binkert.org virtual ~Event(); 3015768Snate@binkert.org virtual const std::string name() const; 302265SN/A 3035501Snate@binkert.org /// Return a C string describing the event. This string should 3045501Snate@binkert.org /// *not* be dynamically allocated; just a const char array 3055501Snate@binkert.org /// describing the event class. 3065501Snate@binkert.org virtual const char *description() const; 3075501Snate@binkert.org 3085501Snate@binkert.org /// Dump the current event data 3095501Snate@binkert.org void dump() const; 3105501Snate@binkert.org 3115501Snate@binkert.org public: 3125501Snate@binkert.org /* 3135501Snate@binkert.org * This member function is invoked when the event is processed 3145501Snate@binkert.org * (occurs). There is no default implementation; each subclass 3155501Snate@binkert.org * must provide its own implementation. The event is not 3165501Snate@binkert.org * automatically deleted after it is processed (to allow for 3175501Snate@binkert.org * statically allocated event objects). 3185501Snate@binkert.org * 3195501Snate@binkert.org * If the AutoDestroy flag is set, the object is deleted once it 3205501Snate@binkert.org * is processed. 3215501Snate@binkert.org */ 3225501Snate@binkert.org virtual void process() = 0; 3235501Snate@binkert.org 3242SN/A /// Determine if the current event is scheduled 3255769Snate@binkert.org bool scheduled() const { return flags.isSet(Scheduled); } 3262SN/A 3272SN/A /// Squash the current event 3285769Snate@binkert.org void squash() { flags.set(Squashed); } 3292SN/A 3302SN/A /// Check whether the event is squashed 3315769Snate@binkert.org bool squashed() const { return flags.isSet(Squashed); } 3322SN/A 3332667Sstever@eecs.umich.edu /// See if this is a SimExitEvent (without resorting to RTTI) 3345769Snate@binkert.org bool isExitEvent() const { return flags.isSet(IsExitEvent); } 3352667Sstever@eecs.umich.edu 3362SN/A /// Get the time that the event is scheduled 3372SN/A Tick when() const { return _when; } 3382SN/A 3392SN/A /// Get the event priority 3407058Snate@binkert.org Priority priority() const { return _priority; } 3412SN/A 3429983Sstever@gmail.com //! If this is part of a GlobalEvent, return the pointer to the 3439983Sstever@gmail.com //! Global Event. By default, there is no GlobalEvent, so return 3449983Sstever@gmail.com //! NULL. (Overridden in GlobalEvent::BarrierEvent.) 3459983Sstever@gmail.com virtual BaseGlobalEvent *globalEvent() { return NULL; } 3469983Sstever@gmail.com 3475605Snate@binkert.org#ifndef SWIG 348224SN/A virtual void serialize(std::ostream &os); 349237SN/A virtual void unserialize(Checkpoint *cp, const std::string §ion); 3509983Sstever@gmail.com 3519983Sstever@gmail.com //! This function is required to support restoring from checkpoints 3529983Sstever@gmail.com //! when running with multiple queues. Since we still have not thrashed 3539983Sstever@gmail.com //! out all the details on checkpointing, this function is most likely 3549983Sstever@gmail.com //! to be revisited in future. 3559983Sstever@gmail.com virtual void unserialize(Checkpoint *cp, const std::string §ion, 3569983Sstever@gmail.com EventQueue *eventq); 3575605Snate@binkert.org#endif 358571SN/A}; 359571SN/A 3607005Snate@binkert.org#ifndef SWIG 3617005Snate@binkert.orginline bool 3627005Snate@binkert.orgoperator<(const Event &l, const Event &r) 3637005Snate@binkert.org{ 3647005Snate@binkert.org return l.when() < r.when() || 3657005Snate@binkert.org (l.when() == r.when() && l.priority() < r.priority()); 3667005Snate@binkert.org} 3677005Snate@binkert.org 3687005Snate@binkert.orginline bool 3697005Snate@binkert.orgoperator>(const Event &l, const Event &r) 3707005Snate@binkert.org{ 3717005Snate@binkert.org return l.when() > r.when() || 3727005Snate@binkert.org (l.when() == r.when() && l.priority() > r.priority()); 3737005Snate@binkert.org} 3747005Snate@binkert.org 3757005Snate@binkert.orginline bool 3767005Snate@binkert.orgoperator<=(const Event &l, const Event &r) 3777005Snate@binkert.org{ 3787005Snate@binkert.org return l.when() < r.when() || 3797005Snate@binkert.org (l.when() == r.when() && l.priority() <= r.priority()); 3807005Snate@binkert.org} 3817005Snate@binkert.orginline bool 3827005Snate@binkert.orgoperator>=(const Event &l, const Event &r) 3837005Snate@binkert.org{ 3847005Snate@binkert.org return l.when() > r.when() || 3857005Snate@binkert.org (l.when() == r.when() && l.priority() >= r.priority()); 3867005Snate@binkert.org} 3877005Snate@binkert.org 3887005Snate@binkert.orginline bool 3897005Snate@binkert.orgoperator==(const Event &l, const Event &r) 3907005Snate@binkert.org{ 3917005Snate@binkert.org return l.when() == r.when() && l.priority() == r.priority(); 3927005Snate@binkert.org} 3937005Snate@binkert.org 3947005Snate@binkert.orginline bool 3957005Snate@binkert.orgoperator!=(const Event &l, const Event &r) 3967005Snate@binkert.org{ 3977005Snate@binkert.org return l.when() != r.when() || l.priority() != r.priority(); 3987005Snate@binkert.org} 3997005Snate@binkert.org#endif 4007005Snate@binkert.org 4012SN/A/* 4022SN/A * Queue of events sorted in time order 4032SN/A */ 404395SN/Aclass EventQueue : public Serializable 4052SN/A{ 4065605Snate@binkert.org private: 407265SN/A std::string objName; 4082SN/A Event *head; 4099356Snilay@cs.wisc.edu Tick _curTick; 4102SN/A 4119983Sstever@gmail.com //! Mutex to protect async queue. 4129983Sstever@gmail.com std::mutex *async_queue_mutex; 4139983Sstever@gmail.com 4149983Sstever@gmail.com //! List of events added by other threads to this event queue. 4159983Sstever@gmail.com std::list<Event*> async_queue; 4169983Sstever@gmail.com 4179983Sstever@gmail.com //! Insert / remove event from the queue. Should only be called 4189983Sstever@gmail.com //! by thread operating this queue. 4192SN/A void insert(Event *event); 4202SN/A void remove(Event *event); 4212SN/A 4229983Sstever@gmail.com //! Function for adding events to the async queue. The added events 4239983Sstever@gmail.com //! are added to main event queue later. Threads, other than the 4249983Sstever@gmail.com //! owning thread, should call this function instead of insert(). 4259983Sstever@gmail.com void asyncInsert(Event *event); 4269983Sstever@gmail.com 4277063Snate@binkert.org EventQueue(const EventQueue &); 4287063Snate@binkert.org 4292SN/A public: 4307063Snate@binkert.org EventQueue(const std::string &n); 4312SN/A 432512SN/A virtual const std::string name() const { return objName; } 4339983Sstever@gmail.com void name(const std::string &st) { objName = st; } 434265SN/A 4359983Sstever@gmail.com //! Schedule the given event on this queue. Safe to call from any 4369983Sstever@gmail.com //! thread. 4379983Sstever@gmail.com void schedule(Event *event, Tick when, bool global = false); 4389983Sstever@gmail.com 4399983Sstever@gmail.com //! Deschedule the specified event. Should be called only from the 4409983Sstever@gmail.com //! owning thread. 4415738Snate@binkert.org void deschedule(Event *event); 4429983Sstever@gmail.com 4439983Sstever@gmail.com //! Reschedule the specified event. Should be called only from 4449983Sstever@gmail.com //! the owning thread. 4455738Snate@binkert.org void reschedule(Event *event, Tick when, bool always = false); 4462SN/A 4475501Snate@binkert.org Tick nextTick() const { return head->when(); } 4489356Snilay@cs.wisc.edu void setCurTick(Tick newVal) { _curTick = newVal; } 4499356Snilay@cs.wisc.edu Tick getCurTick() { return _curTick; } 4509356Snilay@cs.wisc.edu 4512667Sstever@eecs.umich.edu Event *serviceOne(); 4522SN/A 4532SN/A // process all events up to the given timestamp. we inline a 4542SN/A // quick test to see if there are any events to process; if so, 4552SN/A // call the internal out-of-line version to process them all. 4565501Snate@binkert.org void 4575501Snate@binkert.org serviceEvents(Tick when) 4585501Snate@binkert.org { 4592SN/A while (!empty()) { 4602SN/A if (nextTick() > when) 4612SN/A break; 4622SN/A 4631634SN/A /** 4641634SN/A * @todo this assert is a good bug catcher. I need to 4651634SN/A * make it true again. 4661634SN/A */ 4671634SN/A //assert(head->when() >= when && "event scheduled in the past"); 4682SN/A serviceOne(); 4692SN/A } 4709356Snilay@cs.wisc.edu 4719356Snilay@cs.wisc.edu setCurTick(when); 4722SN/A } 4732SN/A 4742SN/A // return true if no events are queued 4755501Snate@binkert.org bool empty() const { return head == NULL; } 4762SN/A 4775501Snate@binkert.org void dump() const; 4782SN/A 4795502Snate@binkert.org bool debugVerify() const; 4805502Snate@binkert.org 4819983Sstever@gmail.com //! Function for moving events from the async_queue to the main queue. 4829983Sstever@gmail.com void handleAsyncInsertions(); 4839983Sstever@gmail.com 4848648Snilay@cs.wisc.edu /** 4858648Snilay@cs.wisc.edu * function for replacing the head of the event queue, so that a 4868648Snilay@cs.wisc.edu * different set of events can run without disturbing events that have 4878648Snilay@cs.wisc.edu * already been scheduled. Already scheduled events can be processed 4888648Snilay@cs.wisc.edu * by replacing the original head back. 4898648Snilay@cs.wisc.edu * USING THIS FUNCTION CAN BE DANGEROUS TO THE HEALTH OF THE SIMULATOR. 4908648Snilay@cs.wisc.edu * NOT RECOMMENDED FOR USE. 4918648Snilay@cs.wisc.edu */ 4928648Snilay@cs.wisc.edu Event* replaceHead(Event* s); 4938648Snilay@cs.wisc.edu 4945605Snate@binkert.org#ifndef SWIG 495217SN/A virtual void serialize(std::ostream &os); 496237SN/A virtual void unserialize(Checkpoint *cp, const std::string §ion); 4975605Snate@binkert.org#endif 4982SN/A}; 4992SN/A 5009554Sandreas.hansson@arm.comvoid dumpMainQueue(); 5019554Sandreas.hansson@arm.com 5025605Snate@binkert.org#ifndef SWIG 5035605Snate@binkert.orgclass EventManager 5045605Snate@binkert.org{ 5055605Snate@binkert.org protected: 5065605Snate@binkert.org /** A pointer to this object's event queue */ 5075605Snate@binkert.org EventQueue *eventq; 5082SN/A 5095605Snate@binkert.org public: 5109099Sandreas.hansson@arm.com EventManager(EventManager &em) : eventq(em.eventq) {} 5119159Sandreas.hansson@arm.com EventManager(EventManager *em) : eventq(em->eventq) {} 5125605Snate@binkert.org EventManager(EventQueue *eq) : eventq(eq) {} 5132SN/A 5145605Snate@binkert.org EventQueue * 5159099Sandreas.hansson@arm.com eventQueue() const 5167060Snate@binkert.org { 5177060Snate@binkert.org return eventq; 5187060Snate@binkert.org } 5197060Snate@binkert.org 5205605Snate@binkert.org void 5215605Snate@binkert.org schedule(Event &event, Tick when) 5225605Snate@binkert.org { 5235605Snate@binkert.org eventq->schedule(&event, when); 5245605Snate@binkert.org } 5255605Snate@binkert.org 5265605Snate@binkert.org void 5275605Snate@binkert.org deschedule(Event &event) 5285605Snate@binkert.org { 5295605Snate@binkert.org eventq->deschedule(&event); 5305605Snate@binkert.org } 5315605Snate@binkert.org 5325605Snate@binkert.org void 5335605Snate@binkert.org reschedule(Event &event, Tick when, bool always = false) 5345605Snate@binkert.org { 5355605Snate@binkert.org eventq->reschedule(&event, when, always); 5365605Snate@binkert.org } 5375605Snate@binkert.org 5385605Snate@binkert.org void 5395605Snate@binkert.org schedule(Event *event, Tick when) 5405605Snate@binkert.org { 5415605Snate@binkert.org eventq->schedule(event, when); 5425605Snate@binkert.org } 5435605Snate@binkert.org 5445605Snate@binkert.org void 5455605Snate@binkert.org deschedule(Event *event) 5465605Snate@binkert.org { 5475605Snate@binkert.org eventq->deschedule(event); 5485605Snate@binkert.org } 5495605Snate@binkert.org 5505605Snate@binkert.org void 5515605Snate@binkert.org reschedule(Event *event, Tick when, bool always = false) 5525605Snate@binkert.org { 5535605Snate@binkert.org eventq->reschedule(event, when, always); 5545605Snate@binkert.org } 5559356Snilay@cs.wisc.edu 5569356Snilay@cs.wisc.edu void setCurTick(Tick newVal) { eventq->setCurTick(newVal); } 5575605Snate@binkert.org}; 5585605Snate@binkert.org 5597005Snate@binkert.orgtemplate <class T, void (T::* F)()> 5607005Snate@binkert.orgvoid 5617005Snate@binkert.orgDelayFunction(EventQueue *eventq, Tick when, T *object) 5625502Snate@binkert.org{ 5637005Snate@binkert.org class DelayEvent : public Event 5647005Snate@binkert.org { 5657005Snate@binkert.org private: 5667005Snate@binkert.org T *object; 5677005Snate@binkert.org 5687005Snate@binkert.org public: 5697005Snate@binkert.org DelayEvent(T *o) 5708581Ssteve.reinhardt@amd.com : Event(Default_Pri, AutoDelete), object(o) 5718581Ssteve.reinhardt@amd.com { } 5727005Snate@binkert.org void process() { (object->*F)(); } 5737005Snate@binkert.org const char *description() const { return "delay"; } 5747005Snate@binkert.org }; 5757005Snate@binkert.org 5767005Snate@binkert.org eventq->schedule(new DelayEvent(object), when); 5775502Snate@binkert.org} 5785502Snate@binkert.org 5797005Snate@binkert.orgtemplate <class T, void (T::* F)()> 5807005Snate@binkert.orgclass EventWrapper : public Event 5815502Snate@binkert.org{ 5827005Snate@binkert.org private: 5837005Snate@binkert.org T *object; 5845502Snate@binkert.org 5857005Snate@binkert.org public: 5867005Snate@binkert.org EventWrapper(T *obj, bool del = false, Priority p = Default_Pri) 5877005Snate@binkert.org : Event(p), object(obj) 5887005Snate@binkert.org { 5897005Snate@binkert.org if (del) 5907005Snate@binkert.org setFlags(AutoDelete); 5917005Snate@binkert.org } 5925502Snate@binkert.org 5937066Snate@binkert.org EventWrapper(T &obj, bool del = false, Priority p = Default_Pri) 5947066Snate@binkert.org : Event(p), object(&obj) 5957066Snate@binkert.org { 5967066Snate@binkert.org if (del) 5977066Snate@binkert.org setFlags(AutoDelete); 5987066Snate@binkert.org } 5997066Snate@binkert.org 6007005Snate@binkert.org void process() { (object->*F)(); } 6015502Snate@binkert.org 6027005Snate@binkert.org const std::string 6037005Snate@binkert.org name() const 6047005Snate@binkert.org { 6057005Snate@binkert.org return object->name() + ".wrapped_event"; 6067005Snate@binkert.org } 6077005Snate@binkert.org 6087005Snate@binkert.org const char *description() const { return "EventWrapped"; } 6097005Snate@binkert.org}; 6105605Snate@binkert.org#endif 6112SN/A 6121354SN/A#endif // __SIM_EVENTQ_HH__ 613