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