scheduler.hh revision 13244
12847Sksewell@umich.edu/* 27783SGiacomo.Gabrielli@arm.com * Copyright 2018 Google, Inc. 39913Ssteve.reinhardt@amd.com * 47783SGiacomo.Gabrielli@arm.com * Redistribution and use in source and binary forms, with or without 57783SGiacomo.Gabrielli@arm.com * modification, are permitted provided that the following conditions are 67783SGiacomo.Gabrielli@arm.com * met: redistributions of source code must retain the above copyright 77783SGiacomo.Gabrielli@arm.com * notice, this list of conditions and the following disclaimer; 87783SGiacomo.Gabrielli@arm.com * redistributions in binary form must reproduce the above copyright 97783SGiacomo.Gabrielli@arm.com * notice, this list of conditions and the following disclaimer in the 107783SGiacomo.Gabrielli@arm.com * documentation and/or other materials provided with the distribution; 117783SGiacomo.Gabrielli@arm.com * neither the name of the copyright holders nor the names of its 127783SGiacomo.Gabrielli@arm.com * contributors may be used to endorse or promote products derived from 137783SGiacomo.Gabrielli@arm.com * this software without specific prior written permission. 147783SGiacomo.Gabrielli@arm.com * 155596Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 162847Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 172847Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 182847Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 192847Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 202847Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 212847Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 222847Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 232847Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 242847Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 252847Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 262847Sksewell@umich.edu * 272847Sksewell@umich.edu * Authors: Gabe Black 282847Sksewell@umich.edu */ 292847Sksewell@umich.edu 302847Sksewell@umich.edu#ifndef __SYSTEMC_CORE_SCHEDULER_HH__ 312847Sksewell@umich.edu#define __SYSTEMC_CORE_SCHEDULER_HH__ 322847Sksewell@umich.edu 332847Sksewell@umich.edu#include <functional> 342847Sksewell@umich.edu#include <map> 352847Sksewell@umich.edu#include <set> 362847Sksewell@umich.edu#include <vector> 372847Sksewell@umich.edu 382847Sksewell@umich.edu#include "base/logging.hh" 392847Sksewell@umich.edu#include "sim/core.hh" 402847Sksewell@umich.edu#include "sim/eventq.hh" 415596Sgblack@eecs.umich.edu#include "systemc/core/channel.hh" 422847Sksewell@umich.edu#include "systemc/core/list.hh" 432847Sksewell@umich.edu#include "systemc/core/process.hh" 442847Sksewell@umich.edu#include "systemc/core/sched_event.hh" 452847Sksewell@umich.edu 462847Sksewell@umich.educlass Fiber; 4710835Sandreas.hansson@arm.com 4810835Sandreas.hansson@arm.comnamespace sc_gem5 495596Sgblack@eecs.umich.edu{ 506658Snate@binkert.org 518229Snate@binkert.orgtypedef NodeList<Process> ProcessList; 528229Snate@binkert.orgtypedef NodeList<Channel> ChannelList; 535596Sgblack@eecs.umich.edu 545596Sgblack@eecs.umich.edu/* 559913Ssteve.reinhardt@amd.com * The scheduler supports three different mechanisms, the initialization phase, 562847Sksewell@umich.edu * delta cycles, and timed notifications. 575596Sgblack@eecs.umich.edu * 585596Sgblack@eecs.umich.edu * INITIALIZATION PHASE 595596Sgblack@eecs.umich.edu * 605596Sgblack@eecs.umich.edu * The initialization phase has three parts: 615596Sgblack@eecs.umich.edu * 1. Run requested channel updates. 625596Sgblack@eecs.umich.edu * 2. Make processes which need to initialize runnable (methods and threads 635596Sgblack@eecs.umich.edu * which didn't have dont_initialize called on them). 645596Sgblack@eecs.umich.edu * 3. Process delta notifications. 655596Sgblack@eecs.umich.edu * 665596Sgblack@eecs.umich.edu * First, the Kernel SimObject calls the update() method during its startup() 675596Sgblack@eecs.umich.edu * callback which handles the requested channel updates. The Kernel also 685596Sgblack@eecs.umich.edu * schedules an event to be run at time 0 with a slightly elevated priority 695596Sgblack@eecs.umich.edu * so that it happens before any "normal" event. 7012104Snathanael.premillieu@arm.com * 715596Sgblack@eecs.umich.edu * When that t0 event happens, it calls the schedulers prepareForInit method 725596Sgblack@eecs.umich.edu * which performs step 2 above. That indirectly causes the scheduler's 735596Sgblack@eecs.umich.edu * readyEvent to be scheduled with slightly lowered priority, ensuring it 749920Syasuko.eckert@amd.com * happens after any "normal" event. 7510319SAndreas.Sandberg@ARM.com * 7612104Snathanael.premillieu@arm.com * Because delta notifications are scheduled at the standard priority, all 775596Sgblack@eecs.umich.edu * of those events will happen next, performing step 3 above. Once they finish, 785596Sgblack@eecs.umich.edu * if the readyEvent was scheduled above, there shouldn't be any higher 795596Sgblack@eecs.umich.edu * priority events in front of it. When it runs, it will start the first 805596Sgblack@eecs.umich.edu * evaluate phase of the first delta cycle. 818902Sandreas.hansson@arm.com * 825596Sgblack@eecs.umich.edu * DELTA CYCLE 835596Sgblack@eecs.umich.edu * 845596Sgblack@eecs.umich.edu * A delta cycle has three phases within it. 855596Sgblack@eecs.umich.edu * 1. The evaluate phase where runnable processes are allowed to run. 8610417Sandreas.hansson@arm.com * 2. The update phase where requested channel updates hapen. 877720Sgblack@eecs.umich.edu * 3. The delta notification phase where delta notifications happen. 887720Sgblack@eecs.umich.edu * 895596Sgblack@eecs.umich.edu * The readyEvent runs all three steps of the delta cycle. It first goes 905596Sgblack@eecs.umich.edu * through the list of runnable processes and executes them until the set is 9110417Sandreas.hansson@arm.com * empty, and then immediately runs the update phase. Since these are all part 9210417Sandreas.hansson@arm.com * of the same event, there's no chance for other events to intervene and 935596Sgblack@eecs.umich.edu * break the required order above. 949252Sdjordje.kovacevic@arm.com * 959252Sdjordje.kovacevic@arm.com * During the update phase above, the spec forbids any action which would make 965596Sgblack@eecs.umich.edu * a process runnable. That means that once the update phase finishes, the set 975596Sgblack@eecs.umich.edu * of runnable processes will be empty. There may, however, have been some 985596Sgblack@eecs.umich.edu * delta notifications/timeouts which will have been scheduled during either 995596Sgblack@eecs.umich.edu * the evaluate or update phase above. Those will have been accumulated in the 1005596Sgblack@eecs.umich.edu * scheduler, and are now all executed. 1015596Sgblack@eecs.umich.edu * 1025596Sgblack@eecs.umich.edu * If any processes became runnable during the delta notification phase, the 1035596Sgblack@eecs.umich.edu * readyEvent will have been scheduled and will be waiting and ready to run 1045596Sgblack@eecs.umich.edu * again, effectively starting the next delta cycle. 1055596Sgblack@eecs.umich.edu * 1065596Sgblack@eecs.umich.edu * TIMED NOTIFICATION PHASE 1075596Sgblack@eecs.umich.edu * 1085596Sgblack@eecs.umich.edu * If no processes became runnable, the event queue will continue to process 1097783SGiacomo.Gabrielli@arm.com * events until it comes across an event which represents all the timed 1109046SAli.Saidi@ARM.com * notifications which are supposed to happen at a particular time. The object 11110835Sandreas.hansson@arm.com * which tracks them will execute all those notifications, and then destroy 1129046SAli.Saidi@ARM.com * itself. If the readyEvent is now ready to run, the next delta cycle will 1137783SGiacomo.Gabrielli@arm.com * start. 1147783SGiacomo.Gabrielli@arm.com * 1157783SGiacomo.Gabrielli@arm.com * PAUSE/STOP 1167783SGiacomo.Gabrielli@arm.com * 11710835Sandreas.hansson@arm.com * To inject a pause from sc_pause which should happen after the current delta 1189046SAli.Saidi@ARM.com * cycle's delta notification phase, an event is scheduled with a lower than 1197783SGiacomo.Gabrielli@arm.com * normal priority, but higher than the readyEvent. That ensures that any 1209046SAli.Saidi@ARM.com * delta notifications which are scheduled with normal priority will happen 1219046SAli.Saidi@ARM.com * first, since those are part of the current delta cycle. Then the pause 1227783SGiacomo.Gabrielli@arm.com * event will happen before the next readyEvent which would start the next 1235596Sgblack@eecs.umich.edu * delta cycle. All of these events are scheduled for the current time, and so 1248471SGiacomo.Gabrielli@arm.com * would happen before any timed notifications went off. 1258471SGiacomo.Gabrielli@arm.com * 1269252Sdjordje.kovacevic@arm.com * To inject a stop from sc_stop, the delta cycles should stop before even the 1279252Sdjordje.kovacevic@arm.com * delta notifications have happened, but after the evaluate and update phases. 1289252Sdjordje.kovacevic@arm.com * For that, a stop event with slightly higher than normal priority will be 1299252Sdjordje.kovacevic@arm.com * scheduled so that it happens before any of the delta notification events 1309252Sdjordje.kovacevic@arm.com * which are at normal priority. 1319252Sdjordje.kovacevic@arm.com * 1329252Sdjordje.kovacevic@arm.com * MAX RUN TIME 1339527SMatt.Horsnell@arm.com * 1348471SGiacomo.Gabrielli@arm.com * When sc_start is called, it's possible to pass in a maximum time the 1358471SGiacomo.Gabrielli@arm.com * simulation should run to, at which point sc_pause is implicitly called. The 1365596Sgblack@eecs.umich.edu * simulation is supposed to run up to the latest timed notification phase 1375596Sgblack@eecs.umich.edu * which is less than or equal to the maximum time. In other words it should 1385596Sgblack@eecs.umich.edu * run timed notifications at the maximum time, but not the subsequent evaluate 1395596Sgblack@eecs.umich.edu * phase. That's implemented by scheduling an event at the max time with a 1405596Sgblack@eecs.umich.edu * priority which is lower than all the others except the ready event. Timed 1415596Sgblack@eecs.umich.edu * notifications will happen before it fires, but it will override any ready 1425596Sgblack@eecs.umich.edu * event and prevent the evaluate phase from starting. 1435596Sgblack@eecs.umich.edu */ 1445596Sgblack@eecs.umich.edu 1455596Sgblack@eecs.umich.educlass Scheduler 1465596Sgblack@eecs.umich.edu{ 1475596Sgblack@eecs.umich.edu public: 1485596Sgblack@eecs.umich.edu typedef std::list<ScEvent *> ScEvents; 1497783SGiacomo.Gabrielli@arm.com 1509532Sgeoffrey.blake@arm.com class TimeSlot : public ::Event 1519532Sgeoffrey.blake@arm.com { 1529532Sgeoffrey.blake@arm.com public: 1539532Sgeoffrey.blake@arm.com TimeSlot() : ::Event(Default_Pri, AutoDelete) {} 1547783SGiacomo.Gabrielli@arm.com 1559532Sgeoffrey.blake@arm.com ScEvents events; 1569532Sgeoffrey.blake@arm.com void process(); 1579532Sgeoffrey.blake@arm.com }; 1589532Sgeoffrey.blake@arm.com 1599532Sgeoffrey.blake@arm.com typedef std::map<Tick, TimeSlot *> TimeSlots; 1609532Sgeoffrey.blake@arm.com 1619532Sgeoffrey.blake@arm.com Scheduler(); 1629046SAli.Saidi@ARM.com ~Scheduler(); 1637783SGiacomo.Gabrielli@arm.com 1647783SGiacomo.Gabrielli@arm.com void clear(); 1657783SGiacomo.Gabrielli@arm.com 1665596Sgblack@eecs.umich.edu const std::string name() const { return "systemc_scheduler"; } 1675596Sgblack@eecs.umich.edu 1685596Sgblack@eecs.umich.edu uint64_t numCycles() { return _numCycles; } 1695596Sgblack@eecs.umich.edu Process *current() { return _current; } 1705596Sgblack@eecs.umich.edu 1715596Sgblack@eecs.umich.edu void initPhase(); 1725596Sgblack@eecs.umich.edu 17312104Snathanael.premillieu@arm.com // Register a process with the scheduler. 17412104Snathanael.premillieu@arm.com void reg(Process *p); 17512104Snathanael.premillieu@arm.com 1765596Sgblack@eecs.umich.edu // Run the next process, if there is one. 1775596Sgblack@eecs.umich.edu void yield(); 1785596Sgblack@eecs.umich.edu 1795596Sgblack@eecs.umich.edu // Put a process on the ready list. 1805596Sgblack@eecs.umich.edu void ready(Process *p); 1815596Sgblack@eecs.umich.edu 1825596Sgblack@eecs.umich.edu // Mark a process as ready if init is finished, or put it on the list of 1835596Sgblack@eecs.umich.edu // processes to be initialized. 18412104Snathanael.premillieu@arm.com void resume(Process *p); 18512104Snathanael.premillieu@arm.com 18612104Snathanael.premillieu@arm.com // Remove a process from the ready/init list if it was on one of them, and 1877783SGiacomo.Gabrielli@arm.com // return if it was. 1887783SGiacomo.Gabrielli@arm.com bool suspend(Process *p); 1897783SGiacomo.Gabrielli@arm.com 1907783SGiacomo.Gabrielli@arm.com // Schedule an update for a given channel. 1917783SGiacomo.Gabrielli@arm.com void requestUpdate(Channel *c); 1927783SGiacomo.Gabrielli@arm.com 1937783SGiacomo.Gabrielli@arm.com // Run the given process immediately, preempting whatever may be running. 1947783SGiacomo.Gabrielli@arm.com void 1957783SGiacomo.Gabrielli@arm.com runNow(Process *p) 1969382SAli.Saidi@ARM.com { 1979382SAli.Saidi@ARM.com // This function may put a process on the wrong list, ie a thread 1987783SGiacomo.Gabrielli@arm.com // the method list. That's fine since that's just a performance 1997783SGiacomo.Gabrielli@arm.com // optimization, and the important thing here is how the processes are 2007783SGiacomo.Gabrielli@arm.com // ordered. 2017783SGiacomo.Gabrielli@arm.com 2027783SGiacomo.Gabrielli@arm.com // If a process is running, schedule it/us to run again. 2039382SAli.Saidi@ARM.com if (_current) 2045596Sgblack@eecs.umich.edu readyListMethods.pushFirst(_current); 2055596Sgblack@eecs.umich.edu // Schedule p to run first. 2067848SAli.Saidi@ARM.com readyListMethods.pushFirst(p); 2077848SAli.Saidi@ARM.com yield(); 20810935Snilay@cs.wisc.edu } 2097848SAli.Saidi@ARM.com 2107848SAli.Saidi@ARM.com // Set an event queue for scheduling events. 21112104Snathanael.premillieu@arm.com void setEventQueue(EventQueue *_eq) { eq = _eq; } 2129913Ssteve.reinhardt@amd.com 21312104Snathanael.premillieu@arm.com // Get the current time according to gem5. 2149913Ssteve.reinhardt@amd.com Tick getCurTick() { return eq ? eq->getCurTick() : 0; } 2159913Ssteve.reinhardt@amd.com 2169913Ssteve.reinhardt@amd.com Tick 2179913Ssteve.reinhardt@amd.com delayed(const ::sc_core::sc_time &delay) 2189913Ssteve.reinhardt@amd.com { 2199913Ssteve.reinhardt@amd.com //XXX We're assuming the systemc time resolution is in ps. 2209913Ssteve.reinhardt@amd.com return getCurTick() + delay.value() * SimClock::Int::ps; 2219913Ssteve.reinhardt@amd.com } 2229920Syasuko.eckert@amd.com 2239920Syasuko.eckert@amd.com // For scheduling delayed/timed notifications/timeouts. 2249920Syasuko.eckert@amd.com void 2259920Syasuko.eckert@amd.com schedule(ScEvent *event, const ::sc_core::sc_time &delay) 2269913Ssteve.reinhardt@amd.com { 2279913Ssteve.reinhardt@amd.com Tick tick = delayed(delay); 2289913Ssteve.reinhardt@amd.com if (tick < getCurTick()) 2299913Ssteve.reinhardt@amd.com tick = getCurTick(); 2307848SAli.Saidi@ARM.com 2317848SAli.Saidi@ARM.com // Delta notification/timeout. 2325702Ssaidi@eecs.umich.edu if (delay.value() == 0) { 2335702Ssaidi@eecs.umich.edu event->schedule(deltas, tick); 2345596Sgblack@eecs.umich.edu if (!inEvaluate() && !inUpdate()) 23510379Sandreas.hansson@arm.com scheduleReadyEvent(); 2365702Ssaidi@eecs.umich.edu return; 2378557Sgblack@eecs.umich.edu } 2388557Sgblack@eecs.umich.edu 23911877Sbrandon.potter@amd.com // Timed notification/timeout. 2402847Sksewell@umich.edu TimeSlot *&ts = timeSlots[tick]; 2415596Sgblack@eecs.umich.edu if (!ts) { 2425596Sgblack@eecs.umich.edu ts = new TimeSlot; 2435596Sgblack@eecs.umich.edu schedule(ts, tick); 2445596Sgblack@eecs.umich.edu } 2455596Sgblack@eecs.umich.edu event->schedule(ts->events, tick); 2465596Sgblack@eecs.umich.edu } 2475596Sgblack@eecs.umich.edu 2485596Sgblack@eecs.umich.edu // For descheduling delayed/timed notifications/timeouts. 2495596Sgblack@eecs.umich.edu void 2505596Sgblack@eecs.umich.edu deschedule(ScEvent *event) 2515596Sgblack@eecs.umich.edu { 2525596Sgblack@eecs.umich.edu ScEvents *on = event->scheduledOn(); 2535596Sgblack@eecs.umich.edu 25410319SAndreas.Sandberg@ARM.com if (on == &deltas) { 2555596Sgblack@eecs.umich.edu event->deschedule(); 2565596Sgblack@eecs.umich.edu return; 2575596Sgblack@eecs.umich.edu } 2585596Sgblack@eecs.umich.edu 2595596Sgblack@eecs.umich.edu // Timed notification/timeout. 2605596Sgblack@eecs.umich.edu auto tsit = timeSlots.find(event->when()); 2615596Sgblack@eecs.umich.edu panic_if(tsit == timeSlots.end(), 2625596Sgblack@eecs.umich.edu "Descheduling event at time with no events."); 2635596Sgblack@eecs.umich.edu TimeSlot *ts = tsit->second; 2645596Sgblack@eecs.umich.edu ScEvents &events = ts->events; 2655596Sgblack@eecs.umich.edu assert(on == &events); 2665596Sgblack@eecs.umich.edu event->deschedule(); 2675596Sgblack@eecs.umich.edu 2685596Sgblack@eecs.umich.edu // If no more events are happening at this time slot, get rid of it. 26910319SAndreas.Sandberg@ARM.com if (events.empty()) { 2709920Syasuko.eckert@amd.com deschedule(ts); 2719920Syasuko.eckert@amd.com timeSlots.erase(tsit); 2729920Syasuko.eckert@amd.com } 2739920Syasuko.eckert@amd.com } 2745596Sgblack@eecs.umich.edu 2755596Sgblack@eecs.umich.edu void 2765596Sgblack@eecs.umich.edu completeTimeSlot(TimeSlot *ts) 27710319SAndreas.Sandberg@ARM.com { 2785596Sgblack@eecs.umich.edu _changeStamp++; 2795596Sgblack@eecs.umich.edu assert(ts == timeSlots.begin()->second); 2805596Sgblack@eecs.umich.edu timeSlots.erase(timeSlots.begin()); 2815596Sgblack@eecs.umich.edu if (!runToTime && starved()) 2825596Sgblack@eecs.umich.edu scheduleStarvationEvent(); 2835596Sgblack@eecs.umich.edu } 2845596Sgblack@eecs.umich.edu 2855596Sgblack@eecs.umich.edu // Pending activity ignores gem5 activity, much like how a systemc 2865596Sgblack@eecs.umich.edu // simulation wouldn't know about asynchronous external events (socket IO 2875596Sgblack@eecs.umich.edu // for instance) that might happen before time advances in a pure 2885596Sgblack@eecs.umich.edu // systemc simulation. Also the spec lists what specific types of pending 2895596Sgblack@eecs.umich.edu // activity needs to be counted, which obviously doesn't include gem5 2905596Sgblack@eecs.umich.edu // events. 2915596Sgblack@eecs.umich.edu 2925596Sgblack@eecs.umich.edu // Return whether there's pending systemc activity at this time. 2935596Sgblack@eecs.umich.edu bool 2945596Sgblack@eecs.umich.edu pendingCurr() 2955596Sgblack@eecs.umich.edu { 29610319SAndreas.Sandberg@ARM.com return !readyListMethods.empty() || !readyListThreads.empty() || 2979920Syasuko.eckert@amd.com !updateList.empty() || !deltas.empty(); 2989920Syasuko.eckert@amd.com } 2999920Syasuko.eckert@amd.com 3009920Syasuko.eckert@amd.com // Return whether there are pending timed notifications or timeouts. 3019920Syasuko.eckert@amd.com bool 3025596Sgblack@eecs.umich.edu pendingFuture() 30312104Snathanael.premillieu@arm.com { 3045596Sgblack@eecs.umich.edu return !timeSlots.empty(); 3055596Sgblack@eecs.umich.edu } 3065596Sgblack@eecs.umich.edu 3075596Sgblack@eecs.umich.edu // Return how many ticks there are until the first pending event, if any. 3085596Sgblack@eecs.umich.edu Tick 30912104Snathanael.premillieu@arm.com timeToPending() 3105596Sgblack@eecs.umich.edu { 3115596Sgblack@eecs.umich.edu if (pendingCurr()) 3125596Sgblack@eecs.umich.edu return 0; 3135596Sgblack@eecs.umich.edu if (pendingFuture()) 3145596Sgblack@eecs.umich.edu return timeSlots.begin()->first - getCurTick(); 3155596Sgblack@eecs.umich.edu return MaxTick - getCurTick(); 3165596Sgblack@eecs.umich.edu } 3175596Sgblack@eecs.umich.edu 3185596Sgblack@eecs.umich.edu // Run scheduled channel updates. 3195596Sgblack@eecs.umich.edu void runUpdate(); 3205596Sgblack@eecs.umich.edu 3215596Sgblack@eecs.umich.edu // Run delta events. 3225596Sgblack@eecs.umich.edu void runDelta(); 3235596Sgblack@eecs.umich.edu 3245596Sgblack@eecs.umich.edu void setScMainFiber(Fiber *sc_main) { scMain = sc_main; } 3255596Sgblack@eecs.umich.edu 3265596Sgblack@eecs.umich.edu void start(Tick max_tick, bool run_to_time); 3275596Sgblack@eecs.umich.edu void oneCycle(); 3285596Sgblack@eecs.umich.edu 3295596Sgblack@eecs.umich.edu void schedulePause(); 3305596Sgblack@eecs.umich.edu void scheduleStop(bool finish_delta); 3315596Sgblack@eecs.umich.edu 3325596Sgblack@eecs.umich.edu enum Status 3335596Sgblack@eecs.umich.edu { 3345596Sgblack@eecs.umich.edu StatusOther = 0, 3355596Sgblack@eecs.umich.edu StatusEvaluate, 3365596Sgblack@eecs.umich.edu StatusUpdate, 337 StatusDelta, 338 StatusTiming, 339 StatusPaused, 340 StatusStopped 341 }; 342 343 bool elaborationDone() { return _elaborationDone; } 344 void elaborationDone(bool b) { _elaborationDone = b; } 345 346 bool paused() { return status() == StatusPaused; } 347 bool stopped() { return status() == StatusStopped; } 348 bool inEvaluate() { return status() == StatusEvaluate; } 349 bool inUpdate() { return status() == StatusUpdate; } 350 bool inDelta() { return status() == StatusDelta; } 351 bool inTiming() { return status() == StatusTiming; } 352 353 uint64_t changeStamp() { return _changeStamp; } 354 355 void throwToScMain(const ::sc_core::sc_report *r=nullptr); 356 357 Status status() { return _status; } 358 void status(Status s) { _status = s; } 359 360 private: 361 typedef const EventBase::Priority Priority; 362 static Priority DefaultPriority = EventBase::Default_Pri; 363 364 static Priority StopPriority = DefaultPriority - 1; 365 static Priority PausePriority = DefaultPriority + 1; 366 static Priority MaxTickPriority = DefaultPriority + 2; 367 static Priority ReadyPriority = DefaultPriority + 3; 368 static Priority StarvationPriority = ReadyPriority; 369 370 EventQueue *eq; 371 372 // For gem5 style events. 373 void 374 schedule(::Event *event, Tick tick) 375 { 376 if (initDone) 377 eq->schedule(event, tick); 378 else 379 eventsToSchedule[event] = tick; 380 } 381 382 void schedule(::Event *event) { schedule(event, getCurTick()); } 383 384 void 385 deschedule(::Event *event) 386 { 387 if (initDone) 388 eq->deschedule(event); 389 else 390 eventsToSchedule.erase(event); 391 } 392 393 ScEvents deltas; 394 TimeSlots timeSlots; 395 396 Process * 397 getNextReady() 398 { 399 Process *p = readyListMethods.getNext(); 400 return p ? p : readyListThreads.getNext(); 401 } 402 403 void runReady(); 404 EventWrapper<Scheduler, &Scheduler::runReady> readyEvent; 405 void scheduleReadyEvent(); 406 407 void pause(); 408 void stop(); 409 EventWrapper<Scheduler, &Scheduler::pause> pauseEvent; 410 EventWrapper<Scheduler, &Scheduler::stop> stopEvent; 411 412 Fiber *scMain; 413 const ::sc_core::sc_report *_throwToScMain; 414 415 bool 416 starved() 417 { 418 return (readyListMethods.empty() && readyListThreads.empty() && 419 updateList.empty() && deltas.empty() && 420 (timeSlots.empty() || timeSlots.begin()->first > maxTick) && 421 initList.empty()); 422 } 423 EventWrapper<Scheduler, &Scheduler::pause> starvationEvent; 424 void scheduleStarvationEvent(); 425 426 bool _elaborationDone; 427 bool _started; 428 bool _stopNow; 429 430 Status _status; 431 432 Tick maxTick; 433 Tick lastReadyTick; 434 void 435 maxTickFunc() 436 { 437 if (lastReadyTick != getCurTick()) 438 _changeStamp++; 439 pause(); 440 } 441 EventWrapper<Scheduler, &Scheduler::maxTickFunc> maxTickEvent; 442 443 uint64_t _numCycles; 444 uint64_t _changeStamp; 445 446 Process *_current; 447 448 bool initDone; 449 bool runToTime; 450 bool runOnce; 451 452 ProcessList initList; 453 454 ProcessList readyListMethods; 455 ProcessList readyListThreads; 456 457 ChannelList updateList; 458 459 std::map<::Event *, Tick> eventsToSchedule; 460}; 461 462extern Scheduler scheduler; 463 464inline void 465Scheduler::TimeSlot::process() 466{ 467 scheduler.status(StatusTiming); 468 469 try { 470 while (!events.empty()) 471 events.front()->run(); 472 } catch (...) { 473 if (events.empty()) 474 scheduler.completeTimeSlot(this); 475 else 476 scheduler.schedule(this); 477 scheduler.throwToScMain(); 478 } 479 480 scheduler.status(StatusOther); 481 scheduler.completeTimeSlot(this); 482} 483 484const ::sc_core::sc_report *reportifyException(); 485 486} // namespace sc_gem5 487 488#endif // __SYSTEMC_CORE_SCHEDULER_H__ 489