scheduler.hh revision 13245:c666c5d4996b
15647Sgblack@eecs.umich.edu/* 25647Sgblack@eecs.umich.edu * Copyright 2018 Google, Inc. 35647Sgblack@eecs.umich.edu * 45647Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 57087Snate@binkert.org * modification, are permitted provided that the following conditions are 67087Snate@binkert.org * met: redistributions of source code must retain the above copyright 77087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 87087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 97087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 107087Snate@binkert.org * documentation and/or other materials provided with the distribution; 117087Snate@binkert.org * neither the name of the copyright holders nor the names of its 127087Snate@binkert.org * contributors may be used to endorse or promote products derived from 135647Sgblack@eecs.umich.edu * this software without specific prior written permission. 147087Snate@binkert.org * 157087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 167087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 177087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 187087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 197087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 207087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 217087Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 225647Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 237087Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 245647Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 255647Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265647Sgblack@eecs.umich.edu * 275647Sgblack@eecs.umich.edu * Authors: Gabe Black 285647Sgblack@eecs.umich.edu */ 295647Sgblack@eecs.umich.edu 305647Sgblack@eecs.umich.edu#ifndef __SYSTEMC_CORE_SCHEDULER_HH__ 315647Sgblack@eecs.umich.edu#define __SYSTEMC_CORE_SCHEDULER_HH__ 325647Sgblack@eecs.umich.edu 335647Sgblack@eecs.umich.edu#include <functional> 345647Sgblack@eecs.umich.edu#include <map> 355647Sgblack@eecs.umich.edu#include <set> 365647Sgblack@eecs.umich.edu#include <vector> 375647Sgblack@eecs.umich.edu 385647Sgblack@eecs.umich.edu#include "base/logging.hh" 395647Sgblack@eecs.umich.edu#include "sim/core.hh" 405648Sgblack@eecs.umich.edu#include "sim/eventq.hh" 415647Sgblack@eecs.umich.edu#include "systemc/core/channel.hh" 425654Sgblack@eecs.umich.edu#include "systemc/core/list.hh" 435647Sgblack@eecs.umich.edu#include "systemc/core/process.hh" 446137Sgblack@eecs.umich.edu#include "systemc/core/sched_event.hh" 456137Sgblack@eecs.umich.edu 466137Sgblack@eecs.umich.educlass Fiber; 475654Sgblack@eecs.umich.edu 486046Sgblack@eecs.umich.edunamespace sc_gem5 495647Sgblack@eecs.umich.edu{ 505648Sgblack@eecs.umich.edu 515648Sgblack@eecs.umich.educlass TraceFile; 525647Sgblack@eecs.umich.edu 535647Sgblack@eecs.umich.edutypedef NodeList<Process> ProcessList; 545647Sgblack@eecs.umich.edutypedef NodeList<Channel> ChannelList; 555647Sgblack@eecs.umich.edu 565647Sgblack@eecs.umich.edu/* 575647Sgblack@eecs.umich.edu * The scheduler supports three different mechanisms, the initialization phase, 585647Sgblack@eecs.umich.edu * delta cycles, and timed notifications. 595647Sgblack@eecs.umich.edu * 605647Sgblack@eecs.umich.edu * INITIALIZATION PHASE 615648Sgblack@eecs.umich.edu * 625647Sgblack@eecs.umich.edu * The initialization phase has three parts: 635648Sgblack@eecs.umich.edu * 1. Run requested channel updates. 645648Sgblack@eecs.umich.edu * 2. Make processes which need to initialize runnable (methods and threads 655648Sgblack@eecs.umich.edu * which didn't have dont_initialize called on them). 665648Sgblack@eecs.umich.edu * 3. Process delta notifications. 675648Sgblack@eecs.umich.edu * 685648Sgblack@eecs.umich.edu * First, the Kernel SimObject calls the update() method during its startup() 695648Sgblack@eecs.umich.edu * callback which handles the requested channel updates. The Kernel also 705648Sgblack@eecs.umich.edu * schedules an event to be run at time 0 with a slightly elevated priority 715648Sgblack@eecs.umich.edu * so that it happens before any "normal" event. 725648Sgblack@eecs.umich.edu * 735648Sgblack@eecs.umich.edu * When that t0 event happens, it calls the schedulers prepareForInit method 745648Sgblack@eecs.umich.edu * which performs step 2 above. That indirectly causes the scheduler's 755648Sgblack@eecs.umich.edu * readyEvent to be scheduled with slightly lowered priority, ensuring it 765648Sgblack@eecs.umich.edu * happens after any "normal" event. 775648Sgblack@eecs.umich.edu * 785648Sgblack@eecs.umich.edu * Because delta notifications are scheduled at the standard priority, all 795648Sgblack@eecs.umich.edu * of those events will happen next, performing step 3 above. Once they finish, 805648Sgblack@eecs.umich.edu * if the readyEvent was scheduled above, there shouldn't be any higher 815648Sgblack@eecs.umich.edu * priority events in front of it. When it runs, it will start the first 825648Sgblack@eecs.umich.edu * evaluate phase of the first delta cycle. 835648Sgblack@eecs.umich.edu * 845648Sgblack@eecs.umich.edu * DELTA CYCLE 855648Sgblack@eecs.umich.edu * 865648Sgblack@eecs.umich.edu * A delta cycle has three phases within it. 875648Sgblack@eecs.umich.edu * 1. The evaluate phase where runnable processes are allowed to run. 885648Sgblack@eecs.umich.edu * 2. The update phase where requested channel updates hapen. 895648Sgblack@eecs.umich.edu * 3. The delta notification phase where delta notifications happen. 905648Sgblack@eecs.umich.edu * 915648Sgblack@eecs.umich.edu * The readyEvent runs all three steps of the delta cycle. It first goes 925648Sgblack@eecs.umich.edu * through the list of runnable processes and executes them until the set is 935648Sgblack@eecs.umich.edu * empty, and then immediately runs the update phase. Since these are all part 945648Sgblack@eecs.umich.edu * of the same event, there's no chance for other events to intervene and 955648Sgblack@eecs.umich.edu * break the required order above. 965648Sgblack@eecs.umich.edu * 975648Sgblack@eecs.umich.edu * During the update phase above, the spec forbids any action which would make 985648Sgblack@eecs.umich.edu * a process runnable. That means that once the update phase finishes, the set 995648Sgblack@eecs.umich.edu * of runnable processes will be empty. There may, however, have been some 1005648Sgblack@eecs.umich.edu * delta notifications/timeouts which will have been scheduled during either 1015648Sgblack@eecs.umich.edu * the evaluate or update phase above. Those will have been accumulated in the 1025648Sgblack@eecs.umich.edu * scheduler, and are now all executed. 1035648Sgblack@eecs.umich.edu * 1045648Sgblack@eecs.umich.edu * If any processes became runnable during the delta notification phase, the 1055648Sgblack@eecs.umich.edu * readyEvent will have been scheduled and will be waiting and ready to run 1065648Sgblack@eecs.umich.edu * again, effectively starting the next delta cycle. 1075648Sgblack@eecs.umich.edu * 1085648Sgblack@eecs.umich.edu * TIMED NOTIFICATION PHASE 1095648Sgblack@eecs.umich.edu * 1105648Sgblack@eecs.umich.edu * If no processes became runnable, the event queue will continue to process 1115648Sgblack@eecs.umich.edu * events until it comes across an event which represents all the timed 1125648Sgblack@eecs.umich.edu * notifications which are supposed to happen at a particular time. The object 1135648Sgblack@eecs.umich.edu * which tracks them will execute all those notifications, and then destroy 1145648Sgblack@eecs.umich.edu * itself. If the readyEvent is now ready to run, the next delta cycle will 1155648Sgblack@eecs.umich.edu * start. 1165648Sgblack@eecs.umich.edu * 1175648Sgblack@eecs.umich.edu * PAUSE/STOP 1185648Sgblack@eecs.umich.edu * 1195648Sgblack@eecs.umich.edu * To inject a pause from sc_pause which should happen after the current delta 1205648Sgblack@eecs.umich.edu * cycle's delta notification phase, an event is scheduled with a lower than 1215648Sgblack@eecs.umich.edu * normal priority, but higher than the readyEvent. That ensures that any 1225648Sgblack@eecs.umich.edu * delta notifications which are scheduled with normal priority will happen 1235648Sgblack@eecs.umich.edu * first, since those are part of the current delta cycle. Then the pause 1245648Sgblack@eecs.umich.edu * event will happen before the next readyEvent which would start the next 1255648Sgblack@eecs.umich.edu * delta cycle. All of these events are scheduled for the current time, and so 1265648Sgblack@eecs.umich.edu * would happen before any timed notifications went off. 1275648Sgblack@eecs.umich.edu * 1285648Sgblack@eecs.umich.edu * To inject a stop from sc_stop, the delta cycles should stop before even the 1295648Sgblack@eecs.umich.edu * delta notifications have happened, but after the evaluate and update phases. 1305648Sgblack@eecs.umich.edu * For that, a stop event with slightly higher than normal priority will be 1315648Sgblack@eecs.umich.edu * scheduled so that it happens before any of the delta notification events 1325648Sgblack@eecs.umich.edu * which are at normal priority. 1335648Sgblack@eecs.umich.edu * 1345648Sgblack@eecs.umich.edu * MAX RUN TIME 1355648Sgblack@eecs.umich.edu * 1365648Sgblack@eecs.umich.edu * When sc_start is called, it's possible to pass in a maximum time the 1375648Sgblack@eecs.umich.edu * simulation should run to, at which point sc_pause is implicitly called. The 1385648Sgblack@eecs.umich.edu * simulation is supposed to run up to the latest timed notification phase 1395648Sgblack@eecs.umich.edu * which is less than or equal to the maximum time. In other words it should 1405648Sgblack@eecs.umich.edu * run timed notifications at the maximum time, but not the subsequent evaluate 1415648Sgblack@eecs.umich.edu * phase. That's implemented by scheduling an event at the max time with a 1425648Sgblack@eecs.umich.edu * priority which is lower than all the others except the ready event. Timed 1435648Sgblack@eecs.umich.edu * notifications will happen before it fires, but it will override any ready 1445648Sgblack@eecs.umich.edu * event and prevent the evaluate phase from starting. 1455648Sgblack@eecs.umich.edu */ 1465648Sgblack@eecs.umich.edu 1475648Sgblack@eecs.umich.educlass Scheduler 1485648Sgblack@eecs.umich.edu{ 1495648Sgblack@eecs.umich.edu public: 1505648Sgblack@eecs.umich.edu typedef std::list<ScEvent *> ScEvents; 1515648Sgblack@eecs.umich.edu 1525648Sgblack@eecs.umich.edu class TimeSlot : public ::Event 1535648Sgblack@eecs.umich.edu { 1545648Sgblack@eecs.umich.edu public: 1555648Sgblack@eecs.umich.edu TimeSlot() : ::Event(Default_Pri, AutoDelete) {} 1565648Sgblack@eecs.umich.edu 1575648Sgblack@eecs.umich.edu ScEvents events; 1585648Sgblack@eecs.umich.edu void process(); 1595648Sgblack@eecs.umich.edu }; 1605648Sgblack@eecs.umich.edu 1615648Sgblack@eecs.umich.edu typedef std::map<Tick, TimeSlot *> TimeSlots; 1625648Sgblack@eecs.umich.edu 1635648Sgblack@eecs.umich.edu Scheduler(); 1645648Sgblack@eecs.umich.edu ~Scheduler(); 1655648Sgblack@eecs.umich.edu 1665648Sgblack@eecs.umich.edu void clear(); 1675648Sgblack@eecs.umich.edu 1685648Sgblack@eecs.umich.edu const std::string name() const { return "systemc_scheduler"; } 1695648Sgblack@eecs.umich.edu 1705648Sgblack@eecs.umich.edu uint64_t numCycles() { return _numCycles; } 1715648Sgblack@eecs.umich.edu Process *current() { return _current; } 1725648Sgblack@eecs.umich.edu 1735648Sgblack@eecs.umich.edu void initPhase(); 1745648Sgblack@eecs.umich.edu 1755648Sgblack@eecs.umich.edu // Register a process with the scheduler. 1765648Sgblack@eecs.umich.edu void reg(Process *p); 1775648Sgblack@eecs.umich.edu 1785648Sgblack@eecs.umich.edu // Run the next process, if there is one. 1795648Sgblack@eecs.umich.edu void yield(); 1805648Sgblack@eecs.umich.edu 1815648Sgblack@eecs.umich.edu // Put a process on the ready list. 1825648Sgblack@eecs.umich.edu void ready(Process *p); 1835648Sgblack@eecs.umich.edu 1845648Sgblack@eecs.umich.edu // Mark a process as ready if init is finished, or put it on the list of 1855648Sgblack@eecs.umich.edu // processes to be initialized. 1865648Sgblack@eecs.umich.edu void resume(Process *p); 1875648Sgblack@eecs.umich.edu 1885648Sgblack@eecs.umich.edu // Remove a process from the ready/init list if it was on one of them, and 1895648Sgblack@eecs.umich.edu // return if it was. 1905648Sgblack@eecs.umich.edu bool suspend(Process *p); 1915648Sgblack@eecs.umich.edu 1925648Sgblack@eecs.umich.edu // Schedule an update for a given channel. 1935648Sgblack@eecs.umich.edu void requestUpdate(Channel *c); 1945648Sgblack@eecs.umich.edu 1955648Sgblack@eecs.umich.edu // Run the given process immediately, preempting whatever may be running. 1965648Sgblack@eecs.umich.edu void 1975648Sgblack@eecs.umich.edu runNow(Process *p) 1985648Sgblack@eecs.umich.edu { 1995648Sgblack@eecs.umich.edu // This function may put a process on the wrong list, ie a thread 2005648Sgblack@eecs.umich.edu // the method list. That's fine since that's just a performance 2015648Sgblack@eecs.umich.edu // optimization, and the important thing here is how the processes are 2025648Sgblack@eecs.umich.edu // ordered. 2035648Sgblack@eecs.umich.edu 2045648Sgblack@eecs.umich.edu // If a process is running, schedule it/us to run again. 2055648Sgblack@eecs.umich.edu if (_current) 2065649Sgblack@eecs.umich.edu readyListMethods.pushFirst(_current); 2075649Sgblack@eecs.umich.edu // Schedule p to run first. 2085649Sgblack@eecs.umich.edu readyListMethods.pushFirst(p); 2095648Sgblack@eecs.umich.edu yield(); 2105898Sgblack@eecs.umich.edu } 2115648Sgblack@eecs.umich.edu 2125648Sgblack@eecs.umich.edu // Set an event queue for scheduling events. 2135648Sgblack@eecs.umich.edu void setEventQueue(EventQueue *_eq) { eq = _eq; } 2145648Sgblack@eecs.umich.edu 2155648Sgblack@eecs.umich.edu // Get the current time according to gem5. 2165648Sgblack@eecs.umich.edu Tick getCurTick() { return eq ? eq->getCurTick() : 0; } 2175648Sgblack@eecs.umich.edu 2185648Sgblack@eecs.umich.edu Tick 2195648Sgblack@eecs.umich.edu delayed(const ::sc_core::sc_time &delay) 2205648Sgblack@eecs.umich.edu { 2215648Sgblack@eecs.umich.edu //XXX We're assuming the systemc time resolution is in ps. 2225648Sgblack@eecs.umich.edu return getCurTick() + delay.value() * SimClock::Int::ps; 2235648Sgblack@eecs.umich.edu } 2245649Sgblack@eecs.umich.edu 2255649Sgblack@eecs.umich.edu // For scheduling delayed/timed notifications/timeouts. 2265649Sgblack@eecs.umich.edu void 2275648Sgblack@eecs.umich.edu schedule(ScEvent *event, const ::sc_core::sc_time &delay) 2285898Sgblack@eecs.umich.edu { 2295648Sgblack@eecs.umich.edu Tick tick = delayed(delay); 2305647Sgblack@eecs.umich.edu if (tick < getCurTick()) 2315691Sgblack@eecs.umich.edu tick = getCurTick(); 2325691Sgblack@eecs.umich.edu 2335691Sgblack@eecs.umich.edu // Delta notification/timeout. 2345691Sgblack@eecs.umich.edu if (delay.value() == 0) { 2355691Sgblack@eecs.umich.edu event->schedule(deltas, tick); 2365691Sgblack@eecs.umich.edu if (!inEvaluate() && !inUpdate()) 2375691Sgblack@eecs.umich.edu scheduleReadyEvent(); 2385691Sgblack@eecs.umich.edu return; 2395691Sgblack@eecs.umich.edu } 2405691Sgblack@eecs.umich.edu 2415691Sgblack@eecs.umich.edu // Timed notification/timeout. 2425691Sgblack@eecs.umich.edu TimeSlot *&ts = timeSlots[tick]; 2435691Sgblack@eecs.umich.edu if (!ts) { 2445691Sgblack@eecs.umich.edu ts = new TimeSlot; 2455691Sgblack@eecs.umich.edu schedule(ts, tick); 2465691Sgblack@eecs.umich.edu } 2475691Sgblack@eecs.umich.edu event->schedule(ts->events, tick); 2485691Sgblack@eecs.umich.edu } 2495691Sgblack@eecs.umich.edu 2505691Sgblack@eecs.umich.edu // For descheduling delayed/timed notifications/timeouts. 2515691Sgblack@eecs.umich.edu void 2525691Sgblack@eecs.umich.edu deschedule(ScEvent *event) 2535691Sgblack@eecs.umich.edu { 2545691Sgblack@eecs.umich.edu ScEvents *on = event->scheduledOn(); 2555691Sgblack@eecs.umich.edu 2565691Sgblack@eecs.umich.edu if (on == &deltas) { 2575691Sgblack@eecs.umich.edu event->deschedule(); 2585691Sgblack@eecs.umich.edu return; 2595691Sgblack@eecs.umich.edu } 2605691Sgblack@eecs.umich.edu 2615691Sgblack@eecs.umich.edu // Timed notification/timeout. 2625691Sgblack@eecs.umich.edu auto tsit = timeSlots.find(event->when()); 2635691Sgblack@eecs.umich.edu panic_if(tsit == timeSlots.end(), 2645691Sgblack@eecs.umich.edu "Descheduling event at time with no events."); 2655691Sgblack@eecs.umich.edu TimeSlot *ts = tsit->second; 2665691Sgblack@eecs.umich.edu ScEvents &events = ts->events; 2675691Sgblack@eecs.umich.edu assert(on == &events); 2685691Sgblack@eecs.umich.edu event->deschedule(); 2695691Sgblack@eecs.umich.edu 2706066Sgblack@eecs.umich.edu // If no more events are happening at this time slot, get rid of it. 2716066Sgblack@eecs.umich.edu if (events.empty()) { 2726050Sgblack@eecs.umich.edu deschedule(ts); 2736050Sgblack@eecs.umich.edu timeSlots.erase(tsit); 2745691Sgblack@eecs.umich.edu } 2755691Sgblack@eecs.umich.edu } 2765811Sgblack@eecs.umich.edu 2775691Sgblack@eecs.umich.edu void 2785647Sgblack@eecs.umich.edu completeTimeSlot(TimeSlot *ts) 2796041Sgblack@eecs.umich.edu { 2806041Sgblack@eecs.umich.edu _changeStamp++; 2816041Sgblack@eecs.umich.edu assert(ts == timeSlots.begin()->second); 2826041Sgblack@eecs.umich.edu timeSlots.erase(timeSlots.begin()); 2836136Sgblack@eecs.umich.edu if (!runToTime && starved()) 2846136Sgblack@eecs.umich.edu scheduleStarvationEvent(); 2856136Sgblack@eecs.umich.edu scheduleTimeAdvancesEvent(); 2866136Sgblack@eecs.umich.edu } 2876136Sgblack@eecs.umich.edu 2886041Sgblack@eecs.umich.edu // Pending activity ignores gem5 activity, much like how a systemc 2896136Sgblack@eecs.umich.edu // simulation wouldn't know about asynchronous external events (socket IO 2906136Sgblack@eecs.umich.edu // for instance) that might happen before time advances in a pure 2916041Sgblack@eecs.umich.edu // systemc simulation. Also the spec lists what specific types of pending 2926041Sgblack@eecs.umich.edu // activity needs to be counted, which obviously doesn't include gem5 2936041Sgblack@eecs.umich.edu // events. 2946137Sgblack@eecs.umich.edu 2956137Sgblack@eecs.umich.edu // Return whether there's pending systemc activity at this time. 2966137Sgblack@eecs.umich.edu bool 2976137Sgblack@eecs.umich.edu pendingCurr() 2986137Sgblack@eecs.umich.edu { 2996137Sgblack@eecs.umich.edu return !readyListMethods.empty() || !readyListThreads.empty() || 3006137Sgblack@eecs.umich.edu !updateList.empty() || !deltas.empty(); 3016137Sgblack@eecs.umich.edu } 3026137Sgblack@eecs.umich.edu 3036137Sgblack@eecs.umich.edu // Return whether there are pending timed notifications or timeouts. 3045651Sgblack@eecs.umich.edu bool 3055651Sgblack@eecs.umich.edu pendingFuture() 3065651Sgblack@eecs.umich.edu { 3076136Sgblack@eecs.umich.edu return !timeSlots.empty(); 3085651Sgblack@eecs.umich.edu } 3095651Sgblack@eecs.umich.edu 3105651Sgblack@eecs.umich.edu // Return how many ticks there are until the first pending event, if any. 3115651Sgblack@eecs.umich.edu Tick 3125654Sgblack@eecs.umich.edu timeToPending() 3135654Sgblack@eecs.umich.edu { 3145654Sgblack@eecs.umich.edu if (pendingCurr()) 3155654Sgblack@eecs.umich.edu return 0; 3165697Snate@binkert.org if (pendingFuture()) 3175655Sgblack@eecs.umich.edu return timeSlots.begin()->first - getCurTick(); 3185691Sgblack@eecs.umich.edu return MaxTick - getCurTick(); 3195691Sgblack@eecs.umich.edu } 3205654Sgblack@eecs.umich.edu 3215651Sgblack@eecs.umich.edu // Run scheduled channel updates. 3225651Sgblack@eecs.umich.edu void runUpdate(); 3235651Sgblack@eecs.umich.edu 3245651Sgblack@eecs.umich.edu // Run delta events. 3255651Sgblack@eecs.umich.edu void runDelta(); 3265651Sgblack@eecs.umich.edu 3276064Sgblack@eecs.umich.edu void setScMainFiber(Fiber *sc_main) { scMain = sc_main; } 3285651Sgblack@eecs.umich.edu 3295651Sgblack@eecs.umich.edu void start(Tick max_tick, bool run_to_time); 3305651Sgblack@eecs.umich.edu void oneCycle(); 3315651Sgblack@eecs.umich.edu 3326065Sgblack@eecs.umich.edu void schedulePause(); 3336065Sgblack@eecs.umich.edu void scheduleStop(bool finish_delta); 3346065Sgblack@eecs.umich.edu 3356065Sgblack@eecs.umich.edu enum Status 3366065Sgblack@eecs.umich.edu { 3376069Sgblack@eecs.umich.edu StatusOther = 0, 3386069Sgblack@eecs.umich.edu StatusEvaluate, 3396069Sgblack@eecs.umich.edu StatusUpdate, 3406069Sgblack@eecs.umich.edu StatusDelta, 3416069Sgblack@eecs.umich.edu StatusTiming, 3426069Sgblack@eecs.umich.edu StatusPaused, 3436065Sgblack@eecs.umich.edu StatusStopped 3446065Sgblack@eecs.umich.edu }; 3456065Sgblack@eecs.umich.edu 3466065Sgblack@eecs.umich.edu bool elaborationDone() { return _elaborationDone; } 3476065Sgblack@eecs.umich.edu void elaborationDone(bool b) { _elaborationDone = b; } 3486065Sgblack@eecs.umich.edu 3496065Sgblack@eecs.umich.edu bool paused() { return status() == StatusPaused; } 3506041Sgblack@eecs.umich.edu bool stopped() { return status() == StatusStopped; } 3516041Sgblack@eecs.umich.edu bool inEvaluate() { return status() == StatusEvaluate; } 3526041Sgblack@eecs.umich.edu bool inUpdate() { return status() == StatusUpdate; } 3536041Sgblack@eecs.umich.edu bool inDelta() { return status() == StatusDelta; } 3546136Sgblack@eecs.umich.edu bool inTiming() { return status() == StatusTiming; } 3556136Sgblack@eecs.umich.edu 3566136Sgblack@eecs.umich.edu uint64_t changeStamp() { return _changeStamp; } 3576061Sgblack@eecs.umich.edu 3586061Sgblack@eecs.umich.edu void throwToScMain(const ::sc_core::sc_report *r=nullptr); 3596041Sgblack@eecs.umich.edu 3606041Sgblack@eecs.umich.edu Status status() { return _status; } 3616041Sgblack@eecs.umich.edu void status(Status s) { _status = s; } 3626041Sgblack@eecs.umich.edu 3636041Sgblack@eecs.umich.edu void registerTraceFile(TraceFile *tf) { traceFiles.insert(tf); } 3646041Sgblack@eecs.umich.edu void unregisterTraceFile(TraceFile *tf) { traceFiles.erase(tf); } 3656041Sgblack@eecs.umich.edu 3666136Sgblack@eecs.umich.edu private: 3676136Sgblack@eecs.umich.edu typedef const EventBase::Priority Priority; 3686136Sgblack@eecs.umich.edu static Priority DefaultPriority = EventBase::Default_Pri; 3696041Sgblack@eecs.umich.edu 3706041Sgblack@eecs.umich.edu static Priority StopPriority = DefaultPriority - 1; 3716041Sgblack@eecs.umich.edu static Priority PausePriority = DefaultPriority + 1; 3725647Sgblack@eecs.umich.edu static Priority MaxTickPriority = DefaultPriority + 2; 3735648Sgblack@eecs.umich.edu static Priority ReadyPriority = DefaultPriority + 3; 3745647Sgblack@eecs.umich.edu static Priority StarvationPriority = ReadyPriority; 3755647Sgblack@eecs.umich.edu static Priority TimeAdvancesPriority = EventBase::Maximum_Pri; 3765647Sgblack@eecs.umich.edu 3775647Sgblack@eecs.umich.edu EventQueue *eq; 3785647Sgblack@eecs.umich.edu 3795647Sgblack@eecs.umich.edu // For gem5 style events. 3805647Sgblack@eecs.umich.edu void 3815647Sgblack@eecs.umich.edu schedule(::Event *event, Tick tick) 3825647Sgblack@eecs.umich.edu { 3835647Sgblack@eecs.umich.edu if (initDone) 3845647Sgblack@eecs.umich.edu eq->schedule(event, tick); 3855647Sgblack@eecs.umich.edu else 3865647Sgblack@eecs.umich.edu eventsToSchedule[event] = tick; 3875647Sgblack@eecs.umich.edu } 3885647Sgblack@eecs.umich.edu 3895647Sgblack@eecs.umich.edu void schedule(::Event *event) { schedule(event, getCurTick()); } 3905647Sgblack@eecs.umich.edu 3915848Sgblack@eecs.umich.edu void 3925848Sgblack@eecs.umich.edu deschedule(::Event *event) 3935848Sgblack@eecs.umich.edu { 3945848Sgblack@eecs.umich.edu if (initDone) 3955848Sgblack@eecs.umich.edu eq->deschedule(event); 3965848Sgblack@eecs.umich.edu else 3975848Sgblack@eecs.umich.edu eventsToSchedule.erase(event); 3985848Sgblack@eecs.umich.edu } 3995848Sgblack@eecs.umich.edu 4005848Sgblack@eecs.umich.edu ScEvents deltas; 4015848Sgblack@eecs.umich.edu TimeSlots timeSlots; 4025848Sgblack@eecs.umich.edu 4035848Sgblack@eecs.umich.edu Process * 4045647Sgblack@eecs.umich.edu getNextReady() 4055647Sgblack@eecs.umich.edu { 4065647Sgblack@eecs.umich.edu Process *p = readyListMethods.getNext(); 4075647Sgblack@eecs.umich.edu return p ? p : readyListThreads.getNext(); 4085648Sgblack@eecs.umich.edu } 4095647Sgblack@eecs.umich.edu 4105647Sgblack@eecs.umich.edu void runReady(); 4115647Sgblack@eecs.umich.edu EventWrapper<Scheduler, &Scheduler::runReady> readyEvent; 4125648Sgblack@eecs.umich.edu void scheduleReadyEvent(); 4135647Sgblack@eecs.umich.edu 4145647Sgblack@eecs.umich.edu void pause(); 4155647Sgblack@eecs.umich.edu void stop(); 4165647Sgblack@eecs.umich.edu EventWrapper<Scheduler, &Scheduler::pause> pauseEvent; 4175647Sgblack@eecs.umich.edu EventWrapper<Scheduler, &Scheduler::stop> stopEvent; 4185647Sgblack@eecs.umich.edu 4195647Sgblack@eecs.umich.edu Fiber *scMain; 4205647Sgblack@eecs.umich.edu const ::sc_core::sc_report *_throwToScMain; 4215647Sgblack@eecs.umich.edu 4225647Sgblack@eecs.umich.edu bool 4235647Sgblack@eecs.umich.edu starved() 4245647Sgblack@eecs.umich.edu { 4255647Sgblack@eecs.umich.edu return (readyListMethods.empty() && readyListThreads.empty() && 4265647Sgblack@eecs.umich.edu updateList.empty() && deltas.empty() && 4275647Sgblack@eecs.umich.edu (timeSlots.empty() || timeSlots.begin()->first > maxTick) && 4285647Sgblack@eecs.umich.edu initList.empty()); 4295647Sgblack@eecs.umich.edu } 4305647Sgblack@eecs.umich.edu EventWrapper<Scheduler, &Scheduler::pause> starvationEvent; 4315647Sgblack@eecs.umich.edu void scheduleStarvationEvent(); 4325647Sgblack@eecs.umich.edu 4335647Sgblack@eecs.umich.edu bool _elaborationDone; 4345647Sgblack@eecs.umich.edu bool _started; 4355647Sgblack@eecs.umich.edu bool _stopNow; 4365647Sgblack@eecs.umich.edu 4375647Sgblack@eecs.umich.edu Status _status; 4385647Sgblack@eecs.umich.edu 4395647Sgblack@eecs.umich.edu Tick maxTick; 4405647Sgblack@eecs.umich.edu Tick lastReadyTick; 4415647Sgblack@eecs.umich.edu void 4425647Sgblack@eecs.umich.edu maxTickFunc() 4435647Sgblack@eecs.umich.edu { 4445647Sgblack@eecs.umich.edu if (lastReadyTick != getCurTick()) 4455690Sgblack@eecs.umich.edu _changeStamp++; 4465690Sgblack@eecs.umich.edu pause(); 4475690Sgblack@eecs.umich.edu } 4485690Sgblack@eecs.umich.edu EventWrapper<Scheduler, &Scheduler::maxTickFunc> maxTickEvent; 4495647Sgblack@eecs.umich.edu 4505647Sgblack@eecs.umich.edu void timeAdvances() { trace(false); } 4515647Sgblack@eecs.umich.edu EventWrapper<Scheduler, &Scheduler::timeAdvances> timeAdvancesEvent; 4525647Sgblack@eecs.umich.edu void 4535647Sgblack@eecs.umich.edu scheduleTimeAdvancesEvent() 4545647Sgblack@eecs.umich.edu { 4555647Sgblack@eecs.umich.edu if (!traceFiles.empty() && !timeAdvancesEvent.scheduled()) 4565647Sgblack@eecs.umich.edu schedule(&timeAdvancesEvent); 4575647Sgblack@eecs.umich.edu } 4585647Sgblack@eecs.umich.edu 4595647Sgblack@eecs.umich.edu uint64_t _numCycles; 4605647Sgblack@eecs.umich.edu uint64_t _changeStamp; 4615647Sgblack@eecs.umich.edu 4625647Sgblack@eecs.umich.edu Process *_current; 4635647Sgblack@eecs.umich.edu 4645647Sgblack@eecs.umich.edu bool initDone; 4655647Sgblack@eecs.umich.edu bool runToTime; 4665647Sgblack@eecs.umich.edu bool runOnce; 4675647Sgblack@eecs.umich.edu 4685647Sgblack@eecs.umich.edu ProcessList initList; 4695647Sgblack@eecs.umich.edu 4705647Sgblack@eecs.umich.edu ProcessList readyListMethods; 4715647Sgblack@eecs.umich.edu ProcessList readyListThreads; 4725647Sgblack@eecs.umich.edu 4735647Sgblack@eecs.umich.edu ChannelList updateList; 4746046Sgblack@eecs.umich.edu 4756046Sgblack@eecs.umich.edu std::map<::Event *, Tick> eventsToSchedule; 4766046Sgblack@eecs.umich.edu 4776046Sgblack@eecs.umich.edu std::set<TraceFile *> traceFiles; 4786046Sgblack@eecs.umich.edu 4796046Sgblack@eecs.umich.edu void trace(bool delta); 4806046Sgblack@eecs.umich.edu}; 4816046Sgblack@eecs.umich.edu 4826046Sgblack@eecs.umich.eduextern Scheduler scheduler; 4836046Sgblack@eecs.umich.edu 4846046Sgblack@eecs.umich.eduinline void 4856712Snate@binkert.orgScheduler::TimeSlot::process() 4866046Sgblack@eecs.umich.edu{ 4876046Sgblack@eecs.umich.edu scheduler.status(StatusTiming); 4886046Sgblack@eecs.umich.edu 4896046Sgblack@eecs.umich.edu try { 4906046Sgblack@eecs.umich.edu while (!events.empty()) 4916046Sgblack@eecs.umich.edu events.front()->run(); 4926046Sgblack@eecs.umich.edu } catch (...) { 4936065Sgblack@eecs.umich.edu if (events.empty()) 4946065Sgblack@eecs.umich.edu scheduler.completeTimeSlot(this); 4956138Sgblack@eecs.umich.edu else 4966138Sgblack@eecs.umich.edu scheduler.schedule(this); 4976046Sgblack@eecs.umich.edu scheduler.throwToScMain(); 4986046Sgblack@eecs.umich.edu } 4996138Sgblack@eecs.umich.edu 5006138Sgblack@eecs.umich.edu scheduler.status(StatusOther); 5016138Sgblack@eecs.umich.edu scheduler.completeTimeSlot(this); 5026138Sgblack@eecs.umich.edu} 5036138Sgblack@eecs.umich.edu 5046138Sgblack@eecs.umich.educonst ::sc_core::sc_report *reportifyException(); 5056138Sgblack@eecs.umich.edu 5066138Sgblack@eecs.umich.edu} // namespace sc_gem5 5076138Sgblack@eecs.umich.edu 5086138Sgblack@eecs.umich.edu#endif // __SYSTEMC_CORE_SCHEDULER_H__ 5096138Sgblack@eecs.umich.edu