scheduler.cc revision 13703
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#include "systemc/core/scheduler.hh" 3112953Sgabeblack@google.com 3212953Sgabeblack@google.com#include "base/fiber.hh" 3312954Sgabeblack@google.com#include "base/logging.hh" 3412954Sgabeblack@google.com#include "sim/eventq.hh" 3513703Sgabeblack@google.com#include "sim/sim_exit.hh" 3612982Sgabeblack@google.com#include "systemc/core/kernel.hh" 3713403Sgabeblack@google.com#include "systemc/core/sc_main_fiber.hh" 3813317Sgabeblack@google.com#include "systemc/ext/core/messages.hh" 3912982Sgabeblack@google.com#include "systemc/ext/core/sc_main.hh" 4013182Sgabeblack@google.com#include "systemc/ext/utils/sc_report.hh" 4113182Sgabeblack@google.com#include "systemc/ext/utils/sc_report_handler.hh" 4213312Sgabeblack@google.com#include "systemc/utils/report.hh" 4313245Sgabeblack@google.com#include "systemc/utils/tracefile.hh" 4412953Sgabeblack@google.com 4512953Sgabeblack@google.comnamespace sc_gem5 4612953Sgabeblack@google.com{ 4712953Sgabeblack@google.com 4812954Sgabeblack@google.comScheduler::Scheduler() : 4912962Sgabeblack@google.com eq(nullptr), readyEvent(this, false, ReadyPriority), 5012961Sgabeblack@google.com pauseEvent(this, false, PausePriority), 5113701Sgabeblack@google.com stopEvent(this, false, StopPriority), _throwUp(nullptr), 5212987Sgabeblack@google.com starvationEvent(this, false, StarvationPriority), 5313203Sgabeblack@google.com _elaborationDone(false), _started(false), _stopNow(false), 5413702Sgabeblack@google.com _status(StatusOther), maxTick(::MaxTick), 5513702Sgabeblack@google.com maxTickEvent(this, false, MaxTickPriority), 5613245Sgabeblack@google.com timeAdvancesEvent(this, false, TimeAdvancesPriority), _numCycles(0), 5713702Sgabeblack@google.com _changeStamp(0), _current(nullptr), initDone(false), runToTime(true), 5813702Sgabeblack@google.com runOnce(false) 5912954Sgabeblack@google.com{} 6012953Sgabeblack@google.com 6113072Sgabeblack@google.comScheduler::~Scheduler() 6213072Sgabeblack@google.com{ 6313072Sgabeblack@google.com // Clear out everything that belongs to us to make sure nobody tries to 6413072Sgabeblack@google.com // clear themselves out after the scheduler goes away. 6513076Sgabeblack@google.com clear(); 6613076Sgabeblack@google.com} 6713072Sgabeblack@google.com 6813076Sgabeblack@google.comvoid 6913076Sgabeblack@google.comScheduler::clear() 7013076Sgabeblack@google.com{ 7113072Sgabeblack@google.com // Delta notifications. 7213144Sgabeblack@google.com while (!deltas.empty()) 7313144Sgabeblack@google.com deltas.front()->deschedule(); 7413072Sgabeblack@google.com 7513072Sgabeblack@google.com // Timed notifications. 7613076Sgabeblack@google.com for (auto &tsp: timeSlots) { 7713076Sgabeblack@google.com TimeSlot *&ts = tsp.second; 7813144Sgabeblack@google.com while (!ts->events.empty()) 7913144Sgabeblack@google.com ts->events.front()->deschedule(); 8013088Sgabeblack@google.com deschedule(ts); 8113072Sgabeblack@google.com } 8213076Sgabeblack@google.com timeSlots.clear(); 8313072Sgabeblack@google.com 8413072Sgabeblack@google.com // gem5 events. 8513072Sgabeblack@google.com if (readyEvent.scheduled()) 8613088Sgabeblack@google.com deschedule(&readyEvent); 8713072Sgabeblack@google.com if (pauseEvent.scheduled()) 8813088Sgabeblack@google.com deschedule(&pauseEvent); 8913072Sgabeblack@google.com if (stopEvent.scheduled()) 9013088Sgabeblack@google.com deschedule(&stopEvent); 9113072Sgabeblack@google.com if (starvationEvent.scheduled()) 9213088Sgabeblack@google.com deschedule(&starvationEvent); 9313072Sgabeblack@google.com if (maxTickEvent.scheduled()) 9413088Sgabeblack@google.com deschedule(&maxTickEvent); 9513245Sgabeblack@google.com if (timeAdvancesEvent.scheduled()) 9613245Sgabeblack@google.com deschedule(&timeAdvancesEvent); 9713072Sgabeblack@google.com 9813072Sgabeblack@google.com Process *p; 9913072Sgabeblack@google.com while ((p = initList.getNext())) 10013072Sgabeblack@google.com p->popListNode(); 10113176Sgabeblack@google.com while ((p = readyListMethods.getNext())) 10213176Sgabeblack@google.com p->popListNode(); 10313176Sgabeblack@google.com while ((p = readyListThreads.getNext())) 10413072Sgabeblack@google.com p->popListNode(); 10513072Sgabeblack@google.com 10613072Sgabeblack@google.com Channel *c; 10713072Sgabeblack@google.com while ((c = updateList.getNext())) 10813072Sgabeblack@google.com c->popListNode(); 10913072Sgabeblack@google.com} 11013072Sgabeblack@google.com 11112953Sgabeblack@google.comvoid 11213067Sgabeblack@google.comScheduler::initPhase() 11312953Sgabeblack@google.com{ 11413488Sgabeblack@google.com runUpdate(); 11513488Sgabeblack@google.com 11613194Sgabeblack@google.com for (Process *p = initList.getNext(); p; p = initList.getNext()) { 11712957Sgabeblack@google.com p->popListNode(); 11813180Sgabeblack@google.com 11913194Sgabeblack@google.com if (p->dontInitialize()) { 12013194Sgabeblack@google.com if (!p->hasStaticSensitivities() && !p->internal()) { 12113317Sgabeblack@google.com SC_REPORT_WARNING(sc_core::SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, 12213317Sgabeblack@google.com p->name()); 12313194Sgabeblack@google.com } 12413194Sgabeblack@google.com } else { 12513194Sgabeblack@google.com p->ready(); 12613180Sgabeblack@google.com } 12712957Sgabeblack@google.com } 12812957Sgabeblack@google.com 12913186Sgabeblack@google.com runDelta(); 13013067Sgabeblack@google.com 13112985Sgabeblack@google.com for (auto ets: eventsToSchedule) 13212985Sgabeblack@google.com eq->schedule(ets.first, ets.second); 13312985Sgabeblack@google.com eventsToSchedule.clear(); 13412985Sgabeblack@google.com 13513068Sgabeblack@google.com if (_started) { 13613096Sgabeblack@google.com if (!runToTime && starved()) 13713068Sgabeblack@google.com scheduleStarvationEvent(); 13813069Sgabeblack@google.com kernel->status(::sc_core::SC_RUNNING); 13913068Sgabeblack@google.com } 14012961Sgabeblack@google.com 14113067Sgabeblack@google.com initDone = true; 14213186Sgabeblack@google.com 14313186Sgabeblack@google.com status(StatusOther); 14413245Sgabeblack@google.com 14513245Sgabeblack@google.com scheduleTimeAdvancesEvent(); 14612957Sgabeblack@google.com} 14712957Sgabeblack@google.com 14812957Sgabeblack@google.comvoid 14912957Sgabeblack@google.comScheduler::reg(Process *p) 15012957Sgabeblack@google.com{ 15113067Sgabeblack@google.com if (initDone) { 15213194Sgabeblack@google.com // If not marked as dontInitialize, mark as ready. 15313194Sgabeblack@google.com if (!p->dontInitialize()) 15413194Sgabeblack@google.com p->ready(); 15512957Sgabeblack@google.com } else { 15612957Sgabeblack@google.com // Otherwise, record that this process should be initialized once we 15712957Sgabeblack@google.com // get there. 15812957Sgabeblack@google.com initList.pushLast(p); 15912957Sgabeblack@google.com } 16012957Sgabeblack@google.com} 16112957Sgabeblack@google.com 16212957Sgabeblack@google.comvoid 16312953Sgabeblack@google.comScheduler::yield() 16412953Sgabeblack@google.com{ 16513176Sgabeblack@google.com // Pull a process from the active list. 16613209Sgabeblack@google.com _current = getNextReady(); 16712953Sgabeblack@google.com if (!_current) { 16812953Sgabeblack@google.com // There are no more processes, so return control to evaluate. 16912953Sgabeblack@google.com Fiber::primaryFiber()->run(); 17012953Sgabeblack@google.com } else { 17112953Sgabeblack@google.com _current->popListNode(); 17213328Sgabeblack@google.com _current->scheduled(false); 17312953Sgabeblack@google.com // Switch to whatever Fiber is supposed to run this process. All 17412953Sgabeblack@google.com // Fibers which aren't running should be parked at this line. 17512953Sgabeblack@google.com _current->fiber()->run(); 17612961Sgabeblack@google.com // If the current process needs to be manually started, start it. 17713093Sgabeblack@google.com if (_current && _current->needsStart()) { 17813093Sgabeblack@google.com _current->needsStart(false); 17913308Sgabeblack@google.com // If a process hasn't started yet, "resetting" it just starts it 18013308Sgabeblack@google.com // and signals its reset event. 18113308Sgabeblack@google.com if (_current->inReset()) 18213308Sgabeblack@google.com _current->resetEvent().notify(); 18313182Sgabeblack@google.com try { 18413182Sgabeblack@google.com _current->run(); 18513182Sgabeblack@google.com } catch (...) { 18613701Sgabeblack@google.com throwUp(); 18713182Sgabeblack@google.com } 18813093Sgabeblack@google.com } 18912953Sgabeblack@google.com } 19013259Sgabeblack@google.com if (_current && !_current->needsStart()) { 19113259Sgabeblack@google.com if (_current->excWrapper) { 19213259Sgabeblack@google.com auto ew = _current->excWrapper; 19313259Sgabeblack@google.com _current->excWrapper = nullptr; 19413259Sgabeblack@google.com ew->throw_it(); 19513260Sgabeblack@google.com } else if (_current->inReset()) { 19613259Sgabeblack@google.com _current->reset(false); 19713259Sgabeblack@google.com } 19812995Sgabeblack@google.com } 19912953Sgabeblack@google.com} 20012953Sgabeblack@google.com 20112953Sgabeblack@google.comvoid 20212954Sgabeblack@google.comScheduler::ready(Process *p) 20312953Sgabeblack@google.com{ 20413154Sgabeblack@google.com if (_stopNow) 20513154Sgabeblack@google.com return; 20613154Sgabeblack@google.com 20713328Sgabeblack@google.com p->scheduled(true); 20813328Sgabeblack@google.com 20913176Sgabeblack@google.com if (p->procKind() == ::sc_core::SC_METHOD_PROC_) 21013176Sgabeblack@google.com readyListMethods.pushLast(p); 21112954Sgabeblack@google.com else 21213176Sgabeblack@google.com readyListThreads.pushLast(p); 21312953Sgabeblack@google.com 21413244Sgabeblack@google.com if (!inEvaluate()) 21513244Sgabeblack@google.com scheduleReadyEvent(); 21612954Sgabeblack@google.com} 21712954Sgabeblack@google.com 21812954Sgabeblack@google.comvoid 21913133Sgabeblack@google.comScheduler::resume(Process *p) 22013133Sgabeblack@google.com{ 22113133Sgabeblack@google.com if (initDone) 22213133Sgabeblack@google.com ready(p); 22313133Sgabeblack@google.com else 22413133Sgabeblack@google.com initList.pushLast(p); 22513133Sgabeblack@google.com} 22613133Sgabeblack@google.com 22713133Sgabeblack@google.combool 22813176Sgabeblack@google.comlistContains(ListNode *list, ListNode *target) 22913176Sgabeblack@google.com{ 23013176Sgabeblack@google.com ListNode *n = list->nextListNode; 23113176Sgabeblack@google.com while (n != list) 23213176Sgabeblack@google.com if (n == target) 23313176Sgabeblack@google.com return true; 23413176Sgabeblack@google.com return false; 23513176Sgabeblack@google.com} 23613176Sgabeblack@google.com 23713176Sgabeblack@google.combool 23813133Sgabeblack@google.comScheduler::suspend(Process *p) 23913133Sgabeblack@google.com{ 24013176Sgabeblack@google.com bool was_ready; 24113133Sgabeblack@google.com if (initDone) { 24213194Sgabeblack@google.com // After initialization, check if we're on a ready list. 24313176Sgabeblack@google.com was_ready = (p->nextListNode != nullptr); 24413133Sgabeblack@google.com p->popListNode(); 24513133Sgabeblack@google.com } else { 24613194Sgabeblack@google.com // Nothing is ready before init. 24713194Sgabeblack@google.com was_ready = false; 24813133Sgabeblack@google.com } 24913176Sgabeblack@google.com return was_ready; 25013133Sgabeblack@google.com} 25113133Sgabeblack@google.com 25213133Sgabeblack@google.comvoid 25312954Sgabeblack@google.comScheduler::requestUpdate(Channel *c) 25412954Sgabeblack@google.com{ 25512954Sgabeblack@google.com updateList.pushLast(c); 25613244Sgabeblack@google.com if (!inEvaluate()) 25713244Sgabeblack@google.com scheduleReadyEvent(); 25812954Sgabeblack@google.com} 25912954Sgabeblack@google.com 26012954Sgabeblack@google.comvoid 26112954Sgabeblack@google.comScheduler::scheduleReadyEvent() 26212954Sgabeblack@google.com{ 26312954Sgabeblack@google.com // Schedule the evaluate and update phases. 26412954Sgabeblack@google.com if (!readyEvent.scheduled()) { 26513069Sgabeblack@google.com schedule(&readyEvent); 26612987Sgabeblack@google.com if (starvationEvent.scheduled()) 26713069Sgabeblack@google.com deschedule(&starvationEvent); 26812987Sgabeblack@google.com } 26912987Sgabeblack@google.com} 27012987Sgabeblack@google.com 27112987Sgabeblack@google.comvoid 27212987Sgabeblack@google.comScheduler::scheduleStarvationEvent() 27312987Sgabeblack@google.com{ 27412987Sgabeblack@google.com if (!starvationEvent.scheduled()) { 27513069Sgabeblack@google.com schedule(&starvationEvent); 27612987Sgabeblack@google.com if (readyEvent.scheduled()) 27713069Sgabeblack@google.com deschedule(&readyEvent); 27812954Sgabeblack@google.com } 27912954Sgabeblack@google.com} 28012954Sgabeblack@google.com 28112954Sgabeblack@google.comvoid 28212954Sgabeblack@google.comScheduler::runReady() 28312954Sgabeblack@google.com{ 28413245Sgabeblack@google.com scheduleTimeAdvancesEvent(); 28513245Sgabeblack@google.com 28613176Sgabeblack@google.com bool empty = readyListMethods.empty() && readyListThreads.empty(); 28713140Sgabeblack@google.com lastReadyTick = getCurTick(); 28812954Sgabeblack@google.com 28912954Sgabeblack@google.com // The evaluation phase. 29013245Sgabeblack@google.com status(StatusEvaluate); 29112953Sgabeblack@google.com do { 29213209Sgabeblack@google.com yield(); 29313209Sgabeblack@google.com } while (getNextReady()); 29413275Sgabeblack@google.com _current = nullptr; 29512954Sgabeblack@google.com 29613140Sgabeblack@google.com if (!empty) { 29712954Sgabeblack@google.com _numCycles++; 29813140Sgabeblack@google.com _changeStamp++; 29913140Sgabeblack@google.com } 30012954Sgabeblack@google.com 30113244Sgabeblack@google.com if (_stopNow) { 30213244Sgabeblack@google.com status(StatusOther); 30313154Sgabeblack@google.com return; 30413244Sgabeblack@google.com } 30513154Sgabeblack@google.com 30613186Sgabeblack@google.com runUpdate(); 30713245Sgabeblack@google.com if (!traceFiles.empty()) 30813245Sgabeblack@google.com trace(true); 30913186Sgabeblack@google.com runDelta(); 31013061Sgabeblack@google.com 31113096Sgabeblack@google.com if (!runToTime && starved()) 31213096Sgabeblack@google.com scheduleStarvationEvent(); 31313096Sgabeblack@google.com 31413064Sgabeblack@google.com if (runOnce) 31513064Sgabeblack@google.com schedulePause(); 31613186Sgabeblack@google.com 31713186Sgabeblack@google.com status(StatusOther); 31812953Sgabeblack@google.com} 31912953Sgabeblack@google.com 32012953Sgabeblack@google.comvoid 32113186Sgabeblack@google.comScheduler::runUpdate() 32212953Sgabeblack@google.com{ 32313186Sgabeblack@google.com status(StatusUpdate); 32413186Sgabeblack@google.com 32513188Sgabeblack@google.com try { 32613188Sgabeblack@google.com Channel *channel = updateList.getNext(); 32713188Sgabeblack@google.com while (channel) { 32813188Sgabeblack@google.com channel->popListNode(); 32913188Sgabeblack@google.com channel->update(); 33013188Sgabeblack@google.com channel = updateList.getNext(); 33113188Sgabeblack@google.com } 33213188Sgabeblack@google.com } catch (...) { 33313701Sgabeblack@google.com throwUp(); 33412954Sgabeblack@google.com } 33512953Sgabeblack@google.com} 33612953Sgabeblack@google.com 33712961Sgabeblack@google.comvoid 33813186Sgabeblack@google.comScheduler::runDelta() 33913186Sgabeblack@google.com{ 34013186Sgabeblack@google.com status(StatusDelta); 34113188Sgabeblack@google.com 34213188Sgabeblack@google.com try { 34313188Sgabeblack@google.com while (!deltas.empty()) 34413289Sgabeblack@google.com deltas.back()->run(); 34513188Sgabeblack@google.com } catch (...) { 34613701Sgabeblack@google.com throwUp(); 34713188Sgabeblack@google.com } 34813186Sgabeblack@google.com} 34913186Sgabeblack@google.com 35013186Sgabeblack@google.comvoid 35112961Sgabeblack@google.comScheduler::pause() 35212961Sgabeblack@google.com{ 35313186Sgabeblack@google.com status(StatusPaused); 35412982Sgabeblack@google.com kernel->status(::sc_core::SC_PAUSED); 35513061Sgabeblack@google.com runOnce = false; 35613703Sgabeblack@google.com if (scMainFiber.called()) { 35713703Sgabeblack@google.com if (!scMainFiber.finished()) 35813703Sgabeblack@google.com scMainFiber.run(); 35913703Sgabeblack@google.com } else { 36013703Sgabeblack@google.com if (scMainFiber.finished()) 36113703Sgabeblack@google.com fatal("Pausing systemc after sc_main completed."); 36213703Sgabeblack@google.com else 36313703Sgabeblack@google.com exitSimLoopNow("systemc pause"); 36413703Sgabeblack@google.com } 36512961Sgabeblack@google.com} 36612961Sgabeblack@google.com 36712961Sgabeblack@google.comvoid 36812961Sgabeblack@google.comScheduler::stop() 36912961Sgabeblack@google.com{ 37013186Sgabeblack@google.com status(StatusStopped); 37112982Sgabeblack@google.com kernel->stop(); 37213074Sgabeblack@google.com 37313076Sgabeblack@google.com clear(); 37413074Sgabeblack@google.com 37513061Sgabeblack@google.com runOnce = false; 37613703Sgabeblack@google.com if (scMainFiber.called()) { 37713703Sgabeblack@google.com if (!scMainFiber.finished()) 37813703Sgabeblack@google.com scMainFiber.run(); 37913703Sgabeblack@google.com } else { 38013703Sgabeblack@google.com if (scMainFiber.finished()) 38113703Sgabeblack@google.com fatal("Stopping systemc after sc_main completed."); 38213703Sgabeblack@google.com else 38313703Sgabeblack@google.com exitSimLoopNow("systemc stop"); 38413703Sgabeblack@google.com } 38512961Sgabeblack@google.com} 38612961Sgabeblack@google.com 38712961Sgabeblack@google.comvoid 38812961Sgabeblack@google.comScheduler::start(Tick max_tick, bool run_to_time) 38912961Sgabeblack@google.com{ 39012961Sgabeblack@google.com _started = true; 39113186Sgabeblack@google.com status(StatusOther); 39212987Sgabeblack@google.com runToTime = run_to_time; 39312961Sgabeblack@google.com 39412961Sgabeblack@google.com maxTick = max_tick; 39513140Sgabeblack@google.com lastReadyTick = getCurTick(); 39612961Sgabeblack@google.com 39713067Sgabeblack@google.com if (initDone) { 39813096Sgabeblack@google.com if (!runToTime && starved()) 39913068Sgabeblack@google.com scheduleStarvationEvent(); 40012982Sgabeblack@google.com kernel->status(::sc_core::SC_RUNNING); 40112982Sgabeblack@google.com } 40212961Sgabeblack@google.com 40313069Sgabeblack@google.com schedule(&maxTickEvent, maxTick); 40413245Sgabeblack@google.com scheduleTimeAdvancesEvent(); 40513069Sgabeblack@google.com 40612961Sgabeblack@google.com // Return to gem5 to let it run events, etc. 40712961Sgabeblack@google.com Fiber::primaryFiber()->run(); 40812961Sgabeblack@google.com 40912961Sgabeblack@google.com if (pauseEvent.scheduled()) 41013088Sgabeblack@google.com deschedule(&pauseEvent); 41112961Sgabeblack@google.com if (stopEvent.scheduled()) 41213088Sgabeblack@google.com deschedule(&stopEvent); 41312961Sgabeblack@google.com if (maxTickEvent.scheduled()) 41413088Sgabeblack@google.com deschedule(&maxTickEvent); 41512987Sgabeblack@google.com if (starvationEvent.scheduled()) 41613088Sgabeblack@google.com deschedule(&starvationEvent); 41713182Sgabeblack@google.com 41813701Sgabeblack@google.com if (_throwUp) { 41913701Sgabeblack@google.com const ::sc_core::sc_report *to_throw = _throwUp; 42013701Sgabeblack@google.com _throwUp = nullptr; 42113182Sgabeblack@google.com throw *to_throw; 42213182Sgabeblack@google.com } 42312961Sgabeblack@google.com} 42412961Sgabeblack@google.com 42512961Sgabeblack@google.comvoid 42613061Sgabeblack@google.comScheduler::oneCycle() 42713061Sgabeblack@google.com{ 42813061Sgabeblack@google.com runOnce = true; 42913095Sgabeblack@google.com scheduleReadyEvent(); 43013061Sgabeblack@google.com start(::MaxTick, false); 43113061Sgabeblack@google.com} 43213061Sgabeblack@google.com 43313061Sgabeblack@google.comvoid 43412961Sgabeblack@google.comScheduler::schedulePause() 43512961Sgabeblack@google.com{ 43612961Sgabeblack@google.com if (pauseEvent.scheduled()) 43712961Sgabeblack@google.com return; 43812961Sgabeblack@google.com 43913088Sgabeblack@google.com schedule(&pauseEvent); 44012961Sgabeblack@google.com} 44112961Sgabeblack@google.com 44212961Sgabeblack@google.comvoid 44313701Sgabeblack@google.comScheduler::throwUp() 44413182Sgabeblack@google.com{ 44513701Sgabeblack@google.com if (scMainFiber.called() && !scMainFiber.finished()) { 44613701Sgabeblack@google.com ::sc_core::sc_report report = reportifyException(); 44713701Sgabeblack@google.com _throwUp = &report; 44813701Sgabeblack@google.com status(StatusOther); 44913701Sgabeblack@google.com scMainFiber.run(); 45013701Sgabeblack@google.com } else { 45113701Sgabeblack@google.com reportHandlerProc(reportifyException(), 45213701Sgabeblack@google.com ::sc_core::sc_report_handler::get_catch_actions()); 45313701Sgabeblack@google.com } 45413182Sgabeblack@google.com} 45513182Sgabeblack@google.com 45613182Sgabeblack@google.comvoid 45712961Sgabeblack@google.comScheduler::scheduleStop(bool finish_delta) 45812961Sgabeblack@google.com{ 45912961Sgabeblack@google.com if (stopEvent.scheduled()) 46012961Sgabeblack@google.com return; 46112961Sgabeblack@google.com 46212961Sgabeblack@google.com if (!finish_delta) { 46313154Sgabeblack@google.com _stopNow = true; 46413076Sgabeblack@google.com // If we're not supposed to finish the delta cycle, flush all 46513076Sgabeblack@google.com // pending activity. 46613076Sgabeblack@google.com clear(); 46712961Sgabeblack@google.com } 46813088Sgabeblack@google.com schedule(&stopEvent); 46912961Sgabeblack@google.com} 47012961Sgabeblack@google.com 47113245Sgabeblack@google.comvoid 47213245Sgabeblack@google.comScheduler::trace(bool delta) 47313245Sgabeblack@google.com{ 47413245Sgabeblack@google.com for (auto tf: traceFiles) 47513245Sgabeblack@google.com tf->trace(delta); 47613245Sgabeblack@google.com} 47713245Sgabeblack@google.com 47812953Sgabeblack@google.comScheduler scheduler; 47913329Sgabeblack@google.comProcess *getCurrentProcess() { return scheduler.current(); } 48012953Sgabeblack@google.com 48113182Sgabeblack@google.comnamespace { 48213182Sgabeblack@google.com 48313182Sgabeblack@google.comvoid 48413182Sgabeblack@google.comthrowingReportHandler(const ::sc_core::sc_report &r, 48513182Sgabeblack@google.com const ::sc_core::sc_actions &) 48613182Sgabeblack@google.com{ 48713182Sgabeblack@google.com throw r; 48813182Sgabeblack@google.com} 48913182Sgabeblack@google.com 49013182Sgabeblack@google.com} // anonymous namespace 49113182Sgabeblack@google.com 49213264Sgabeblack@google.comconst ::sc_core::sc_report 49313182Sgabeblack@google.comreportifyException() 49413182Sgabeblack@google.com{ 49513312Sgabeblack@google.com ::sc_core::sc_report_handler_proc old_handler = reportHandlerProc; 49613182Sgabeblack@google.com ::sc_core::sc_report_handler::set_handler(&throwingReportHandler); 49713182Sgabeblack@google.com 49813182Sgabeblack@google.com try { 49913182Sgabeblack@google.com try { 50013182Sgabeblack@google.com // Rethrow the current exception so we can catch it and throw an 50113182Sgabeblack@google.com // sc_report instead if it's not a type we recognize/can handle. 50213182Sgabeblack@google.com throw; 50313182Sgabeblack@google.com } catch (const ::sc_core::sc_report &) { 50413182Sgabeblack@google.com // It's already a sc_report, so nothing to do. 50513182Sgabeblack@google.com throw; 50613182Sgabeblack@google.com } catch (const ::sc_core::sc_unwind_exception &) { 50713182Sgabeblack@google.com panic("Kill/reset exception escaped a Process::run()"); 50813182Sgabeblack@google.com } catch (const std::exception &e) { 50913317Sgabeblack@google.com SC_REPORT_ERROR( 51013317Sgabeblack@google.com sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, e.what()); 51113182Sgabeblack@google.com } catch (const char *msg) { 51213317Sgabeblack@google.com SC_REPORT_ERROR( 51313317Sgabeblack@google.com sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, msg); 51413182Sgabeblack@google.com } catch (...) { 51513317Sgabeblack@google.com SC_REPORT_ERROR( 51613317Sgabeblack@google.com sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, 51713317Sgabeblack@google.com "UNKNOWN EXCEPTION"); 51813182Sgabeblack@google.com } 51913182Sgabeblack@google.com } catch (const ::sc_core::sc_report &r) { 52013182Sgabeblack@google.com ::sc_core::sc_report_handler::set_handler(old_handler); 52113264Sgabeblack@google.com return r; 52213182Sgabeblack@google.com } 52313182Sgabeblack@google.com panic("No exception thrown in reportifyException."); 52413182Sgabeblack@google.com} 52513182Sgabeblack@google.com 52612953Sgabeblack@google.com} // namespace sc_gem5 527