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
26113901Sgabeblack@google.comScheduler::asyncRequestUpdate(Channel *c)
26213901Sgabeblack@google.com{
26313901Sgabeblack@google.com    std::lock_guard<std::mutex> lock(asyncListMutex);
26413901Sgabeblack@google.com    asyncUpdateList.pushLast(c);
26513901Sgabeblack@google.com}
26613901Sgabeblack@google.com
26713901Sgabeblack@google.comvoid
26812954Sgabeblack@google.comScheduler::scheduleReadyEvent()
26912954Sgabeblack@google.com{
27012954Sgabeblack@google.com    // Schedule the evaluate and update phases.
27112954Sgabeblack@google.com    if (!readyEvent.scheduled()) {
27213069Sgabeblack@google.com        schedule(&readyEvent);
27312987Sgabeblack@google.com        if (starvationEvent.scheduled())
27413069Sgabeblack@google.com            deschedule(&starvationEvent);
27512987Sgabeblack@google.com    }
27612987Sgabeblack@google.com}
27712987Sgabeblack@google.com
27812987Sgabeblack@google.comvoid
27912987Sgabeblack@google.comScheduler::scheduleStarvationEvent()
28012987Sgabeblack@google.com{
28112987Sgabeblack@google.com    if (!starvationEvent.scheduled()) {
28213069Sgabeblack@google.com        schedule(&starvationEvent);
28312987Sgabeblack@google.com        if (readyEvent.scheduled())
28413069Sgabeblack@google.com            deschedule(&readyEvent);
28512954Sgabeblack@google.com    }
28612954Sgabeblack@google.com}
28712954Sgabeblack@google.com
28812954Sgabeblack@google.comvoid
28912954Sgabeblack@google.comScheduler::runReady()
29012954Sgabeblack@google.com{
29113245Sgabeblack@google.com    scheduleTimeAdvancesEvent();
29213245Sgabeblack@google.com
29313176Sgabeblack@google.com    bool empty = readyListMethods.empty() && readyListThreads.empty();
29413140Sgabeblack@google.com    lastReadyTick = getCurTick();
29512954Sgabeblack@google.com
29612954Sgabeblack@google.com    // The evaluation phase.
29713245Sgabeblack@google.com    status(StatusEvaluate);
29812953Sgabeblack@google.com    do {
29913209Sgabeblack@google.com        yield();
30013209Sgabeblack@google.com    } while (getNextReady());
30113275Sgabeblack@google.com    _current = nullptr;
30212954Sgabeblack@google.com
30313140Sgabeblack@google.com    if (!empty) {
30412954Sgabeblack@google.com        _numCycles++;
30513140Sgabeblack@google.com        _changeStamp++;
30613140Sgabeblack@google.com    }
30712954Sgabeblack@google.com
30813244Sgabeblack@google.com    if (_stopNow) {
30913244Sgabeblack@google.com        status(StatusOther);
31013154Sgabeblack@google.com        return;
31113244Sgabeblack@google.com    }
31213154Sgabeblack@google.com
31313186Sgabeblack@google.com    runUpdate();
31413245Sgabeblack@google.com    if (!traceFiles.empty())
31513245Sgabeblack@google.com        trace(true);
31613186Sgabeblack@google.com    runDelta();
31713061Sgabeblack@google.com
31813096Sgabeblack@google.com    if (!runToTime && starved())
31913096Sgabeblack@google.com        scheduleStarvationEvent();
32013096Sgabeblack@google.com
32113064Sgabeblack@google.com    if (runOnce)
32213064Sgabeblack@google.com        schedulePause();
32313186Sgabeblack@google.com
32413186Sgabeblack@google.com    status(StatusOther);
32512953Sgabeblack@google.com}
32612953Sgabeblack@google.com
32712953Sgabeblack@google.comvoid
32813186Sgabeblack@google.comScheduler::runUpdate()
32912953Sgabeblack@google.com{
33013186Sgabeblack@google.com    status(StatusUpdate);
33113901Sgabeblack@google.com    {
33213901Sgabeblack@google.com        std::lock_guard<std::mutex> lock(asyncListMutex);
33313901Sgabeblack@google.com        Channel *channel;
33413901Sgabeblack@google.com        while ((channel = asyncUpdateList.getNext()) != nullptr)
33513901Sgabeblack@google.com            updateList.pushLast(channel);
33613901Sgabeblack@google.com    }
33713186Sgabeblack@google.com
33813188Sgabeblack@google.com    try {
33913188Sgabeblack@google.com        Channel *channel = updateList.getNext();
34013188Sgabeblack@google.com        while (channel) {
34113188Sgabeblack@google.com            channel->popListNode();
34213188Sgabeblack@google.com            channel->update();
34313188Sgabeblack@google.com            channel = updateList.getNext();
34413188Sgabeblack@google.com        }
34513188Sgabeblack@google.com    } catch (...) {
34613701Sgabeblack@google.com        throwUp();
34712954Sgabeblack@google.com    }
34812953Sgabeblack@google.com}
34912953Sgabeblack@google.com
35012961Sgabeblack@google.comvoid
35113186Sgabeblack@google.comScheduler::runDelta()
35213186Sgabeblack@google.com{
35313186Sgabeblack@google.com    status(StatusDelta);
35413188Sgabeblack@google.com
35513188Sgabeblack@google.com    try {
35613188Sgabeblack@google.com        while (!deltas.empty())
35713289Sgabeblack@google.com            deltas.back()->run();
35813188Sgabeblack@google.com    } catch (...) {
35913701Sgabeblack@google.com        throwUp();
36013188Sgabeblack@google.com    }
36113186Sgabeblack@google.com}
36213186Sgabeblack@google.com
36313186Sgabeblack@google.comvoid
36412961Sgabeblack@google.comScheduler::pause()
36512961Sgabeblack@google.com{
36613186Sgabeblack@google.com    status(StatusPaused);
36712982Sgabeblack@google.com    kernel->status(::sc_core::SC_PAUSED);
36813061Sgabeblack@google.com    runOnce = false;
36913703Sgabeblack@google.com    if (scMainFiber.called()) {
37013703Sgabeblack@google.com        if (!scMainFiber.finished())
37113703Sgabeblack@google.com            scMainFiber.run();
37213703Sgabeblack@google.com    } else {
37313703Sgabeblack@google.com        if (scMainFiber.finished())
37413703Sgabeblack@google.com            fatal("Pausing systemc after sc_main completed.");
37513703Sgabeblack@google.com        else
37613703Sgabeblack@google.com            exitSimLoopNow("systemc pause");
37713703Sgabeblack@google.com    }
37812961Sgabeblack@google.com}
37912961Sgabeblack@google.com
38012961Sgabeblack@google.comvoid
38112961Sgabeblack@google.comScheduler::stop()
38212961Sgabeblack@google.com{
38313186Sgabeblack@google.com    status(StatusStopped);
38412982Sgabeblack@google.com    kernel->stop();
38513074Sgabeblack@google.com
38613076Sgabeblack@google.com    clear();
38713074Sgabeblack@google.com
38813061Sgabeblack@google.com    runOnce = false;
38913703Sgabeblack@google.com    if (scMainFiber.called()) {
39013703Sgabeblack@google.com        if (!scMainFiber.finished())
39113703Sgabeblack@google.com            scMainFiber.run();
39213703Sgabeblack@google.com    } else {
39313703Sgabeblack@google.com        if (scMainFiber.finished())
39413703Sgabeblack@google.com            fatal("Stopping systemc after sc_main completed.");
39513703Sgabeblack@google.com        else
39613703Sgabeblack@google.com            exitSimLoopNow("systemc stop");
39713703Sgabeblack@google.com    }
39812961Sgabeblack@google.com}
39912961Sgabeblack@google.com
40012961Sgabeblack@google.comvoid
40112961Sgabeblack@google.comScheduler::start(Tick max_tick, bool run_to_time)
40212961Sgabeblack@google.com{
40312961Sgabeblack@google.com    _started = true;
40413186Sgabeblack@google.com    status(StatusOther);
40512987Sgabeblack@google.com    runToTime = run_to_time;
40612961Sgabeblack@google.com
40712961Sgabeblack@google.com    maxTick = max_tick;
40813140Sgabeblack@google.com    lastReadyTick = getCurTick();
40912961Sgabeblack@google.com
41013067Sgabeblack@google.com    if (initDone) {
41113096Sgabeblack@google.com        if (!runToTime && starved())
41213068Sgabeblack@google.com            scheduleStarvationEvent();
41312982Sgabeblack@google.com        kernel->status(::sc_core::SC_RUNNING);
41412982Sgabeblack@google.com    }
41512961Sgabeblack@google.com
41613069Sgabeblack@google.com    schedule(&maxTickEvent, maxTick);
41713245Sgabeblack@google.com    scheduleTimeAdvancesEvent();
41813069Sgabeblack@google.com
41912961Sgabeblack@google.com    // Return to gem5 to let it run events, etc.
42012961Sgabeblack@google.com    Fiber::primaryFiber()->run();
42112961Sgabeblack@google.com
42212961Sgabeblack@google.com    if (pauseEvent.scheduled())
42313088Sgabeblack@google.com        deschedule(&pauseEvent);
42412961Sgabeblack@google.com    if (stopEvent.scheduled())
42513088Sgabeblack@google.com        deschedule(&stopEvent);
42612961Sgabeblack@google.com    if (maxTickEvent.scheduled())
42713088Sgabeblack@google.com        deschedule(&maxTickEvent);
42812987Sgabeblack@google.com    if (starvationEvent.scheduled())
42913088Sgabeblack@google.com        deschedule(&starvationEvent);
43013182Sgabeblack@google.com
43113701Sgabeblack@google.com    if (_throwUp) {
43213701Sgabeblack@google.com        const ::sc_core::sc_report *to_throw = _throwUp;
43313701Sgabeblack@google.com        _throwUp = nullptr;
43413182Sgabeblack@google.com        throw *to_throw;
43513182Sgabeblack@google.com    }
43612961Sgabeblack@google.com}
43712961Sgabeblack@google.com
43812961Sgabeblack@google.comvoid
43913061Sgabeblack@google.comScheduler::oneCycle()
44013061Sgabeblack@google.com{
44113061Sgabeblack@google.com    runOnce = true;
44213095Sgabeblack@google.com    scheduleReadyEvent();
44313061Sgabeblack@google.com    start(::MaxTick, false);
44413061Sgabeblack@google.com}
44513061Sgabeblack@google.com
44613061Sgabeblack@google.comvoid
44712961Sgabeblack@google.comScheduler::schedulePause()
44812961Sgabeblack@google.com{
44912961Sgabeblack@google.com    if (pauseEvent.scheduled())
45012961Sgabeblack@google.com        return;
45112961Sgabeblack@google.com
45213088Sgabeblack@google.com    schedule(&pauseEvent);
45312961Sgabeblack@google.com}
45412961Sgabeblack@google.com
45512961Sgabeblack@google.comvoid
45613701Sgabeblack@google.comScheduler::throwUp()
45713182Sgabeblack@google.com{
45813701Sgabeblack@google.com    if (scMainFiber.called() && !scMainFiber.finished()) {
45913701Sgabeblack@google.com        ::sc_core::sc_report report = reportifyException();
46013701Sgabeblack@google.com        _throwUp = &report;
46113701Sgabeblack@google.com        status(StatusOther);
46213701Sgabeblack@google.com        scMainFiber.run();
46313701Sgabeblack@google.com    } else {
46413701Sgabeblack@google.com        reportHandlerProc(reportifyException(),
46513701Sgabeblack@google.com                ::sc_core::sc_report_handler::get_catch_actions());
46613701Sgabeblack@google.com    }
46713182Sgabeblack@google.com}
46813182Sgabeblack@google.com
46913182Sgabeblack@google.comvoid
47012961Sgabeblack@google.comScheduler::scheduleStop(bool finish_delta)
47112961Sgabeblack@google.com{
47212961Sgabeblack@google.com    if (stopEvent.scheduled())
47312961Sgabeblack@google.com        return;
47412961Sgabeblack@google.com
47512961Sgabeblack@google.com    if (!finish_delta) {
47613154Sgabeblack@google.com        _stopNow = true;
47713076Sgabeblack@google.com        // If we're not supposed to finish the delta cycle, flush all
47813076Sgabeblack@google.com        // pending activity.
47913076Sgabeblack@google.com        clear();
48012961Sgabeblack@google.com    }
48113088Sgabeblack@google.com    schedule(&stopEvent);
48212961Sgabeblack@google.com}
48312961Sgabeblack@google.com
48413245Sgabeblack@google.comvoid
48513245Sgabeblack@google.comScheduler::trace(bool delta)
48613245Sgabeblack@google.com{
48713245Sgabeblack@google.com    for (auto tf: traceFiles)
48813245Sgabeblack@google.com        tf->trace(delta);
48913245Sgabeblack@google.com}
49013245Sgabeblack@google.com
49112953Sgabeblack@google.comScheduler scheduler;
49213329Sgabeblack@google.comProcess *getCurrentProcess() { return scheduler.current(); }
49312953Sgabeblack@google.com
49413182Sgabeblack@google.comnamespace {
49513182Sgabeblack@google.com
49613182Sgabeblack@google.comvoid
49713182Sgabeblack@google.comthrowingReportHandler(const ::sc_core::sc_report &r,
49813182Sgabeblack@google.com                      const ::sc_core::sc_actions &)
49913182Sgabeblack@google.com{
50013182Sgabeblack@google.com    throw r;
50113182Sgabeblack@google.com}
50213182Sgabeblack@google.com
50313182Sgabeblack@google.com} // anonymous namespace
50413182Sgabeblack@google.com
50513264Sgabeblack@google.comconst ::sc_core::sc_report
50613182Sgabeblack@google.comreportifyException()
50713182Sgabeblack@google.com{
50813312Sgabeblack@google.com    ::sc_core::sc_report_handler_proc old_handler = reportHandlerProc;
50913182Sgabeblack@google.com    ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);
51013182Sgabeblack@google.com
51113182Sgabeblack@google.com    try {
51213182Sgabeblack@google.com        try {
51313182Sgabeblack@google.com            // Rethrow the current exception so we can catch it and throw an
51413182Sgabeblack@google.com            // sc_report instead if it's not a type we recognize/can handle.
51513182Sgabeblack@google.com            throw;
51613182Sgabeblack@google.com        } catch (const ::sc_core::sc_report &) {
51713182Sgabeblack@google.com            // It's already a sc_report, so nothing to do.
51813182Sgabeblack@google.com            throw;
51913182Sgabeblack@google.com        } catch (const ::sc_core::sc_unwind_exception &) {
52013182Sgabeblack@google.com            panic("Kill/reset exception escaped a Process::run()");
52113182Sgabeblack@google.com        } catch (const std::exception &e) {
52213317Sgabeblack@google.com            SC_REPORT_ERROR(
52313317Sgabeblack@google.com                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, e.what());
52413182Sgabeblack@google.com        } catch (const char *msg) {
52513317Sgabeblack@google.com            SC_REPORT_ERROR(
52613317Sgabeblack@google.com                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, msg);
52713182Sgabeblack@google.com        } catch (...) {
52813317Sgabeblack@google.com            SC_REPORT_ERROR(
52913317Sgabeblack@google.com                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_,
53013317Sgabeblack@google.com                    "UNKNOWN EXCEPTION");
53113182Sgabeblack@google.com        }
53213182Sgabeblack@google.com    } catch (const ::sc_core::sc_report &r) {
53313182Sgabeblack@google.com        ::sc_core::sc_report_handler::set_handler(old_handler);
53413264Sgabeblack@google.com        return r;
53513182Sgabeblack@google.com    }
53613182Sgabeblack@google.com    panic("No exception thrown in reportifyException.");
53713182Sgabeblack@google.com}
53813182Sgabeblack@google.com
53912953Sgabeblack@google.com} // namespace sc_gem5
540