scheduler.hh revision 13701:d84e5d2979a7
112837Sgabeblack@google.com/* 212837Sgabeblack@google.com * Copyright 2018 Google, Inc. 312837Sgabeblack@google.com * 412837Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 512837Sgabeblack@google.com * modification, are permitted provided that the following conditions are 612837Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 712837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 812837Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 912837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1012837Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1112837Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1212837Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1312837Sgabeblack@google.com * this software without specific prior written permission. 1412837Sgabeblack@google.com * 1512837Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1612837Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1712837Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1812837Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1912837Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2012837Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2112837Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2212837Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2312837Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2412837Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2512837Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2612837Sgabeblack@google.com * 2712837Sgabeblack@google.com * Authors: Gabe Black 2812837Sgabeblack@google.com */ 2912837Sgabeblack@google.com 3012901Sgabeblack@google.com#ifndef __SYSTEMC_CORE_SCHEDULER_HH__ 3112901Sgabeblack@google.com#define __SYSTEMC_CORE_SCHEDULER_HH__ 3212901Sgabeblack@google.com 3312837Sgabeblack@google.com#include <functional> 3412982Sgabeblack@google.com#include <map> 3512951Sgabeblack@google.com#include <set> 3612953Sgabeblack@google.com#include <vector> 3712837Sgabeblack@google.com 3812951Sgabeblack@google.com#include "base/logging.hh" 3912837Sgabeblack@google.com#include "sim/core.hh" 4012952Sgabeblack@google.com#include "sim/eventq.hh" 4112952Sgabeblack@google.com#include "systemc/core/channel.hh" 4212952Sgabeblack@google.com#include "systemc/core/list.hh" 4312952Sgabeblack@google.com#include "systemc/core/process.hh" 4412952Sgabeblack@google.com#include "systemc/core/sched_event.hh" 4512952Sgabeblack@google.com 4612993Sgabeblack@google.comclass Fiber; 4712993Sgabeblack@google.com 4812993Sgabeblack@google.comnamespace sc_gem5 4912952Sgabeblack@google.com{ 5012952Sgabeblack@google.com 5112952Sgabeblack@google.comclass TraceFile; 5212952Sgabeblack@google.com 5312952Sgabeblack@google.comtypedef NodeList<Process> ProcessList; 5412993Sgabeblack@google.comtypedef NodeList<Channel> ChannelList; 5512993Sgabeblack@google.com 5612993Sgabeblack@google.com/* 5712952Sgabeblack@google.com * The scheduler supports three different mechanisms, the initialization phase, 5812952Sgabeblack@google.com * delta cycles, and timed notifications. 5912952Sgabeblack@google.com * 6012952Sgabeblack@google.com * INITIALIZATION PHASE 6112952Sgabeblack@google.com * 6212993Sgabeblack@google.com * The initialization phase has three parts: 6312993Sgabeblack@google.com * 1. Run requested channel updates. 6412993Sgabeblack@google.com * 2. Make processes which need to initialize runnable (methods and threads 6512952Sgabeblack@google.com * which didn't have dont_initialize called on them). 6612952Sgabeblack@google.com * 3. Process delta notifications. 6712952Sgabeblack@google.com * 6812952Sgabeblack@google.com * First, the Kernel SimObject calls the update() method during its startup() 6912837Sgabeblack@google.com * callback which handles the requested channel updates. The Kernel also 7012837Sgabeblack@google.com * schedules an event to be run at time 0 with a slightly elevated priority 7112837Sgabeblack@google.com * so that it happens before any "normal" event. 7212951Sgabeblack@google.com * 7312951Sgabeblack@google.com * When that t0 event happens, it calls the schedulers prepareForInit method 7412951Sgabeblack@google.com * which performs step 2 above. That indirectly causes the scheduler's 7512837Sgabeblack@google.com * readyEvent to be scheduled with slightly lowered priority, ensuring it 7612951Sgabeblack@google.com * happens after any "normal" event. 7712951Sgabeblack@google.com * 7812951Sgabeblack@google.com * Because delta notifications are scheduled at the standard priority, all 7912837Sgabeblack@google.com * of those events will happen next, performing step 3 above. Once they finish, 8012837Sgabeblack@google.com * if the readyEvent was scheduled above, there shouldn't be any higher 8112837Sgabeblack@google.com * priority events in front of it. When it runs, it will start the first 8212982Sgabeblack@google.com * evaluate phase of the first delta cycle. 8312837Sgabeblack@google.com * 8412837Sgabeblack@google.com * DELTA CYCLE 8512837Sgabeblack@google.com * 8612837Sgabeblack@google.com * A delta cycle has three phases within it. 8712837Sgabeblack@google.com * 1. The evaluate phase where runnable processes are allowed to run. 8812837Sgabeblack@google.com * 2. The update phase where requested channel updates hapen. 8912837Sgabeblack@google.com * 3. The delta notification phase where delta notifications happen. 9012837Sgabeblack@google.com * 9112837Sgabeblack@google.com * The readyEvent runs all three steps of the delta cycle. It first goes 9212837Sgabeblack@google.com * through the list of runnable processes and executes them until the set is 9312837Sgabeblack@google.com * empty, and then immediately runs the update phase. Since these are all part 9412837Sgabeblack@google.com * of the same event, there's no chance for other events to intervene and 9512837Sgabeblack@google.com * break the required order above. 9612837Sgabeblack@google.com * 9712837Sgabeblack@google.com * During the update phase above, the spec forbids any action which would make 9812837Sgabeblack@google.com * a process runnable. That means that once the update phase finishes, the set 9912837Sgabeblack@google.com * of runnable processes will be empty. There may, however, have been some 10012837Sgabeblack@google.com * delta notifications/timeouts which will have been scheduled during either 10112837Sgabeblack@google.com * the evaluate or update phase above. Those will have been accumulated in the 10212837Sgabeblack@google.com * scheduler, and are now all executed. 10312837Sgabeblack@google.com * 10412837Sgabeblack@google.com * If any processes became runnable during the delta notification phase, the 10512837Sgabeblack@google.com * readyEvent will have been scheduled and will be waiting and ready to run 10612837Sgabeblack@google.com * again, effectively starting the next delta cycle. 10712837Sgabeblack@google.com * 10812837Sgabeblack@google.com * TIMED NOTIFICATION PHASE 10912837Sgabeblack@google.com * 11012837Sgabeblack@google.com * If no processes became runnable, the event queue will continue to process 11112837Sgabeblack@google.com * events until it comes across an event which represents all the timed 11212837Sgabeblack@google.com * notifications which are supposed to happen at a particular time. The object 11312837Sgabeblack@google.com * which tracks them will execute all those notifications, and then destroy 11412837Sgabeblack@google.com * itself. If the readyEvent is now ready to run, the next delta cycle will 11512837Sgabeblack@google.com * start. 11612837Sgabeblack@google.com * 11712837Sgabeblack@google.com * PAUSE/STOP 11812837Sgabeblack@google.com * 11912837Sgabeblack@google.com * To inject a pause from sc_pause which should happen after the current delta 12012837Sgabeblack@google.com * cycle's delta notification phase, an event is scheduled with a lower than 12112837Sgabeblack@google.com * normal priority, but higher than the readyEvent. That ensures that any 12212837Sgabeblack@google.com * delta notifications which are scheduled with normal priority will happen 12312837Sgabeblack@google.com * first, since those are part of the current delta cycle. Then the pause 12412837Sgabeblack@google.com * event will happen before the next readyEvent which would start the next 12512837Sgabeblack@google.com * delta cycle. All of these events are scheduled for the current time, and so 12612837Sgabeblack@google.com * would happen before any timed notifications went off. 12712837Sgabeblack@google.com * 12812837Sgabeblack@google.com * To inject a stop from sc_stop, the delta cycles should stop before even the 12912837Sgabeblack@google.com * delta notifications have happened, but after the evaluate and update phases. 13012837Sgabeblack@google.com * For that, a stop event with slightly higher than normal priority will be 13112837Sgabeblack@google.com * scheduled so that it happens before any of the delta notification events 13212837Sgabeblack@google.com * which are at normal priority. 13312837Sgabeblack@google.com * 13412837Sgabeblack@google.com * MAX RUN TIME 13512837Sgabeblack@google.com * 13612837Sgabeblack@google.com * When sc_start is called, it's possible to pass in a maximum time the 13712837Sgabeblack@google.com * simulation should run to, at which point sc_pause is implicitly called. The 13812837Sgabeblack@google.com * simulation is supposed to run up to the latest timed notification phase 13912837Sgabeblack@google.com * which is less than or equal to the maximum time. In other words it should 14012837Sgabeblack@google.com * run timed notifications at the maximum time, but not the subsequent evaluate 14112837Sgabeblack@google.com * phase. That's implemented by scheduling an event at the max time with a 14212837Sgabeblack@google.com * priority which is lower than all the others except the ready event. Timed 14312837Sgabeblack@google.com * notifications will happen before it fires, but it will override any ready 14412837Sgabeblack@google.com * event and prevent the evaluate phase from starting. 14512837Sgabeblack@google.com */ 14612837Sgabeblack@google.com 14712837Sgabeblack@google.comclass Scheduler 14812837Sgabeblack@google.com{ 14912837Sgabeblack@google.com public: 15012837Sgabeblack@google.com typedef std::list<ScEvent *> ScEvents; 15112837Sgabeblack@google.com 15212837Sgabeblack@google.com class TimeSlot : public ::Event 15312837Sgabeblack@google.com { 15412837Sgabeblack@google.com public: 15512837Sgabeblack@google.com TimeSlot() : ::Event(Default_Pri, AutoDelete) {} 15612837Sgabeblack@google.com 15712837Sgabeblack@google.com ScEvents events; 15812951Sgabeblack@google.com void process(); 15912837Sgabeblack@google.com }; 16012837Sgabeblack@google.com 16112837Sgabeblack@google.com typedef std::map<Tick, TimeSlot *> TimeSlots; 16212837Sgabeblack@google.com 16312837Sgabeblack@google.com Scheduler(); 16412951Sgabeblack@google.com ~Scheduler(); 16512837Sgabeblack@google.com 16612837Sgabeblack@google.com void clear(); 16712951Sgabeblack@google.com 16812952Sgabeblack@google.com const std::string name() const { return "systemc_scheduler"; } 16912951Sgabeblack@google.com 17012951Sgabeblack@google.com uint64_t numCycles() { return _numCycles; } 17112837Sgabeblack@google.com Process *current() { return _current; } 17212951Sgabeblack@google.com 17312951Sgabeblack@google.com void initPhase(); 17412951Sgabeblack@google.com 17512951Sgabeblack@google.com // Register a process with the scheduler. 17612951Sgabeblack@google.com void reg(Process *p); 17712928Sgabeblack@google.com 17812837Sgabeblack@google.com // Run the next process, if there is one. 17912837Sgabeblack@google.com void yield(); 18012837Sgabeblack@google.com 18112837Sgabeblack@google.com // Put a process on the ready list. 18212837Sgabeblack@google.com void ready(Process *p); 18312837Sgabeblack@google.com 18412837Sgabeblack@google.com // Mark a process as ready if init is finished, or put it on the list of 18512837Sgabeblack@google.com // processes to be initialized. 18612837Sgabeblack@google.com void resume(Process *p); 18712837Sgabeblack@google.com 18812837Sgabeblack@google.com // Remove a process from the ready/init list if it was on one of them, and 18912837Sgabeblack@google.com // return if it was. 19012837Sgabeblack@google.com bool suspend(Process *p); 19112837Sgabeblack@google.com 19212837Sgabeblack@google.com // Schedule an update for a given channel. 19312837Sgabeblack@google.com void requestUpdate(Channel *c); 19412837Sgabeblack@google.com 19512837Sgabeblack@google.com // Run the given process immediately, preempting whatever may be running. 19612837Sgabeblack@google.com void 19712837Sgabeblack@google.com runNow(Process *p) 19812837Sgabeblack@google.com { 19912837Sgabeblack@google.com // This function may put a process on the wrong list, ie a thread 20012837Sgabeblack@google.com // the method list. That's fine since that's just a performance 20112837Sgabeblack@google.com // optimization, and the important thing here is how the processes are 20212837Sgabeblack@google.com // ordered. 20312837Sgabeblack@google.com 20412837Sgabeblack@google.com // If a process is running, schedule it/us to run again. 20512837Sgabeblack@google.com if (_current) 20612837Sgabeblack@google.com readyListMethods.pushFirst(_current); 20712837Sgabeblack@google.com // Schedule p to run first. 20812837Sgabeblack@google.com readyListMethods.pushFirst(p); 20912837Sgabeblack@google.com yield(); 21012837Sgabeblack@google.com } 21112837Sgabeblack@google.com 21212837Sgabeblack@google.com // Run this process at the next opportunity. 21312837Sgabeblack@google.com void 21412837Sgabeblack@google.com runNext(Process *p) 21512837Sgabeblack@google.com { 21612837Sgabeblack@google.com // Like above, it's ok if this isn't a method. Putting it on this list 21712837Sgabeblack@google.com // just gives it priority. 21812837Sgabeblack@google.com readyListMethods.pushFirst(p); 21912837Sgabeblack@google.com if (!inEvaluate()) 22012837Sgabeblack@google.com scheduleReadyEvent(); 22112837Sgabeblack@google.com } 22212837Sgabeblack@google.com 22312837Sgabeblack@google.com // Set an event queue for scheduling events. 22412837Sgabeblack@google.com void setEventQueue(EventQueue *_eq) { eq = _eq; } 22512837Sgabeblack@google.com 22612837Sgabeblack@google.com // Get the current time according to gem5. 22712837Sgabeblack@google.com Tick getCurTick() { return eq ? eq->getCurTick() : 0; } 22812837Sgabeblack@google.com 22912837Sgabeblack@google.com Tick 23012837Sgabeblack@google.com delayed(const ::sc_core::sc_time &delay) 23112953Sgabeblack@google.com { 23212837Sgabeblack@google.com return getCurTick() + delay.value(); 23312837Sgabeblack@google.com } 23412837Sgabeblack@google.com 23512953Sgabeblack@google.com // For scheduling delayed/timed notifications/timeouts. 23612837Sgabeblack@google.com void 23712953Sgabeblack@google.com schedule(ScEvent *event, const ::sc_core::sc_time &delay) 23812837Sgabeblack@google.com { 23912837Sgabeblack@google.com Tick tick = delayed(delay); 24012837Sgabeblack@google.com if (tick < getCurTick()) 24112951Sgabeblack@google.com tick = getCurTick(); 24212951Sgabeblack@google.com 24312837Sgabeblack@google.com // Delta notification/timeout. 24412951Sgabeblack@google.com if (delay.value() == 0) { 24512837Sgabeblack@google.com event->schedule(deltas, tick); 24612951Sgabeblack@google.com if (!inEvaluate() && !inUpdate()) 24712837Sgabeblack@google.com scheduleReadyEvent(); 24812837Sgabeblack@google.com return; 24912837Sgabeblack@google.com } 25012951Sgabeblack@google.com 25112837Sgabeblack@google.com // Timed notification/timeout. 25212951Sgabeblack@google.com TimeSlot *&ts = timeSlots[tick]; 25312837Sgabeblack@google.com if (!ts) { 25412837Sgabeblack@google.com ts = new TimeSlot; 25512837Sgabeblack@google.com schedule(ts, tick); 25612951Sgabeblack@google.com } 25712837Sgabeblack@google.com event->schedule(ts->events, tick); 25812951Sgabeblack@google.com } 25912837Sgabeblack@google.com 26012837Sgabeblack@google.com // For descheduling delayed/timed notifications/timeouts. 26112837Sgabeblack@google.com void 26212951Sgabeblack@google.com deschedule(ScEvent *event) 26312837Sgabeblack@google.com { 26412951Sgabeblack@google.com ScEvents *on = event->scheduledOn(); 26512837Sgabeblack@google.com 26612837Sgabeblack@google.com if (on == &deltas) { 26712837Sgabeblack@google.com event->deschedule(); 26812951Sgabeblack@google.com return; 26912837Sgabeblack@google.com } 27012951Sgabeblack@google.com 27112837Sgabeblack@google.com // Timed notification/timeout. 27212837Sgabeblack@google.com auto tsit = timeSlots.find(event->when()); 27312837Sgabeblack@google.com panic_if(tsit == timeSlots.end(), 27412951Sgabeblack@google.com "Descheduling event at time with no events."); 27512837Sgabeblack@google.com TimeSlot *ts = tsit->second; 27612951Sgabeblack@google.com ScEvents &events = ts->events; 27712837Sgabeblack@google.com assert(on == &events); 27812837Sgabeblack@google.com event->deschedule(); 27912837Sgabeblack@google.com 28012951Sgabeblack@google.com // If no more events are happening at this time slot, get rid of it. 28112837Sgabeblack@google.com if (events.empty()) { 28212951Sgabeblack@google.com deschedule(ts); 28312837Sgabeblack@google.com timeSlots.erase(tsit); 28412837Sgabeblack@google.com } 28512837Sgabeblack@google.com } 28612951Sgabeblack@google.com 28712837Sgabeblack@google.com void 28812951Sgabeblack@google.com completeTimeSlot(TimeSlot *ts) 28912837Sgabeblack@google.com { 29012837Sgabeblack@google.com assert(ts == timeSlots.begin()->second); 29112837Sgabeblack@google.com timeSlots.erase(timeSlots.begin()); 29212951Sgabeblack@google.com if (!runToTime && starved()) 29312837Sgabeblack@google.com scheduleStarvationEvent(); 29412951Sgabeblack@google.com scheduleTimeAdvancesEvent(); 29512837Sgabeblack@google.com } 29612837Sgabeblack@google.com 29712837Sgabeblack@google.com // Pending activity ignores gem5 activity, much like how a systemc 29812951Sgabeblack@google.com // simulation wouldn't know about asynchronous external events (socket IO 29912837Sgabeblack@google.com // for instance) that might happen before time advances in a pure 30012951Sgabeblack@google.com // systemc simulation. Also the spec lists what specific types of pending 30112837Sgabeblack@google.com // activity needs to be counted, which obviously doesn't include gem5 30212837Sgabeblack@google.com // events. 30312837Sgabeblack@google.com 30412951Sgabeblack@google.com // Return whether there's pending systemc activity at this time. 30512837Sgabeblack@google.com bool 30612951Sgabeblack@google.com pendingCurr() 30712837Sgabeblack@google.com { 30812837Sgabeblack@google.com return !readyListMethods.empty() || !readyListThreads.empty() || 30912837Sgabeblack@google.com !updateList.empty() || !deltas.empty(); 31012929Sgabeblack@google.com } 31112929Sgabeblack@google.com 31212929Sgabeblack@google.com // Return whether there are pending timed notifications or timeouts. 31312929Sgabeblack@google.com bool 31412929Sgabeblack@google.com pendingFuture() 31512929Sgabeblack@google.com { 31612929Sgabeblack@google.com return !timeSlots.empty(); 31712929Sgabeblack@google.com } 31812837Sgabeblack@google.com 31912837Sgabeblack@google.com // Return how many ticks there are until the first pending event, if any. 32012837Sgabeblack@google.com Tick 32112951Sgabeblack@google.com timeToPending() 32212837Sgabeblack@google.com { 32312837Sgabeblack@google.com if (pendingCurr()) 32412837Sgabeblack@google.com return 0; 32512951Sgabeblack@google.com if (pendingFuture()) 32612837Sgabeblack@google.com return timeSlots.begin()->first - getCurTick(); 32712951Sgabeblack@google.com return MaxTick - getCurTick(); 32812837Sgabeblack@google.com } 32912837Sgabeblack@google.com 33012837Sgabeblack@google.com // Run scheduled channel updates. 33112951Sgabeblack@google.com void runUpdate(); 33212837Sgabeblack@google.com 33312951Sgabeblack@google.com // Run delta events. 33412837Sgabeblack@google.com void runDelta(); 33512837Sgabeblack@google.com 33612837Sgabeblack@google.com void start(Tick max_tick, bool run_to_time); 33712951Sgabeblack@google.com void oneCycle(); 33812837Sgabeblack@google.com 33912951Sgabeblack@google.com void schedulePause(); 34012837Sgabeblack@google.com void scheduleStop(bool finish_delta); 34112837Sgabeblack@google.com 34212837Sgabeblack@google.com enum Status 34312951Sgabeblack@google.com { 34412837Sgabeblack@google.com StatusOther = 0, 34512951Sgabeblack@google.com StatusEvaluate, 34612837Sgabeblack@google.com StatusUpdate, 34712837Sgabeblack@google.com StatusDelta, 34812837Sgabeblack@google.com StatusTiming, 34912951Sgabeblack@google.com StatusPaused, 35012837Sgabeblack@google.com StatusStopped 35112951Sgabeblack@google.com }; 35212837Sgabeblack@google.com 35312837Sgabeblack@google.com bool elaborationDone() { return _elaborationDone; } 35412837Sgabeblack@google.com void elaborationDone(bool b) { _elaborationDone = b; } 35512951Sgabeblack@google.com 35612837Sgabeblack@google.com bool paused() { return status() == StatusPaused; } 35712951Sgabeblack@google.com bool stopped() { return status() == StatusStopped; } 35812837Sgabeblack@google.com bool inEvaluate() { return status() == StatusEvaluate; } 35912837Sgabeblack@google.com bool inUpdate() { return status() == StatusUpdate; } 36012837Sgabeblack@google.com bool inDelta() { return status() == StatusDelta; } 36112951Sgabeblack@google.com bool inTiming() { return status() == StatusTiming; } 36212837Sgabeblack@google.com 36312951Sgabeblack@google.com uint64_t changeStamp() { return _changeStamp; } 36412837Sgabeblack@google.com void stepChangeStamp() { _changeStamp++; } 36512837Sgabeblack@google.com 36612837Sgabeblack@google.com // Throw upwards, either to sc_main or to the report handler if sc_main 36712951Sgabeblack@google.com // isn't running. 36812837Sgabeblack@google.com void throwUp(); 36912951Sgabeblack@google.com 37012837Sgabeblack@google.com Status status() { return _status; } 37112837Sgabeblack@google.com void status(Status s) { _status = s; } 37212837Sgabeblack@google.com 37312951Sgabeblack@google.com void registerTraceFile(TraceFile *tf) { traceFiles.insert(tf); } 37412837Sgabeblack@google.com void unregisterTraceFile(TraceFile *tf) { traceFiles.erase(tf); } 37512951Sgabeblack@google.com 37612837Sgabeblack@google.com private: 37712837Sgabeblack@google.com typedef const EventBase::Priority Priority; 37812837Sgabeblack@google.com static Priority DefaultPriority = EventBase::Default_Pri; 37912951Sgabeblack@google.com 38012837Sgabeblack@google.com static Priority StopPriority = DefaultPriority - 1; 38112951Sgabeblack@google.com static Priority PausePriority = DefaultPriority + 1; 38212837Sgabeblack@google.com static Priority MaxTickPriority = DefaultPriority + 2; 38312837Sgabeblack@google.com static Priority ReadyPriority = DefaultPriority + 3; 38412837Sgabeblack@google.com static Priority StarvationPriority = ReadyPriority; 38512951Sgabeblack@google.com static Priority TimeAdvancesPriority = EventBase::Maximum_Pri; 38612837Sgabeblack@google.com 38712951Sgabeblack@google.com EventQueue *eq; 38812837Sgabeblack@google.com 38912837Sgabeblack@google.com // For gem5 style events. 39012837Sgabeblack@google.com void 39112951Sgabeblack@google.com schedule(::Event *event, Tick tick) 39212837Sgabeblack@google.com { 39312951Sgabeblack@google.com if (initDone) 39412837Sgabeblack@google.com eq->schedule(event, tick); 39512837Sgabeblack@google.com else 39612837Sgabeblack@google.com eventsToSchedule[event] = tick; 39712837Sgabeblack@google.com } 39812909Sgabeblack@google.com 39912909Sgabeblack@google.com void schedule(::Event *event) { schedule(event, getCurTick()); } 40012951Sgabeblack@google.com 40112909Sgabeblack@google.com void 40212909Sgabeblack@google.com deschedule(::Event *event) 40312914Sgabeblack@google.com { 40412951Sgabeblack@google.com if (initDone) 40512914Sgabeblack@google.com eq->deschedule(event); 40612951Sgabeblack@google.com else 40712914Sgabeblack@google.com eventsToSchedule.erase(event); 40812914Sgabeblack@google.com } 40912914Sgabeblack@google.com 41012951Sgabeblack@google.com ScEvents deltas; 41112914Sgabeblack@google.com TimeSlots timeSlots; 41212951Sgabeblack@google.com 41312914Sgabeblack@google.com Process * 41412914Sgabeblack@google.com getNextReady() 41512914Sgabeblack@google.com { 41612951Sgabeblack@google.com Process *p = readyListMethods.getNext(); 41712914Sgabeblack@google.com return p ? p : readyListThreads.getNext(); 41812951Sgabeblack@google.com } 41912914Sgabeblack@google.com 42012914Sgabeblack@google.com void runReady(); 42112914Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::runReady> readyEvent; 42212951Sgabeblack@google.com void scheduleReadyEvent(); 42312914Sgabeblack@google.com 42412951Sgabeblack@google.com void pause(); 42512914Sgabeblack@google.com void stop(); 42612914Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::pause> pauseEvent; 42712909Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::stop> stopEvent; 42812909Sgabeblack@google.com 42912837Sgabeblack@google.com const ::sc_core::sc_report *_throwUp; 43012837Sgabeblack@google.com 43112958Sgabeblack@google.com bool 43212958Sgabeblack@google.com starved() 43312837Sgabeblack@google.com { 43412837Sgabeblack@google.com return (readyListMethods.empty() && readyListThreads.empty() && 43512837Sgabeblack@google.com updateList.empty() && deltas.empty() && 43612958Sgabeblack@google.com (timeSlots.empty() || timeSlots.begin()->first > maxTick) && 43712837Sgabeblack@google.com initList.empty()); 43812958Sgabeblack@google.com } 43912958Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::pause> starvationEvent; 44012837Sgabeblack@google.com void scheduleStarvationEvent(); 44112837Sgabeblack@google.com 44212837Sgabeblack@google.com bool _elaborationDone; 44312958Sgabeblack@google.com bool _started; 44412837Sgabeblack@google.com bool _stopNow; 44512958Sgabeblack@google.com 44612958Sgabeblack@google.com Status _status; 44712837Sgabeblack@google.com 44812837Sgabeblack@google.com Tick maxTick; 44912837Sgabeblack@google.com Tick lastReadyTick; 45012958Sgabeblack@google.com void 45112837Sgabeblack@google.com maxTickFunc() 45212958Sgabeblack@google.com { 45312958Sgabeblack@google.com if (lastReadyTick != getCurTick()) 45412837Sgabeblack@google.com _changeStamp++; 45512837Sgabeblack@google.com pause(); 45612837Sgabeblack@google.com } 45712958Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::maxTickFunc> maxTickEvent; 45812837Sgabeblack@google.com 45912958Sgabeblack@google.com void timeAdvances() { trace(false); } 46012958Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::timeAdvances> timeAdvancesEvent; 46112837Sgabeblack@google.com void 46212837Sgabeblack@google.com scheduleTimeAdvancesEvent() 46312837Sgabeblack@google.com { 46412951Sgabeblack@google.com if (!traceFiles.empty() && !timeAdvancesEvent.scheduled()) 46512837Sgabeblack@google.com schedule(&timeAdvancesEvent); 46612951Sgabeblack@google.com } 46712837Sgabeblack@google.com 46812837Sgabeblack@google.com uint64_t _numCycles; 46912837Sgabeblack@google.com uint64_t _changeStamp; 47012958Sgabeblack@google.com 47112837Sgabeblack@google.com Process *_current; 47212958Sgabeblack@google.com 47312958Sgabeblack@google.com bool initDone; 47412837Sgabeblack@google.com bool runToTime; 47512837Sgabeblack@google.com bool runOnce; 47612837Sgabeblack@google.com 47712951Sgabeblack@google.com ProcessList initList; 47812837Sgabeblack@google.com 47912951Sgabeblack@google.com ProcessList readyListMethods; 48012837Sgabeblack@google.com ProcessList readyListThreads; 48112837Sgabeblack@google.com 48212837Sgabeblack@google.com ChannelList updateList; 48312958Sgabeblack@google.com 48412837Sgabeblack@google.com std::map<::Event *, Tick> eventsToSchedule; 48512958Sgabeblack@google.com 48612958Sgabeblack@google.com std::set<TraceFile *> traceFiles; 48712958Sgabeblack@google.com 48812837Sgabeblack@google.com void trace(bool delta); 48912837Sgabeblack@google.com}; 49012837Sgabeblack@google.com 49112951Sgabeblack@google.comextern Scheduler scheduler; 49212837Sgabeblack@google.com 49312951Sgabeblack@google.com// A proxy function to avoid having to expose the scheduler in header files. 49412837Sgabeblack@google.comProcess *getCurrentProcess(); 49512837Sgabeblack@google.com 49612837Sgabeblack@google.cominline void 49712958Sgabeblack@google.comScheduler::TimeSlot::process() 49812837Sgabeblack@google.com{ 49912958Sgabeblack@google.com scheduler.stepChangeStamp(); 50012958Sgabeblack@google.com scheduler.status(StatusTiming); 50112958Sgabeblack@google.com 50212837Sgabeblack@google.com try { 50312837Sgabeblack@google.com while (!events.empty()) 50412837Sgabeblack@google.com events.front()->run(); 50512951Sgabeblack@google.com } catch (...) { 50612837Sgabeblack@google.com if (events.empty()) 50712951Sgabeblack@google.com scheduler.completeTimeSlot(this); 50812837Sgabeblack@google.com else 50912837Sgabeblack@google.com scheduler.schedule(this); 51012929Sgabeblack@google.com scheduler.throwUp(); 51112929Sgabeblack@google.com } 51212929Sgabeblack@google.com 51312929Sgabeblack@google.com scheduler.status(StatusOther); 51412929Sgabeblack@google.com scheduler.completeTimeSlot(this); 51512929Sgabeblack@google.com} 51612929Sgabeblack@google.com 51712837Sgabeblack@google.comconst ::sc_core::sc_report reportifyException(); 51812837Sgabeblack@google.com 51912837Sgabeblack@google.com} // namespace sc_gem5 52012837Sgabeblack@google.com 52112958Sgabeblack@google.com#endif // __SYSTEMC_CORE_SCHEDULER_H__ 52212958Sgabeblack@google.com