scheduler.hh revision 13244
112953Sgabeblack@google.com/* 212953Sgabeblack@google.com * Copyright 2018 Google, Inc. 312953Sgabeblack@google.com * 412953Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 512953Sgabeblack@google.com * modification, are permitted provided that the following conditions are 612953Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 712953Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 812953Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 912953Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1012953Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1112953Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1212953Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1312953Sgabeblack@google.com * this software without specific prior written permission. 1412953Sgabeblack@google.com * 1512953Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1612953Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1712953Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1812953Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1912953Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2012953Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2112953Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2212953Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2312953Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2412953Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2512953Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2612953Sgabeblack@google.com * 2712953Sgabeblack@google.com * Authors: Gabe Black 2812953Sgabeblack@google.com */ 2912953Sgabeblack@google.com 3012953Sgabeblack@google.com#ifndef __SYSTEMC_CORE_SCHEDULER_HH__ 3112953Sgabeblack@google.com#define __SYSTEMC_CORE_SCHEDULER_HH__ 3212953Sgabeblack@google.com 3313063Sgabeblack@google.com#include <functional> 3413063Sgabeblack@google.com#include <map> 3513063Sgabeblack@google.com#include <set> 3612957Sgabeblack@google.com#include <vector> 3712957Sgabeblack@google.com 3812961Sgabeblack@google.com#include "base/logging.hh" 3913063Sgabeblack@google.com#include "sim/core.hh" 4012954Sgabeblack@google.com#include "sim/eventq.hh" 4112954Sgabeblack@google.com#include "systemc/core/channel.hh" 4212953Sgabeblack@google.com#include "systemc/core/list.hh" 4312953Sgabeblack@google.com#include "systemc/core/process.hh" 4413063Sgabeblack@google.com#include "systemc/core/sched_event.hh" 4512953Sgabeblack@google.com 4612961Sgabeblack@google.comclass Fiber; 4712961Sgabeblack@google.com 4812953Sgabeblack@google.comnamespace sc_gem5 4912953Sgabeblack@google.com{ 5012953Sgabeblack@google.com 5112953Sgabeblack@google.comtypedef NodeList<Process> ProcessList; 5212954Sgabeblack@google.comtypedef NodeList<Channel> ChannelList; 5312954Sgabeblack@google.com 5412954Sgabeblack@google.com/* 5512954Sgabeblack@google.com * The scheduler supports three different mechanisms, the initialization phase, 5612954Sgabeblack@google.com * delta cycles, and timed notifications. 5712954Sgabeblack@google.com * 5812954Sgabeblack@google.com * INITIALIZATION PHASE 5912954Sgabeblack@google.com * 6012954Sgabeblack@google.com * The initialization phase has three parts: 6112954Sgabeblack@google.com * 1. Run requested channel updates. 6212954Sgabeblack@google.com * 2. Make processes which need to initialize runnable (methods and threads 6312954Sgabeblack@google.com * which didn't have dont_initialize called on them). 6412954Sgabeblack@google.com * 3. Process delta notifications. 6512954Sgabeblack@google.com * 6612954Sgabeblack@google.com * First, the Kernel SimObject calls the update() method during its startup() 6712954Sgabeblack@google.com * callback which handles the requested channel updates. The Kernel also 6812954Sgabeblack@google.com * schedules an event to be run at time 0 with a slightly elevated priority 6912954Sgabeblack@google.com * so that it happens before any "normal" event. 7012954Sgabeblack@google.com * 7112957Sgabeblack@google.com * When that t0 event happens, it calls the schedulers prepareForInit method 7212954Sgabeblack@google.com * which performs step 2 above. That indirectly causes the scheduler's 7312954Sgabeblack@google.com * readyEvent to be scheduled with slightly lowered priority, ensuring it 7412954Sgabeblack@google.com * happens after any "normal" event. 7512954Sgabeblack@google.com * 7612954Sgabeblack@google.com * Because delta notifications are scheduled at the standard priority, all 7712954Sgabeblack@google.com * of those events will happen next, performing step 3 above. Once they finish, 7812954Sgabeblack@google.com * if the readyEvent was scheduled above, there shouldn't be any higher 7912954Sgabeblack@google.com * priority events in front of it. When it runs, it will start the first 8012954Sgabeblack@google.com * evaluate phase of the first delta cycle. 8112954Sgabeblack@google.com * 8212954Sgabeblack@google.com * DELTA CYCLE 8312954Sgabeblack@google.com * 8412954Sgabeblack@google.com * A delta cycle has three phases within it. 8512954Sgabeblack@google.com * 1. The evaluate phase where runnable processes are allowed to run. 8612954Sgabeblack@google.com * 2. The update phase where requested channel updates hapen. 8712954Sgabeblack@google.com * 3. The delta notification phase where delta notifications happen. 8812954Sgabeblack@google.com * 8913063Sgabeblack@google.com * The readyEvent runs all three steps of the delta cycle. It first goes 9012954Sgabeblack@google.com * through the list of runnable processes and executes them until the set is 9112954Sgabeblack@google.com * empty, and then immediately runs the update phase. Since these are all part 9212954Sgabeblack@google.com * of the same event, there's no chance for other events to intervene and 9312954Sgabeblack@google.com * break the required order above. 9412954Sgabeblack@google.com * 9512954Sgabeblack@google.com * During the update phase above, the spec forbids any action which would make 9612954Sgabeblack@google.com * a process runnable. That means that once the update phase finishes, the set 9712954Sgabeblack@google.com * of runnable processes will be empty. There may, however, have been some 9812954Sgabeblack@google.com * delta notifications/timeouts which will have been scheduled during either 9913063Sgabeblack@google.com * the evaluate or update phase above. Those will have been accumulated in the 10013063Sgabeblack@google.com * scheduler, and are now all executed. 10112954Sgabeblack@google.com * 10212954Sgabeblack@google.com * If any processes became runnable during the delta notification phase, the 10313063Sgabeblack@google.com * readyEvent will have been scheduled and will be waiting and ready to run 10413063Sgabeblack@google.com * again, effectively starting the next delta cycle. 10512954Sgabeblack@google.com * 10612954Sgabeblack@google.com * TIMED NOTIFICATION PHASE 10712954Sgabeblack@google.com * 10812954Sgabeblack@google.com * If no processes became runnable, the event queue will continue to process 10913063Sgabeblack@google.com * events until it comes across an event which represents all the timed 11013063Sgabeblack@google.com * notifications which are supposed to happen at a particular time. The object 11113063Sgabeblack@google.com * which tracks them will execute all those notifications, and then destroy 11213063Sgabeblack@google.com * itself. If the readyEvent is now ready to run, the next delta cycle will 11313063Sgabeblack@google.com * start. 11412961Sgabeblack@google.com * 11512961Sgabeblack@google.com * PAUSE/STOP 11612961Sgabeblack@google.com * 11712961Sgabeblack@google.com * To inject a pause from sc_pause which should happen after the current delta 11812961Sgabeblack@google.com * cycle's delta notification phase, an event is scheduled with a lower than 11912961Sgabeblack@google.com * normal priority, but higher than the readyEvent. That ensures that any 12012961Sgabeblack@google.com * delta notifications which are scheduled with normal priority will happen 12112961Sgabeblack@google.com * first, since those are part of the current delta cycle. Then the pause 12212961Sgabeblack@google.com * event will happen before the next readyEvent which would start the next 12312961Sgabeblack@google.com * delta cycle. All of these events are scheduled for the current time, and so 12412961Sgabeblack@google.com * would happen before any timed notifications went off. 12512961Sgabeblack@google.com * 12612961Sgabeblack@google.com * To inject a stop from sc_stop, the delta cycles should stop before even the 12712961Sgabeblack@google.com * delta notifications have happened, but after the evaluate and update phases. 12812961Sgabeblack@google.com * For that, a stop event with slightly higher than normal priority will be 12912961Sgabeblack@google.com * scheduled so that it happens before any of the delta notification events 13012961Sgabeblack@google.com * which are at normal priority. 13112961Sgabeblack@google.com * 13212961Sgabeblack@google.com * MAX RUN TIME 13312961Sgabeblack@google.com * 13412961Sgabeblack@google.com * When sc_start is called, it's possible to pass in a maximum time the 13513058Sgabeblack@google.com * simulation should run to, at which point sc_pause is implicitly called. The 13613058Sgabeblack@google.com * simulation is supposed to run up to the latest timed notification phase 13713058Sgabeblack@google.com * which is less than or equal to the maximum time. In other words it should 13813058Sgabeblack@google.com * run timed notifications at the maximum time, but not the subsequent evaluate 13913058Sgabeblack@google.com * phase. That's implemented by scheduling an event at the max time with a 14013058Sgabeblack@google.com * priority which is lower than all the others except the ready event. Timed 14113058Sgabeblack@google.com * notifications will happen before it fires, but it will override any ready 14213058Sgabeblack@google.com * event and prevent the evaluate phase from starting. 14312954Sgabeblack@google.com */ 14412953Sgabeblack@google.com 14512953Sgabeblack@google.comclass Scheduler 14612953Sgabeblack@google.com{ 14712953Sgabeblack@google.com public: 14813144Sgabeblack@google.com typedef std::list<ScEvent *> ScEvents; 14913063Sgabeblack@google.com 15013063Sgabeblack@google.com class TimeSlot : public ::Event 15113063Sgabeblack@google.com { 15213063Sgabeblack@google.com public: 15313063Sgabeblack@google.com TimeSlot() : ::Event(Default_Pri, AutoDelete) {} 15413063Sgabeblack@google.com 15513063Sgabeblack@google.com ScEvents events; 15613063Sgabeblack@google.com void process(); 15713063Sgabeblack@google.com }; 15813063Sgabeblack@google.com 15913063Sgabeblack@google.com typedef std::map<Tick, TimeSlot *> TimeSlots; 16013063Sgabeblack@google.com 16112953Sgabeblack@google.com Scheduler(); 16213072Sgabeblack@google.com ~Scheduler(); 16312953Sgabeblack@google.com 16413076Sgabeblack@google.com void clear(); 16513076Sgabeblack@google.com 16612954Sgabeblack@google.com const std::string name() const { return "systemc_scheduler"; } 16712954Sgabeblack@google.com 16812953Sgabeblack@google.com uint64_t numCycles() { return _numCycles; } 16912953Sgabeblack@google.com Process *current() { return _current; } 17012953Sgabeblack@google.com 17113067Sgabeblack@google.com void initPhase(); 17212953Sgabeblack@google.com 17312957Sgabeblack@google.com // Register a process with the scheduler. 17412957Sgabeblack@google.com void reg(Process *p); 17512957Sgabeblack@google.com 17612953Sgabeblack@google.com // Run the next process, if there is one. 17712953Sgabeblack@google.com void yield(); 17812953Sgabeblack@google.com 17912953Sgabeblack@google.com // Put a process on the ready list. 18012954Sgabeblack@google.com void ready(Process *p); 18112954Sgabeblack@google.com 18213133Sgabeblack@google.com // Mark a process as ready if init is finished, or put it on the list of 18313133Sgabeblack@google.com // processes to be initialized. 18413133Sgabeblack@google.com void resume(Process *p); 18513133Sgabeblack@google.com 18613133Sgabeblack@google.com // Remove a process from the ready/init list if it was on one of them, and 18713133Sgabeblack@google.com // return if it was. 18813133Sgabeblack@google.com bool suspend(Process *p); 18913133Sgabeblack@google.com 19012954Sgabeblack@google.com // Schedule an update for a given channel. 19112954Sgabeblack@google.com void requestUpdate(Channel *c); 19212953Sgabeblack@google.com 19312953Sgabeblack@google.com // Run the given process immediately, preempting whatever may be running. 19412953Sgabeblack@google.com void 19512953Sgabeblack@google.com runNow(Process *p) 19612953Sgabeblack@google.com { 19713209Sgabeblack@google.com // This function may put a process on the wrong list, ie a thread 19813209Sgabeblack@google.com // the method list. That's fine since that's just a performance 19913209Sgabeblack@google.com // optimization, and the important thing here is how the processes are 20013209Sgabeblack@google.com // ordered. 20113176Sgabeblack@google.com 20212953Sgabeblack@google.com // If a process is running, schedule it/us to run again. 20312953Sgabeblack@google.com if (_current) 20413209Sgabeblack@google.com readyListMethods.pushFirst(_current); 20512953Sgabeblack@google.com // Schedule p to run first. 20613209Sgabeblack@google.com readyListMethods.pushFirst(p); 20712953Sgabeblack@google.com yield(); 20812953Sgabeblack@google.com } 20912953Sgabeblack@google.com 21012954Sgabeblack@google.com // Set an event queue for scheduling events. 21112954Sgabeblack@google.com void setEventQueue(EventQueue *_eq) { eq = _eq; } 21212954Sgabeblack@google.com 21312962Sgabeblack@google.com // Get the current time according to gem5. 21412962Sgabeblack@google.com Tick getCurTick() { return eq ? eq->getCurTick() : 0; } 21512962Sgabeblack@google.com 21613063Sgabeblack@google.com Tick 21713063Sgabeblack@google.com delayed(const ::sc_core::sc_time &delay) 21813063Sgabeblack@google.com { 21913063Sgabeblack@google.com //XXX We're assuming the systemc time resolution is in ps. 22013063Sgabeblack@google.com return getCurTick() + delay.value() * SimClock::Int::ps; 22113063Sgabeblack@google.com } 22213063Sgabeblack@google.com 22312962Sgabeblack@google.com // For scheduling delayed/timed notifications/timeouts. 22412962Sgabeblack@google.com void 22513063Sgabeblack@google.com schedule(ScEvent *event, const ::sc_core::sc_time &delay) 22612962Sgabeblack@google.com { 22713063Sgabeblack@google.com Tick tick = delayed(delay); 22813125Sgabeblack@google.com if (tick < getCurTick()) 22913125Sgabeblack@google.com tick = getCurTick(); 23013125Sgabeblack@google.com 23113063Sgabeblack@google.com // Delta notification/timeout. 23213063Sgabeblack@google.com if (delay.value() == 0) { 23313144Sgabeblack@google.com event->schedule(deltas, tick); 23413244Sgabeblack@google.com if (!inEvaluate() && !inUpdate()) 23513244Sgabeblack@google.com scheduleReadyEvent(); 23613063Sgabeblack@google.com return; 23713063Sgabeblack@google.com } 23813063Sgabeblack@google.com 23913063Sgabeblack@google.com // Timed notification/timeout. 24013063Sgabeblack@google.com TimeSlot *&ts = timeSlots[tick]; 24113063Sgabeblack@google.com if (!ts) { 24213063Sgabeblack@google.com ts = new TimeSlot; 24313069Sgabeblack@google.com schedule(ts, tick); 24413063Sgabeblack@google.com } 24513144Sgabeblack@google.com event->schedule(ts->events, tick); 24612962Sgabeblack@google.com } 24712962Sgabeblack@google.com 24812962Sgabeblack@google.com // For descheduling delayed/timed notifications/timeouts. 24912962Sgabeblack@google.com void 25013063Sgabeblack@google.com deschedule(ScEvent *event) 25112962Sgabeblack@google.com { 25213144Sgabeblack@google.com ScEvents *on = event->scheduledOn(); 25313144Sgabeblack@google.com 25413144Sgabeblack@google.com if (on == &deltas) { 25513144Sgabeblack@google.com event->deschedule(); 25613144Sgabeblack@google.com return; 25713063Sgabeblack@google.com } 25812985Sgabeblack@google.com 25913063Sgabeblack@google.com // Timed notification/timeout. 26013063Sgabeblack@google.com auto tsit = timeSlots.find(event->when()); 26113063Sgabeblack@google.com panic_if(tsit == timeSlots.end(), 26213063Sgabeblack@google.com "Descheduling event at time with no events."); 26313063Sgabeblack@google.com TimeSlot *ts = tsit->second; 26413063Sgabeblack@google.com ScEvents &events = ts->events; 26513144Sgabeblack@google.com assert(on == &events); 26613063Sgabeblack@google.com event->deschedule(); 26713063Sgabeblack@google.com 26813063Sgabeblack@google.com // If no more events are happening at this time slot, get rid of it. 26913063Sgabeblack@google.com if (events.empty()) { 27013069Sgabeblack@google.com deschedule(ts); 27113063Sgabeblack@google.com timeSlots.erase(tsit); 27213063Sgabeblack@google.com } 27312962Sgabeblack@google.com } 27412962Sgabeblack@google.com 27512962Sgabeblack@google.com void 27613063Sgabeblack@google.com completeTimeSlot(TimeSlot *ts) 27712962Sgabeblack@google.com { 27813140Sgabeblack@google.com _changeStamp++; 27913063Sgabeblack@google.com assert(ts == timeSlots.begin()->second); 28013063Sgabeblack@google.com timeSlots.erase(timeSlots.begin()); 28113096Sgabeblack@google.com if (!runToTime && starved()) 28213096Sgabeblack@google.com scheduleStarvationEvent(); 28312962Sgabeblack@google.com } 28412962Sgabeblack@google.com 28512962Sgabeblack@google.com // Pending activity ignores gem5 activity, much like how a systemc 28612962Sgabeblack@google.com // simulation wouldn't know about asynchronous external events (socket IO 28712962Sgabeblack@google.com // for instance) that might happen before time advances in a pure 28812962Sgabeblack@google.com // systemc simulation. Also the spec lists what specific types of pending 28912962Sgabeblack@google.com // activity needs to be counted, which obviously doesn't include gem5 29012962Sgabeblack@google.com // events. 29112962Sgabeblack@google.com 29212962Sgabeblack@google.com // Return whether there's pending systemc activity at this time. 29312962Sgabeblack@google.com bool 29412962Sgabeblack@google.com pendingCurr() 29512962Sgabeblack@google.com { 29613176Sgabeblack@google.com return !readyListMethods.empty() || !readyListThreads.empty() || 29713176Sgabeblack@google.com !updateList.empty() || !deltas.empty(); 29812962Sgabeblack@google.com } 29912962Sgabeblack@google.com 30012962Sgabeblack@google.com // Return whether there are pending timed notifications or timeouts. 30112962Sgabeblack@google.com bool 30212962Sgabeblack@google.com pendingFuture() 30312962Sgabeblack@google.com { 30413063Sgabeblack@google.com return !timeSlots.empty(); 30512962Sgabeblack@google.com } 30612962Sgabeblack@google.com 30712962Sgabeblack@google.com // Return how many ticks there are until the first pending event, if any. 30812962Sgabeblack@google.com Tick 30912962Sgabeblack@google.com timeToPending() 31012962Sgabeblack@google.com { 31113063Sgabeblack@google.com if (pendingCurr()) 31212962Sgabeblack@google.com return 0; 31313063Sgabeblack@google.com if (pendingFuture()) 31413063Sgabeblack@google.com return timeSlots.begin()->first - getCurTick(); 31513063Sgabeblack@google.com return MaxTick - getCurTick(); 31612962Sgabeblack@google.com } 31712954Sgabeblack@google.com 31812954Sgabeblack@google.com // Run scheduled channel updates. 31913186Sgabeblack@google.com void runUpdate(); 32013186Sgabeblack@google.com 32113186Sgabeblack@google.com // Run delta events. 32213186Sgabeblack@google.com void runDelta(); 32312954Sgabeblack@google.com 32412961Sgabeblack@google.com void setScMainFiber(Fiber *sc_main) { scMain = sc_main; } 32512961Sgabeblack@google.com 32612961Sgabeblack@google.com void start(Tick max_tick, bool run_to_time); 32713061Sgabeblack@google.com void oneCycle(); 32812961Sgabeblack@google.com 32912961Sgabeblack@google.com void schedulePause(); 33012961Sgabeblack@google.com void scheduleStop(bool finish_delta); 33112961Sgabeblack@google.com 33213186Sgabeblack@google.com enum Status 33313186Sgabeblack@google.com { 33413186Sgabeblack@google.com StatusOther = 0, 33513244Sgabeblack@google.com StatusEvaluate, 33613244Sgabeblack@google.com StatusUpdate, 33713186Sgabeblack@google.com StatusDelta, 33813186Sgabeblack@google.com StatusTiming, 33913186Sgabeblack@google.com StatusPaused, 34013186Sgabeblack@google.com StatusStopped 34113186Sgabeblack@google.com }; 34213186Sgabeblack@google.com 34313203Sgabeblack@google.com bool elaborationDone() { return _elaborationDone; } 34413203Sgabeblack@google.com void elaborationDone(bool b) { _elaborationDone = b; } 34513203Sgabeblack@google.com 34613186Sgabeblack@google.com bool paused() { return status() == StatusPaused; } 34713186Sgabeblack@google.com bool stopped() { return status() == StatusStopped; } 34813244Sgabeblack@google.com bool inEvaluate() { return status() == StatusEvaluate; } 34913244Sgabeblack@google.com bool inUpdate() { return status() == StatusUpdate; } 35013186Sgabeblack@google.com bool inDelta() { return status() == StatusDelta; } 35113186Sgabeblack@google.com bool inTiming() { return status() == StatusTiming; } 35212961Sgabeblack@google.com 35313140Sgabeblack@google.com uint64_t changeStamp() { return _changeStamp; } 35413140Sgabeblack@google.com 35513182Sgabeblack@google.com void throwToScMain(const ::sc_core::sc_report *r=nullptr); 35613182Sgabeblack@google.com 35713186Sgabeblack@google.com Status status() { return _status; } 35813186Sgabeblack@google.com void status(Status s) { _status = s; } 35913186Sgabeblack@google.com 36012953Sgabeblack@google.com private: 36112961Sgabeblack@google.com typedef const EventBase::Priority Priority; 36212961Sgabeblack@google.com static Priority DefaultPriority = EventBase::Default_Pri; 36312961Sgabeblack@google.com 36412961Sgabeblack@google.com static Priority StopPriority = DefaultPriority - 1; 36512961Sgabeblack@google.com static Priority PausePriority = DefaultPriority + 1; 36613058Sgabeblack@google.com static Priority MaxTickPriority = DefaultPriority + 2; 36713058Sgabeblack@google.com static Priority ReadyPriority = DefaultPriority + 3; 36812987Sgabeblack@google.com static Priority StarvationPriority = ReadyPriority; 36912961Sgabeblack@google.com 37012954Sgabeblack@google.com EventQueue *eq; 37113063Sgabeblack@google.com 37213069Sgabeblack@google.com // For gem5 style events. 37313069Sgabeblack@google.com void 37413069Sgabeblack@google.com schedule(::Event *event, Tick tick) 37513069Sgabeblack@google.com { 37613069Sgabeblack@google.com if (initDone) 37713069Sgabeblack@google.com eq->schedule(event, tick); 37813069Sgabeblack@google.com else 37913069Sgabeblack@google.com eventsToSchedule[event] = tick; 38013069Sgabeblack@google.com } 38113069Sgabeblack@google.com 38213069Sgabeblack@google.com void schedule(::Event *event) { schedule(event, getCurTick()); } 38313069Sgabeblack@google.com 38413069Sgabeblack@google.com void 38513069Sgabeblack@google.com deschedule(::Event *event) 38613069Sgabeblack@google.com { 38713069Sgabeblack@google.com if (initDone) 38813069Sgabeblack@google.com eq->deschedule(event); 38913069Sgabeblack@google.com else 39013069Sgabeblack@google.com eventsToSchedule.erase(event); 39113069Sgabeblack@google.com } 39213069Sgabeblack@google.com 39313063Sgabeblack@google.com ScEvents deltas; 39413063Sgabeblack@google.com TimeSlots timeSlots; 39512954Sgabeblack@google.com 39613209Sgabeblack@google.com Process * 39713209Sgabeblack@google.com getNextReady() 39813209Sgabeblack@google.com { 39913209Sgabeblack@google.com Process *p = readyListMethods.getNext(); 40013209Sgabeblack@google.com return p ? p : readyListThreads.getNext(); 40113209Sgabeblack@google.com } 40213209Sgabeblack@google.com 40312954Sgabeblack@google.com void runReady(); 40412954Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::runReady> readyEvent; 40512954Sgabeblack@google.com void scheduleReadyEvent(); 40612954Sgabeblack@google.com 40712961Sgabeblack@google.com void pause(); 40812961Sgabeblack@google.com void stop(); 40912961Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::pause> pauseEvent; 41012961Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::stop> stopEvent; 41113182Sgabeblack@google.com 41212961Sgabeblack@google.com Fiber *scMain; 41313182Sgabeblack@google.com const ::sc_core::sc_report *_throwToScMain; 41412961Sgabeblack@google.com 41512987Sgabeblack@google.com bool 41612987Sgabeblack@google.com starved() 41712987Sgabeblack@google.com { 41813176Sgabeblack@google.com return (readyListMethods.empty() && readyListThreads.empty() && 41913176Sgabeblack@google.com updateList.empty() && deltas.empty() && 42013063Sgabeblack@google.com (timeSlots.empty() || timeSlots.begin()->first > maxTick) && 42112987Sgabeblack@google.com initList.empty()); 42212987Sgabeblack@google.com } 42312987Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::pause> starvationEvent; 42412987Sgabeblack@google.com void scheduleStarvationEvent(); 42512987Sgabeblack@google.com 42613203Sgabeblack@google.com bool _elaborationDone; 42712961Sgabeblack@google.com bool _started; 42813154Sgabeblack@google.com bool _stopNow; 42912961Sgabeblack@google.com 43013186Sgabeblack@google.com Status _status; 43113186Sgabeblack@google.com 43212961Sgabeblack@google.com Tick maxTick; 43313140Sgabeblack@google.com Tick lastReadyTick; 43413140Sgabeblack@google.com void 43513140Sgabeblack@google.com maxTickFunc() 43613140Sgabeblack@google.com { 43713140Sgabeblack@google.com if (lastReadyTick != getCurTick()) 43813140Sgabeblack@google.com _changeStamp++; 43913140Sgabeblack@google.com pause(); 44013140Sgabeblack@google.com } 44113140Sgabeblack@google.com EventWrapper<Scheduler, &Scheduler::maxTickFunc> maxTickEvent; 44212961Sgabeblack@google.com 44312953Sgabeblack@google.com uint64_t _numCycles; 44413140Sgabeblack@google.com uint64_t _changeStamp; 44512953Sgabeblack@google.com 44612953Sgabeblack@google.com Process *_current; 44712953Sgabeblack@google.com 44813067Sgabeblack@google.com bool initDone; 44912987Sgabeblack@google.com bool runToTime; 45013061Sgabeblack@google.com bool runOnce; 45112957Sgabeblack@google.com 45212953Sgabeblack@google.com ProcessList initList; 45313176Sgabeblack@google.com 45413176Sgabeblack@google.com ProcessList readyListMethods; 45513176Sgabeblack@google.com ProcessList readyListThreads; 45612953Sgabeblack@google.com 45712954Sgabeblack@google.com ChannelList updateList; 45812985Sgabeblack@google.com 45912985Sgabeblack@google.com std::map<::Event *, Tick> eventsToSchedule; 46012953Sgabeblack@google.com}; 46112953Sgabeblack@google.com 46212953Sgabeblack@google.comextern Scheduler scheduler; 46312953Sgabeblack@google.com 46413063Sgabeblack@google.cominline void 46513063Sgabeblack@google.comScheduler::TimeSlot::process() 46613063Sgabeblack@google.com{ 46713186Sgabeblack@google.com scheduler.status(StatusTiming); 46813186Sgabeblack@google.com 46913188Sgabeblack@google.com try { 47013188Sgabeblack@google.com while (!events.empty()) 47113188Sgabeblack@google.com events.front()->run(); 47213188Sgabeblack@google.com } catch (...) { 47313188Sgabeblack@google.com if (events.empty()) 47413188Sgabeblack@google.com scheduler.completeTimeSlot(this); 47513188Sgabeblack@google.com else 47613188Sgabeblack@google.com scheduler.schedule(this); 47713188Sgabeblack@google.com scheduler.throwToScMain(); 47813188Sgabeblack@google.com } 47913186Sgabeblack@google.com 48013186Sgabeblack@google.com scheduler.status(StatusOther); 48113063Sgabeblack@google.com scheduler.completeTimeSlot(this); 48213063Sgabeblack@google.com} 48313063Sgabeblack@google.com 48413182Sgabeblack@google.comconst ::sc_core::sc_report *reportifyException(); 48513182Sgabeblack@google.com 48612953Sgabeblack@google.com} // namespace sc_gem5 48712953Sgabeblack@google.com 48812953Sgabeblack@google.com#endif // __SYSTEMC_CORE_SCHEDULER_H__ 489