eventq.hh revision 224
14661Sksewell@umich.edu/* 25268Sksewell@umich.edu * Copyright (c) 2003 The Regents of The University of Michigan 35268Sksewell@umich.edu * All rights reserved. 44661Sksewell@umich.edu * 55268Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without 65268Sksewell@umich.edu * modification, are permitted provided that the following conditions are 75268Sksewell@umich.edu * met: redistributions of source code must retain the above copyright 85268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer; 95268Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright 105268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the 115268Sksewell@umich.edu * documentation and/or other materials provided with the distribution; 125268Sksewell@umich.edu * neither the name of the copyright holders nor the names of its 135268Sksewell@umich.edu * contributors may be used to endorse or promote products derived from 145268Sksewell@umich.edu * this software without specific prior written permission. 154661Sksewell@umich.edu * 165268Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175268Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185268Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195268Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205268Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215268Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225268Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235268Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245268Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255268Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265268Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274661Sksewell@umich.edu */ 284661Sksewell@umich.edu 294661Sksewell@umich.edu/* @file 304661Sksewell@umich.edu * EventQueue interfaces 314661Sksewell@umich.edu */ 324661Sksewell@umich.edu 334661Sksewell@umich.edu#ifndef __EVENTQ_HH__ 344661Sksewell@umich.edu#define __EVENTQ_HH__ 354661Sksewell@umich.edu 364661Sksewell@umich.edu#include <assert.h> 376216Snate@binkert.org 384661Sksewell@umich.edu#include <algorithm> 394661Sksewell@umich.edu#include <map> 404661Sksewell@umich.edu#include <string> 414661Sksewell@umich.edu#include <vector> 424661Sksewell@umich.edu 434661Sksewell@umich.edu#include "sim/host.hh" // for Tick 445558Snate@binkert.org 455558Snate@binkert.org#include "base/fast_alloc.hh" 465558Snate@binkert.org#include "sim/serialize.hh" 475558Snate@binkert.org#include "base/trace.hh" 485558Snate@binkert.org 495558Snate@binkert.orgclass EventQueue; // forward declaration 505558Snate@binkert.org 514661Sksewell@umich.edu/* 524661Sksewell@umich.edu * An item on an event queue. The action caused by a given 535558Snate@binkert.org * event is specified by deriving a subclass and overriding the 545558Snate@binkert.org * process() member function. 555558Snate@binkert.org */ 565558Snate@binkert.orgclass Event : public Serializeable, public FastAlloc 575558Snate@binkert.org{ 585558Snate@binkert.org friend class EventQueue; 595558Snate@binkert.org 605558Snate@binkert.org private: 615558Snate@binkert.org /// queue to which this event belongs (though it may or may not be 625558Snate@binkert.org /// scheduled on this queue yet) 635558Snate@binkert.org EventQueue *queue; 645558Snate@binkert.org 655558Snate@binkert.org Event *next; 665558Snate@binkert.org 675558Snate@binkert.org Tick _when; //!< timestamp when event should be processed 685558Snate@binkert.org int _priority; //!< event priority 695558Snate@binkert.org char _flags; 705558Snate@binkert.org 715558Snate@binkert.org protected: 725558Snate@binkert.org enum Flags { 735558Snate@binkert.org None = 0x0, 745558Snate@binkert.org Squashed = 0x1, 755558Snate@binkert.org Scheduled = 0x2, 765558Snate@binkert.org AutoDelete = 0x4 775558Snate@binkert.org }; 785558Snate@binkert.org 795558Snate@binkert.org bool getFlags(Flags f) const { return (_flags & f) == f; } 805558Snate@binkert.org void setFlags(Flags f) { _flags |= f; } 815558Snate@binkert.org void clearFlags(Flags f) { _flags &= ~f; } 825558Snate@binkert.org 835558Snate@binkert.org protected: 845558Snate@binkert.org EventQueue *theQueue() const { return queue; } 855558Snate@binkert.org 865558Snate@binkert.org#if TRACING_ON 875558Snate@binkert.org Tick when_created; //!< Keep track of creation time For debugging 885558Snate@binkert.org Tick when_scheduled; //!< Keep track of creation time For debugging 895558Snate@binkert.org 905558Snate@binkert.org virtual void trace(const char *action); //!< trace event activity 915558Snate@binkert.org#else 925558Snate@binkert.org void trace(const char *) {} 935558Snate@binkert.org#endif 945558Snate@binkert.org 955558Snate@binkert.org unsigned annotated_value; 965558Snate@binkert.org 975558Snate@binkert.org public: 985558Snate@binkert.org 995558Snate@binkert.org static const std::string defaultName; 1005558Snate@binkert.org 1015558Snate@binkert.org /* 1025558Snate@binkert.org * Event constructor 1035558Snate@binkert.org * @param queue that the event gets scheduled on 1045558Snate@binkert.org */ 1055558Snate@binkert.org Event(EventQueue *q, int p = 0) 1065558Snate@binkert.org : Serializeable(defaultName), queue(q), next(NULL), 1075558Snate@binkert.org _priority(p), _flags(None), 1085558Snate@binkert.org#if TRACING_ON 1095558Snate@binkert.org when_created(curTick), when_scheduled(0), 1105558Snate@binkert.org#endif 1115558Snate@binkert.org annotated_value(0) 1125558Snate@binkert.org { 1135558Snate@binkert.org } 1145558Snate@binkert.org 1155558Snate@binkert.org /* 1165558Snate@binkert.org * Event constructor 1175558Snate@binkert.org * @param queue that the event gets scheduled on 1185558Snate@binkert.org */ 1195558Snate@binkert.org Event(EventQueue *q, std::string _name, int p = 0) 1205558Snate@binkert.org : Serializeable(_name), queue(q), next(NULL), 1215558Snate@binkert.org _priority(p), _flags(None), 1225558Snate@binkert.org#if TRACING_ON 1235558Snate@binkert.org when_created(curTick), when_scheduled(0), 1245558Snate@binkert.org#endif 1255558Snate@binkert.org annotated_value(0) 1265558Snate@binkert.org { 1275558Snate@binkert.org } 1285558Snate@binkert.org 1295558Snate@binkert.org ~Event() {} 1305558Snate@binkert.org 1315558Snate@binkert.org /// Determine if the current event is scheduled 1325558Snate@binkert.org bool scheduled() const { return getFlags(Scheduled); } 1335558Snate@binkert.org 1345558Snate@binkert.org /// Schedule the event with the current priority or default priority 1355558Snate@binkert.org void schedule(Tick t); 1365558Snate@binkert.org 1375558Snate@binkert.org /// Schedule the event with a specific priority 1385558Snate@binkert.org void schedule(Tick t, int priority); 1395558Snate@binkert.org 1405558Snate@binkert.org /// Reschedule the event with the current priority 1415558Snate@binkert.org void reschedule(Tick t); 1425558Snate@binkert.org 1435558Snate@binkert.org /// Reschedule the event with a specific priority 1445558Snate@binkert.org void reschedule(Tick t, int priority); 1455558Snate@binkert.org 1465558Snate@binkert.org /// Remove the event from the current schedule 1475558Snate@binkert.org void deschedule(); 1485558Snate@binkert.org 1495558Snate@binkert.org /// Return a C string describing the event. This string should 1505558Snate@binkert.org /// *not* be dynamically allocated; just a const char array 1515558Snate@binkert.org /// describing the event class. 1525558Snate@binkert.org virtual const char *description(); 1535558Snate@binkert.org 1545558Snate@binkert.org /// Dump the current event data 1555558Snate@binkert.org void dump(); 1565558Snate@binkert.org 1575558Snate@binkert.org /* 1585558Snate@binkert.org * This member function is invoked when the event is processed 1595558Snate@binkert.org * (occurs). There is no default implementation; each subclass 1605558Snate@binkert.org * must provide its own implementation. The event is not 1615558Snate@binkert.org * automatically deleted after it is processed (to allow for 1625558Snate@binkert.org * statically allocated event objects). 1635558Snate@binkert.org * 1645558Snate@binkert.org * If the AutoDestroy flag is set, the object is deleted once it 1655558Snate@binkert.org * is processed. 1665558Snate@binkert.org */ 1675558Snate@binkert.org virtual void process() = 0; 1685558Snate@binkert.org 1695558Snate@binkert.org void annotate(unsigned value) { annotated_value = value; }; 1705558Snate@binkert.org unsigned annotation() { return annotated_value; } 1715558Snate@binkert.org 1725558Snate@binkert.org /// Squash the current event 1735558Snate@binkert.org void squash() { setFlags(Squashed); } 1745558Snate@binkert.org 1755558Snate@binkert.org /// Check whether the event is squashed 1765558Snate@binkert.org bool squashed() { return getFlags(Squashed); } 1775558Snate@binkert.org 1785558Snate@binkert.org /// Get the time that the event is scheduled 1795558Snate@binkert.org Tick when() const { return _when; } 1805558Snate@binkert.org 1815558Snate@binkert.org /// Get the event priority 1825558Snate@binkert.org int priority() const { return _priority; } 1835558Snate@binkert.org 1845558Snate@binkert.org struct priority_compare : 1855558Snate@binkert.org public std::binary_function<Event *, Event *, bool> 1865558Snate@binkert.org { 1875558Snate@binkert.org bool operator()(const Event *l, const Event *r) const { 1885558Snate@binkert.org return l->when() >= r->when() || l->priority() >= r->priority(); 1895558Snate@binkert.org } 1905558Snate@binkert.org }; 1915558Snate@binkert.org 1925558Snate@binkert.org virtual void serialize(std::ostream &os); 1935558Snate@binkert.org virtual void unserialize(const IniFile *db, const std::string §ion); 1945558Snate@binkert.org}; 1955558Snate@binkert.org 1965558Snate@binkert.orgtemplate <class T, void (T::* F)()> 1975558Snate@binkert.orgvoid 1985558Snate@binkert.orgDelayFunction(Tick when, T *object) 1995558Snate@binkert.org{ 2005558Snate@binkert.org class DelayEvent : public Event 2015558Snate@binkert.org { 2025558Snate@binkert.org private: 2035558Snate@binkert.org T *object; 2045558Snate@binkert.org 205 public: 206 DelayEvent(Tick when, T *o) 207 : Event(&mainEventQueue), object(o) 208 { setFlags(AutoDestroy); schedule(when); } 209 void process() { (object->*F)(); } 210 const char *description() { return "delay"; } 211 }; 212 213 new DelayEvent(when, object); 214} 215 216/* 217 * Queue of events sorted in time order 218 */ 219class EventQueue : public Serializeable 220{ 221 private: 222 Event *head; 223 224 void insert(Event *event); 225 void remove(Event *event); 226 227 public: 228 229 // constructor 230 EventQueue(const std::string &n) 231 : Serializeable(n), head(NULL) 232 {} 233 234 // schedule the given event on this queue 235 void schedule(Event *ev); 236 void deschedule(Event *ev); 237 void reschedule(Event *ev); 238 239 Tick nextTick() { return head->when(); } 240 void serviceOne(); 241 242 // process all events up to the given timestamp. we inline a 243 // quick test to see if there are any events to process; if so, 244 // call the internal out-of-line version to process them all. 245 void serviceEvents(Tick when) { 246 while (!empty()) { 247 if (nextTick() > when) 248 break; 249 250 assert(head->when() >= when && "event scheduled in the past"); 251 serviceOne(); 252 } 253 } 254 255 // default: process all events up to 'now' (curTick) 256 void serviceEvents() { serviceEvents(curTick); } 257 258 // return true if no events are queued 259 bool empty() { return head == NULL; } 260 261 void dump(); 262 263 Tick nextEventTime() { return empty() ? curTick : head->when(); } 264 265 virtual void nameChildren(); 266 virtual void serialize(std::ostream &os); 267}; 268 269 270////////////////////// 271// 272// inline functions 273// 274// can't put these inside declaration due to circular dependence 275// between Event and EventQueue classes. 276// 277////////////////////// 278 279// schedule at specified time (place on event queue specified via 280// constructor) 281inline void 282Event::schedule(Tick t) 283{ 284 assert(!scheduled()); 285 setFlags(Scheduled); 286#if TRACING_ON 287 when_scheduled = curTick; 288#endif 289 _when = t; 290 queue->schedule(this); 291} 292 293inline void 294Event::schedule(Tick t, int p) 295{ 296 _priority = p; 297 schedule(t); 298} 299 300inline void 301Event::deschedule() 302{ 303 assert(scheduled()); 304 305 clearFlags(Squashed); 306 clearFlags(Scheduled); 307 queue->deschedule(this); 308} 309 310inline void 311Event::reschedule(Tick t) 312{ 313 assert(scheduled()); 314 clearFlags(Squashed); 315 316#if TRACING_ON 317 when_scheduled = curTick; 318#endif 319 _when = t; 320 queue->reschedule(this); 321} 322 323inline void 324Event::reschedule(Tick t, int p) 325{ 326 _priority = p; 327 reschedule(t); 328} 329 330inline void 331EventQueue::schedule(Event *event) 332{ 333 insert(event); 334 if (DTRACE(Event)) 335 event->trace("scheduled"); 336} 337 338inline void 339EventQueue::deschedule(Event *event) 340{ 341 remove(event); 342 if (DTRACE(Event)) 343 event->trace("descheduled"); 344} 345 346inline void 347EventQueue::reschedule(Event *event) 348{ 349 remove(event); 350 insert(event); 351 if (DTRACE(Event)) 352 event->trace("rescheduled"); 353} 354 355 356////////////////////// 357// 358// Main Event Queue 359// 360// Events on this queue are processed at the *beginning* of each 361// cycle, before the pipeline simulation is performed. 362// 363// defined in eventq.cc 364// 365////////////////////// 366extern EventQueue mainEventQueue; 367 368#endif // __EVENTQ_HH__ 369