eventq.hh revision 571
11689SN/A/* 28733Sgeoffrey.blake@arm.com * Copyright (c) 2003 The Regents of The University of Michigan 37598Sminkyu.jeong@arm.com * All rights reserved. 47598Sminkyu.jeong@arm.com * 57598Sminkyu.jeong@arm.com * Redistribution and use in source and binary forms, with or without 67598Sminkyu.jeong@arm.com * modification, are permitted provided that the following conditions are 77598Sminkyu.jeong@arm.com * met: redistributions of source code must retain the above copyright 87598Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer; 97598Sminkyu.jeong@arm.com * redistributions in binary form must reproduce the above copyright 107598Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer in the 117598Sminkyu.jeong@arm.com * documentation and/or other materials provided with the distribution; 127598Sminkyu.jeong@arm.com * neither the name of the copyright holders nor the names of its 137598Sminkyu.jeong@arm.com * contributors may be used to endorse or promote products derived from 142326SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271689SN/A */ 281689SN/A 291689SN/A/* @file 301689SN/A * EventQueue interfaces 311689SN/A */ 321689SN/A 331689SN/A#ifndef __EVENTQ_HH__ 341689SN/A#define __EVENTQ_HH__ 351689SN/A 361689SN/A#include <assert.h> 371689SN/A 381689SN/A#include <algorithm> 392665Ssaidi@eecs.umich.edu#include <map> 402665Ssaidi@eecs.umich.edu#include <string> 411689SN/A#include <vector> 421689SN/A 431060SN/A#include "sim/host.hh" // for Tick 441060SN/A 451689SN/A#include "base/fast_alloc.hh" 461060SN/A#include "sim/serialize.hh" 471060SN/A#include "base/trace.hh" 481060SN/A 498230Snate@binkert.orgclass EventQueue; // forward declaration 506658Snate@binkert.org 518733Sgeoffrey.blake@arm.com/* 522292SN/A * An item on an event queue. The action caused by a given 531717SN/A * event is specified by deriving a subclass and overriding the 548229Snate@binkert.org * process() member function. 558232Snate@binkert.org */ 568232Snate@binkert.orgclass Event : public Serializable, public FastAlloc 578232Snate@binkert.org{ 585529Snate@binkert.org friend class EventQueue; 591060SN/A 608733Sgeoffrey.blake@arm.com private: 618733Sgeoffrey.blake@arm.com /// queue to which this event belongs (though it may or may not be 628733Sgeoffrey.blake@arm.com /// scheduled on this queue yet) 638733Sgeoffrey.blake@arm.com EventQueue *queue; 646221Snate@binkert.org 656221Snate@binkert.org Event *next; 661681SN/A 675529Snate@binkert.org Tick _when; //!< timestamp when event should be processed 682873Sktlim@umich.edu int _priority; //!< event priority 694329Sktlim@umich.edu char _flags; 704329Sktlim@umich.edu 714329Sktlim@umich.edu protected: 722292SN/A enum Flags { 732292SN/A None = 0x0, 742292SN/A Squashed = 0x1, 752292SN/A Scheduled = 0x2, 762820Sktlim@umich.edu AutoDelete = 0x4, 772292SN/A AutoSerialize = 0x8 782820Sktlim@umich.edu }; 792820Sktlim@umich.edu 805529Snate@binkert.org bool getFlags(Flags f) const { return (_flags & f) == f; } 812307SN/A void setFlags(Flags f) { _flags |= f; } 821060SN/A void clearFlags(Flags f) { _flags &= ~f; } 832292SN/A 842292SN/A protected: 852292SN/A EventQueue *theQueue() const { return queue; } 861060SN/A 871060SN/A#if TRACING_ON 881060SN/A Tick when_created; //!< Keep track of creation time For debugging 891060SN/A Tick when_scheduled; //!< Keep track of creation time For debugging 901060SN/A 911060SN/A virtual void trace(const char *action); //!< trace event activity 921681SN/A#else 936221Snate@binkert.org void trace(const char *) {} 946221Snate@binkert.org#endif 956221Snate@binkert.org 966221Snate@binkert.org unsigned annotated_value; 972292SN/A 982292SN/A public: 992820Sktlim@umich.edu 1002820Sktlim@umich.edu /// Event priorities, to provide tie-breakers for events scheduled 1012292SN/A /// at the same cycle. Most events are scheduled at the default 1022292SN/A /// priority; these values are used to control events that need to 1032820Sktlim@umich.edu /// be ordered within a cycle. 1042820Sktlim@umich.edu enum Priority { 1052292SN/A /// Breakpoints should happen before anything else, so we 1062292SN/A /// don't miss any action when debugging. 1072292SN/A Debug_Break_Pri = -100, 1082292SN/A 1092292SN/A /// For some reason "delayed" inter-cluster writebacks are 1102292SN/A /// scheduled before regular writebacks (which have default 1112292SN/A /// priority). Steve? 1122292SN/A Delayed_Writeback_Pri = -1, 1131060SN/A 1141060SN/A /// Default is zero for historical reasons. 1151681SN/A Default_Pri = 0, 1161062SN/A 1172292SN/A /// CPU switches schedule the new CPU's tick event for the 1181062SN/A /// same cycle (after unscheduling the old CPU's tick event). 1192301SN/A /// The switch needs to come before any tick events to make 1202301SN/A /// sure we don't tick both CPUs in the same cycle. 1211062SN/A CPU_Switch_Pri = 31, 1222727Sktlim@umich.edu 1231062SN/A /// Serailization needs to occur before tick events also, so 1241062SN/A /// that a serialize/unserialize is identical to an on-line 1251062SN/A /// CPU switch. 1261062SN/A Serialize_Pri = 32, 1271062SN/A 1281062SN/A /// CPU ticks must come after other associated CPU events 1291062SN/A /// (such as writebacks). 1301062SN/A CPU_Tick_Pri = 50, 1311062SN/A 1321062SN/A /// Statistics events (dump, reset, etc.) come after 1331062SN/A /// everything else, but before exit. 1341062SN/A Stat_Event_Pri = 90, 1351062SN/A 1361062SN/A /// If we want to exit on this cycle, it's the very last thing 1371062SN/A /// we do. 1381062SN/A Sim_Exit_Pri = 100 1391062SN/A }; 1401062SN/A 1411062SN/A /* 1421062SN/A * Event constructor 1431062SN/A * @param queue that the event gets scheduled on 1441062SN/A */ 1451062SN/A Event(EventQueue *q, Priority p = Default_Pri) 1461062SN/A : queue(q), next(NULL), _priority(p), _flags(None), 1471062SN/A#if TRACING_ON 1481062SN/A when_created(curTick), when_scheduled(0), 1491062SN/A#endif 1501062SN/A annotated_value(0) 1511062SN/A { 1521062SN/A } 1531062SN/A 1541062SN/A ~Event() {} 1551062SN/A 1561062SN/A virtual const std::string name() const { 1571062SN/A return csprintf("Event_%x", (uintptr_t)this); 1581062SN/A } 1591062SN/A 1601062SN/A /// Determine if the current event is scheduled 1611062SN/A bool scheduled() const { return getFlags(Scheduled); } 1621062SN/A 1631062SN/A /// Schedule the event with the current priority or default priority 1642292SN/A void schedule(Tick t); 1652292SN/A 1662292SN/A /// Reschedule the event with the current priority 1672292SN/A void reschedule(Tick t); 1681062SN/A 1691062SN/A /// Remove the event from the current schedule 1701062SN/A void deschedule(); 1711062SN/A 1721062SN/A /// Return a C string describing the event. This string should 1731062SN/A /// *not* be dynamically allocated; just a const char array 1741062SN/A /// describing the event class. 1752292SN/A virtual const char *description(); 1762292SN/A 1772292SN/A /// Dump the current event data 1782292SN/A void dump(); 1792292SN/A 1802292SN/A /* 1812292SN/A * This member function is invoked when the event is processed 1822292SN/A * (occurs). There is no default implementation; each subclass 1832292SN/A * must provide its own implementation. The event is not 1842292SN/A * automatically deleted after it is processed (to allow for 1852301SN/A * statically allocated event objects). 1862727Sktlim@umich.edu * 1872353SN/A * If the AutoDestroy flag is set, the object is deleted once it 1882727Sktlim@umich.edu * is processed. 1892727Sktlim@umich.edu */ 1902727Sktlim@umich.edu virtual void process() = 0; 1916221Snate@binkert.org 1922353SN/A void annotate(unsigned value) { annotated_value = value; }; 1932727Sktlim@umich.edu unsigned annotation() { return annotated_value; } 1942727Sktlim@umich.edu 1952727Sktlim@umich.edu /// Squash the current event 1962727Sktlim@umich.edu void squash() { setFlags(Squashed); } 1972353SN/A 1982727Sktlim@umich.edu /// Check whether the event is squashed 1992727Sktlim@umich.edu bool squashed() { return getFlags(Squashed); } 2002727Sktlim@umich.edu 2016221Snate@binkert.org /// Get the time that the event is scheduled 2028240Snate@binkert.org Tick when() const { return _when; } 2032301SN/A 2042727Sktlim@umich.edu /// Get the event priority 2052301SN/A int priority() const { return _priority; } 2062727Sktlim@umich.edu 2076221Snate@binkert.org struct priority_compare : 2088240Snate@binkert.org public std::binary_function<Event *, Event *, bool> 2092301SN/A { 2102727Sktlim@umich.edu bool operator()(const Event *l, const Event *r) const { 2112301SN/A return l->when() >= r->when() || l->priority() >= r->priority(); 2122727Sktlim@umich.edu } 2136221Snate@binkert.org }; 2148240Snate@binkert.org 2152301SN/A virtual void serialize(std::ostream &os); 2162727Sktlim@umich.edu virtual void unserialize(Checkpoint *cp, const std::string §ion); 2172301SN/A}; 2182727Sktlim@umich.edu 2196221Snate@binkert.orgtemplate <class T, void (T::* F)()> 2208240Snate@binkert.orgvoid 2212301SN/ADelayFunction(Tick when, T *object) 2222727Sktlim@umich.edu{ 2232301SN/A class DelayEvent : public Event 2242301SN/A { 2258240Snate@binkert.org private: 2262301SN/A T *object; 2272727Sktlim@umich.edu 2282727Sktlim@umich.edu public: 2292727Sktlim@umich.edu DelayEvent(Tick when, T *o) 2302727Sktlim@umich.edu : Event(&mainEventQueue), object(o) 2318240Snate@binkert.org { setFlags(AutoDestroy); schedule(when); } 2322727Sktlim@umich.edu void process() { (object->*F)(); } 2332727Sktlim@umich.edu const char *description() { return "delay"; } 2342727Sktlim@umich.edu }; 2352727Sktlim@umich.edu 2362301SN/A new DelayEvent(when, object); 2372301SN/A} 2386221Snate@binkert.org 2398240Snate@binkert.orgtemplate <class T, void (T::* F)()> 2402301SN/Aclass EventWrapper : public Event 2412727Sktlim@umich.edu{ 2422301SN/A private: 2432326SN/A T *object; 2446221Snate@binkert.org 2458240Snate@binkert.org public: 2462301SN/A EventWrapper(T *obj, EventQueue *q = &mainEventQueue, 2472727Sktlim@umich.edu Priority p = Default_Pri) 2482301SN/A : Event(q, p), object(obj) 2492326SN/A {} 2506221Snate@binkert.org void process() { (object->*F)(); } 2518240Snate@binkert.org}; 2522301SN/A 2532727Sktlim@umich.edu/* 2542301SN/A * Queue of events sorted in time order 2552326SN/A */ 2566221Snate@binkert.orgclass EventQueue : public Serializable 2578240Snate@binkert.org{ 2582301SN/A protected: 2592727Sktlim@umich.edu std::string objName; 2602301SN/A 2612326SN/A private: 2626221Snate@binkert.org Event *head; 2638240Snate@binkert.org 2642301SN/A void insert(Event *event); 2652727Sktlim@umich.edu void remove(Event *event); 2662301SN/A 2672326SN/A public: 2688240Snate@binkert.org 2692301SN/A // constructor 2702727Sktlim@umich.edu EventQueue(const std::string &n) 2712301SN/A : objName(n), head(NULL) 2722326SN/A {} 2732301SN/A 2742326SN/A virtual const std::string name() const { return objName; } 2758240Snate@binkert.org 2762301SN/A // schedule the given event on this queue 2772727Sktlim@umich.edu void schedule(Event *ev); 2782301SN/A void deschedule(Event *ev); 2792326SN/A void reschedule(Event *ev); 2802301SN/A 2812326SN/A Tick nextTick() { return head->when(); } 2828240Snate@binkert.org void serviceOne(); 2832301SN/A 2842727Sktlim@umich.edu // process all events up to the given timestamp. we inline a 2852326SN/A // quick test to see if there are any events to process; if so, 2861062SN/A // call the internal out-of-line version to process them all. 2871062SN/A void serviceEvents(Tick when) { 2881681SN/A while (!empty()) { 2891060SN/A if (nextTick() > when) 2902292SN/A break; 2911060SN/A 2926221Snate@binkert.org assert(head->when() >= when && "event scheduled in the past"); 2932292SN/A serviceOne(); 2942292SN/A } 2952292SN/A } 2962292SN/A 2972292SN/A // default: process all events up to 'now' (curTick) 2982292SN/A void serviceEvents() { serviceEvents(curTick); } 2992292SN/A 3002292SN/A // return true if no events are queued 3012292SN/A bool empty() { return head == NULL; } 3028733Sgeoffrey.blake@arm.com 3038733Sgeoffrey.blake@arm.com void dump(); 3048733Sgeoffrey.blake@arm.com 3058850Sandreas.hansson@arm.com Tick nextEventTime() { return empty() ? curTick : head->when(); } 3068733Sgeoffrey.blake@arm.com 3078733Sgeoffrey.blake@arm.com virtual void serialize(std::ostream &os); 3088733Sgeoffrey.blake@arm.com virtual void unserialize(Checkpoint *cp, const std::string §ion); 3092733Sktlim@umich.edu}; 3101060SN/A 3111060SN/A 3121681SN/A////////////////////// 3131060SN/A// 3142292SN/A// inline functions 3151060SN/A// 3161060SN/A// can't put these inside declaration due to circular dependence 3171060SN/A// between Event and EventQueue classes. 3181060SN/A// 3191060SN/A////////////////////// 3201060SN/A 3211060SN/A// schedule at specified time (place on event queue specified via 3221060SN/A// constructor) 3231060SN/Ainline void 3242292SN/AEvent::schedule(Tick t) 3252292SN/A{ 3261060SN/A assert(!scheduled()); 3271060SN/A setFlags(Scheduled); 3281060SN/A#if TRACING_ON 3291060SN/A when_scheduled = curTick; 3301681SN/A#endif 3311060SN/A _when = t; 3322292SN/A queue->schedule(this); 3331060SN/A} 3341060SN/A 3351060SN/Ainline void 3361060SN/AEvent::deschedule() 3371060SN/A{ 3381060SN/A assert(scheduled()); 3391060SN/A 3401681SN/A clearFlags(Squashed); 3411060SN/A clearFlags(Scheduled); 3422292SN/A queue->deschedule(this); 3431060SN/A} 3441060SN/A 3451060SN/Ainline void 3461060SN/AEvent::reschedule(Tick t) 3471060SN/A{ 3481060SN/A assert(scheduled()); 3491060SN/A clearFlags(Squashed); 3501681SN/A 3511060SN/A#if TRACING_ON 3526221Snate@binkert.org when_scheduled = curTick; 3531060SN/A#endif 3542292SN/A _when = t; 3552292SN/A queue->reschedule(this); 3562292SN/A} 3572292SN/A 3581060SN/Ainline void 3591060SN/AEventQueue::schedule(Event *event) 3601681SN/A{ 3611060SN/A insert(event); 3622292SN/A if (DTRACE(Event)) 3631060SN/A event->trace("scheduled"); 3642292SN/A} 3651060SN/A 3661060SN/Ainline void 3672307SN/AEventQueue::deschedule(Event *event) 3682863Sktlim@umich.edu{ 3692843Sktlim@umich.edu remove(event); 3702307SN/A if (DTRACE(Event)) 3712843Sktlim@umich.edu event->trace("descheduled"); 3722843Sktlim@umich.edu} 3732863Sktlim@umich.edu 3741681SN/Ainline void 3751681SN/AEventQueue::reschedule(Event *event) 3762316SN/A{ 3771681SN/A remove(event); 3782843Sktlim@umich.edu insert(event); 3792843Sktlim@umich.edu if (DTRACE(Event)) 3802843Sktlim@umich.edu event->trace("rescheduled"); 3812843Sktlim@umich.edu} 3822843Sktlim@umich.edu 3832843Sktlim@umich.edu 3842843Sktlim@umich.edu////////////////////// 3851681SN/A// 3862348SN/A// Main Event Queue 3872307SN/A// 3882367SN/A// Events on this queue are processed at the *beginning* of each 3892367SN/A// cycle, before the pipeline simulation is performed. 3901681SN/A// 3912307SN/A// defined in eventq.cc 3922307SN/A// 3932307SN/A////////////////////// 3942307SN/Aextern EventQueue mainEventQueue; 3956221Snate@binkert.org 3966221Snate@binkert.org#endif // __EVENTQ_HH__ 3976221Snate@binkert.org