scheduler.cc revision 13259
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"
3512982Sgabeblack@google.com#include "systemc/core/kernel.hh"
3612982Sgabeblack@google.com#include "systemc/ext/core/sc_main.hh"
3713182Sgabeblack@google.com#include "systemc/ext/utils/sc_report.hh"
3813182Sgabeblack@google.com#include "systemc/ext/utils/sc_report_handler.hh"
3913245Sgabeblack@google.com#include "systemc/utils/tracefile.hh"
4012953Sgabeblack@google.com
4112953Sgabeblack@google.comnamespace sc_gem5
4212953Sgabeblack@google.com{
4312953Sgabeblack@google.com
4412954Sgabeblack@google.comScheduler::Scheduler() :
4512962Sgabeblack@google.com    eq(nullptr), readyEvent(this, false, ReadyPriority),
4612961Sgabeblack@google.com    pauseEvent(this, false, PausePriority),
4712961Sgabeblack@google.com    stopEvent(this, false, StopPriority),
4813182Sgabeblack@google.com    scMain(nullptr), _throwToScMain(nullptr),
4912987Sgabeblack@google.com    starvationEvent(this, false, StarvationPriority),
5013203Sgabeblack@google.com    _elaborationDone(false), _started(false), _stopNow(false),
5113203Sgabeblack@google.com    _status(StatusOther), maxTickEvent(this, false, MaxTickPriority),
5213245Sgabeblack@google.com    timeAdvancesEvent(this, false, TimeAdvancesPriority), _numCycles(0),
5313245Sgabeblack@google.com    _changeStamp(0), _current(nullptr), initDone(false), runOnce(false)
5412954Sgabeblack@google.com{}
5512953Sgabeblack@google.com
5613072Sgabeblack@google.comScheduler::~Scheduler()
5713072Sgabeblack@google.com{
5813072Sgabeblack@google.com    // Clear out everything that belongs to us to make sure nobody tries to
5913072Sgabeblack@google.com    // clear themselves out after the scheduler goes away.
6013076Sgabeblack@google.com    clear();
6113076Sgabeblack@google.com}
6213072Sgabeblack@google.com
6313076Sgabeblack@google.comvoid
6413076Sgabeblack@google.comScheduler::clear()
6513076Sgabeblack@google.com{
6613072Sgabeblack@google.com    // Delta notifications.
6713144Sgabeblack@google.com    while (!deltas.empty())
6813144Sgabeblack@google.com        deltas.front()->deschedule();
6913072Sgabeblack@google.com
7013072Sgabeblack@google.com    // Timed notifications.
7113076Sgabeblack@google.com    for (auto &tsp: timeSlots) {
7213076Sgabeblack@google.com        TimeSlot *&ts = tsp.second;
7313144Sgabeblack@google.com        while (!ts->events.empty())
7413144Sgabeblack@google.com            ts->events.front()->deschedule();
7513088Sgabeblack@google.com        deschedule(ts);
7613072Sgabeblack@google.com    }
7713076Sgabeblack@google.com    timeSlots.clear();
7813072Sgabeblack@google.com
7913072Sgabeblack@google.com    // gem5 events.
8013072Sgabeblack@google.com    if (readyEvent.scheduled())
8113088Sgabeblack@google.com        deschedule(&readyEvent);
8213072Sgabeblack@google.com    if (pauseEvent.scheduled())
8313088Sgabeblack@google.com        deschedule(&pauseEvent);
8413072Sgabeblack@google.com    if (stopEvent.scheduled())
8513088Sgabeblack@google.com        deschedule(&stopEvent);
8613072Sgabeblack@google.com    if (starvationEvent.scheduled())
8713088Sgabeblack@google.com        deschedule(&starvationEvent);
8813072Sgabeblack@google.com    if (maxTickEvent.scheduled())
8913088Sgabeblack@google.com        deschedule(&maxTickEvent);
9013245Sgabeblack@google.com    if (timeAdvancesEvent.scheduled())
9113245Sgabeblack@google.com        deschedule(&timeAdvancesEvent);
9213072Sgabeblack@google.com
9313072Sgabeblack@google.com    Process *p;
9413072Sgabeblack@google.com    while ((p = initList.getNext()))
9513072Sgabeblack@google.com        p->popListNode();
9613176Sgabeblack@google.com    while ((p = readyListMethods.getNext()))
9713176Sgabeblack@google.com        p->popListNode();
9813176Sgabeblack@google.com    while ((p = readyListThreads.getNext()))
9913072Sgabeblack@google.com        p->popListNode();
10013072Sgabeblack@google.com
10113072Sgabeblack@google.com    Channel *c;
10213072Sgabeblack@google.com    while ((c = updateList.getNext()))
10313072Sgabeblack@google.com        c->popListNode();
10413072Sgabeblack@google.com}
10513072Sgabeblack@google.com
10612953Sgabeblack@google.comvoid
10713067Sgabeblack@google.comScheduler::initPhase()
10812953Sgabeblack@google.com{
10913194Sgabeblack@google.com    for (Process *p = initList.getNext(); p; p = initList.getNext()) {
11012957Sgabeblack@google.com        p->popListNode();
11113180Sgabeblack@google.com
11213194Sgabeblack@google.com        if (p->dontInitialize()) {
11313194Sgabeblack@google.com            if (!p->hasStaticSensitivities() && !p->internal()) {
11413194Sgabeblack@google.com                SC_REPORT_WARNING(
11513194Sgabeblack@google.com                        "(W558) disable() or dont_initialize() called on "
11613194Sgabeblack@google.com                        "process with no static sensitivity, it will be "
11713194Sgabeblack@google.com                        "orphaned", p->name());
11813194Sgabeblack@google.com            }
11913194Sgabeblack@google.com        } else {
12013194Sgabeblack@google.com            p->ready();
12113180Sgabeblack@google.com        }
12212957Sgabeblack@google.com    }
12312957Sgabeblack@google.com
12413186Sgabeblack@google.com    runUpdate();
12513186Sgabeblack@google.com    runDelta();
12613067Sgabeblack@google.com
12712985Sgabeblack@google.com    for (auto ets: eventsToSchedule)
12812985Sgabeblack@google.com        eq->schedule(ets.first, ets.second);
12912985Sgabeblack@google.com    eventsToSchedule.clear();
13012985Sgabeblack@google.com
13113068Sgabeblack@google.com    if (_started) {
13213096Sgabeblack@google.com        if (!runToTime && starved())
13313068Sgabeblack@google.com            scheduleStarvationEvent();
13413069Sgabeblack@google.com        kernel->status(::sc_core::SC_RUNNING);
13513068Sgabeblack@google.com    }
13612961Sgabeblack@google.com
13713067Sgabeblack@google.com    initDone = true;
13813186Sgabeblack@google.com
13913186Sgabeblack@google.com    status(StatusOther);
14013245Sgabeblack@google.com
14113245Sgabeblack@google.com    scheduleTimeAdvancesEvent();
14212957Sgabeblack@google.com}
14312957Sgabeblack@google.com
14412957Sgabeblack@google.comvoid
14512957Sgabeblack@google.comScheduler::reg(Process *p)
14612957Sgabeblack@google.com{
14713067Sgabeblack@google.com    if (initDone) {
14813194Sgabeblack@google.com        // If not marked as dontInitialize, mark as ready.
14913194Sgabeblack@google.com        if (!p->dontInitialize())
15013194Sgabeblack@google.com            p->ready();
15112957Sgabeblack@google.com    } else {
15212957Sgabeblack@google.com        // Otherwise, record that this process should be initialized once we
15312957Sgabeblack@google.com        // get there.
15412957Sgabeblack@google.com        initList.pushLast(p);
15512957Sgabeblack@google.com    }
15612957Sgabeblack@google.com}
15712957Sgabeblack@google.com
15812957Sgabeblack@google.comvoid
15912953Sgabeblack@google.comScheduler::yield()
16012953Sgabeblack@google.com{
16113176Sgabeblack@google.com    // Pull a process from the active list.
16213209Sgabeblack@google.com    _current = getNextReady();
16312953Sgabeblack@google.com    if (!_current) {
16412953Sgabeblack@google.com        // There are no more processes, so return control to evaluate.
16512953Sgabeblack@google.com        Fiber::primaryFiber()->run();
16612953Sgabeblack@google.com    } else {
16712953Sgabeblack@google.com        _current->popListNode();
16812953Sgabeblack@google.com        // Switch to whatever Fiber is supposed to run this process. All
16912953Sgabeblack@google.com        // Fibers which aren't running should be parked at this line.
17012953Sgabeblack@google.com        _current->fiber()->run();
17112961Sgabeblack@google.com        // If the current process needs to be manually started, start it.
17213093Sgabeblack@google.com        if (_current && _current->needsStart()) {
17313093Sgabeblack@google.com            _current->needsStart(false);
17413182Sgabeblack@google.com            try {
17513182Sgabeblack@google.com                _current->run();
17613182Sgabeblack@google.com            } catch (...) {
17713182Sgabeblack@google.com                throwToScMain();
17813182Sgabeblack@google.com            }
17913093Sgabeblack@google.com        }
18012953Sgabeblack@google.com    }
18113259Sgabeblack@google.com    if (_current && !_current->needsStart()) {
18213259Sgabeblack@google.com        if (_current->excWrapper) {
18313259Sgabeblack@google.com            auto ew = _current->excWrapper;
18413259Sgabeblack@google.com            _current->excWrapper = nullptr;
18513259Sgabeblack@google.com            ew->throw_it();
18613259Sgabeblack@google.com        } else if (_current->syncReset()) {
18713259Sgabeblack@google.com            _current->reset(false);
18813259Sgabeblack@google.com        }
18912995Sgabeblack@google.com    }
19012953Sgabeblack@google.com}
19112953Sgabeblack@google.com
19212953Sgabeblack@google.comvoid
19312954Sgabeblack@google.comScheduler::ready(Process *p)
19412953Sgabeblack@google.com{
19513154Sgabeblack@google.com    if (_stopNow)
19613154Sgabeblack@google.com        return;
19713154Sgabeblack@google.com
19813176Sgabeblack@google.com    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
19913176Sgabeblack@google.com        readyListMethods.pushLast(p);
20012954Sgabeblack@google.com    else
20113176Sgabeblack@google.com        readyListThreads.pushLast(p);
20212953Sgabeblack@google.com
20313244Sgabeblack@google.com    if (!inEvaluate())
20413244Sgabeblack@google.com        scheduleReadyEvent();
20512954Sgabeblack@google.com}
20612954Sgabeblack@google.com
20712954Sgabeblack@google.comvoid
20813133Sgabeblack@google.comScheduler::resume(Process *p)
20913133Sgabeblack@google.com{
21013133Sgabeblack@google.com    if (initDone)
21113133Sgabeblack@google.com        ready(p);
21213133Sgabeblack@google.com    else
21313133Sgabeblack@google.com        initList.pushLast(p);
21413133Sgabeblack@google.com}
21513133Sgabeblack@google.com
21613133Sgabeblack@google.combool
21713176Sgabeblack@google.comlistContains(ListNode *list, ListNode *target)
21813176Sgabeblack@google.com{
21913176Sgabeblack@google.com    ListNode *n = list->nextListNode;
22013176Sgabeblack@google.com    while (n != list)
22113176Sgabeblack@google.com        if (n == target)
22213176Sgabeblack@google.com            return true;
22313176Sgabeblack@google.com    return false;
22413176Sgabeblack@google.com}
22513176Sgabeblack@google.com
22613176Sgabeblack@google.combool
22713133Sgabeblack@google.comScheduler::suspend(Process *p)
22813133Sgabeblack@google.com{
22913176Sgabeblack@google.com    bool was_ready;
23013133Sgabeblack@google.com    if (initDone) {
23113194Sgabeblack@google.com        // After initialization, check if we're on a ready list.
23213176Sgabeblack@google.com        was_ready = (p->nextListNode != nullptr);
23313133Sgabeblack@google.com        p->popListNode();
23413133Sgabeblack@google.com    } else {
23513194Sgabeblack@google.com        // Nothing is ready before init.
23613194Sgabeblack@google.com        was_ready = false;
23713133Sgabeblack@google.com    }
23813176Sgabeblack@google.com    return was_ready;
23913133Sgabeblack@google.com}
24013133Sgabeblack@google.com
24113133Sgabeblack@google.comvoid
24212954Sgabeblack@google.comScheduler::requestUpdate(Channel *c)
24312954Sgabeblack@google.com{
24412954Sgabeblack@google.com    updateList.pushLast(c);
24513244Sgabeblack@google.com    if (!inEvaluate())
24613244Sgabeblack@google.com        scheduleReadyEvent();
24712954Sgabeblack@google.com}
24812954Sgabeblack@google.com
24912954Sgabeblack@google.comvoid
25012954Sgabeblack@google.comScheduler::scheduleReadyEvent()
25112954Sgabeblack@google.com{
25212954Sgabeblack@google.com    // Schedule the evaluate and update phases.
25312954Sgabeblack@google.com    if (!readyEvent.scheduled()) {
25413069Sgabeblack@google.com        schedule(&readyEvent);
25512987Sgabeblack@google.com        if (starvationEvent.scheduled())
25613069Sgabeblack@google.com            deschedule(&starvationEvent);
25712987Sgabeblack@google.com    }
25812987Sgabeblack@google.com}
25912987Sgabeblack@google.com
26012987Sgabeblack@google.comvoid
26112987Sgabeblack@google.comScheduler::scheduleStarvationEvent()
26212987Sgabeblack@google.com{
26312987Sgabeblack@google.com    if (!starvationEvent.scheduled()) {
26413069Sgabeblack@google.com        schedule(&starvationEvent);
26512987Sgabeblack@google.com        if (readyEvent.scheduled())
26613069Sgabeblack@google.com            deschedule(&readyEvent);
26712954Sgabeblack@google.com    }
26812954Sgabeblack@google.com}
26912954Sgabeblack@google.com
27012954Sgabeblack@google.comvoid
27112954Sgabeblack@google.comScheduler::runReady()
27212954Sgabeblack@google.com{
27313245Sgabeblack@google.com    scheduleTimeAdvancesEvent();
27413245Sgabeblack@google.com
27513176Sgabeblack@google.com    bool empty = readyListMethods.empty() && readyListThreads.empty();
27613140Sgabeblack@google.com    lastReadyTick = getCurTick();
27712954Sgabeblack@google.com
27812954Sgabeblack@google.com    // The evaluation phase.
27913245Sgabeblack@google.com    status(StatusEvaluate);
28012953Sgabeblack@google.com    do {
28113209Sgabeblack@google.com        yield();
28213209Sgabeblack@google.com    } while (getNextReady());
28312954Sgabeblack@google.com
28413140Sgabeblack@google.com    if (!empty) {
28512954Sgabeblack@google.com        _numCycles++;
28613140Sgabeblack@google.com        _changeStamp++;
28713140Sgabeblack@google.com    }
28812954Sgabeblack@google.com
28913244Sgabeblack@google.com    if (_stopNow) {
29013244Sgabeblack@google.com        status(StatusOther);
29113154Sgabeblack@google.com        return;
29213244Sgabeblack@google.com    }
29313154Sgabeblack@google.com
29413186Sgabeblack@google.com    runUpdate();
29513245Sgabeblack@google.com    if (!traceFiles.empty())
29613245Sgabeblack@google.com        trace(true);
29713186Sgabeblack@google.com    runDelta();
29813061Sgabeblack@google.com
29913096Sgabeblack@google.com    if (!runToTime && starved())
30013096Sgabeblack@google.com        scheduleStarvationEvent();
30113096Sgabeblack@google.com
30213064Sgabeblack@google.com    if (runOnce)
30313064Sgabeblack@google.com        schedulePause();
30413186Sgabeblack@google.com
30513186Sgabeblack@google.com    status(StatusOther);
30612953Sgabeblack@google.com}
30712953Sgabeblack@google.com
30812953Sgabeblack@google.comvoid
30913186Sgabeblack@google.comScheduler::runUpdate()
31012953Sgabeblack@google.com{
31113186Sgabeblack@google.com    status(StatusUpdate);
31213186Sgabeblack@google.com
31313188Sgabeblack@google.com    try {
31413188Sgabeblack@google.com        Channel *channel = updateList.getNext();
31513188Sgabeblack@google.com        while (channel) {
31613188Sgabeblack@google.com            channel->popListNode();
31713188Sgabeblack@google.com            channel->update();
31813188Sgabeblack@google.com            channel = updateList.getNext();
31913188Sgabeblack@google.com        }
32013188Sgabeblack@google.com    } catch (...) {
32113188Sgabeblack@google.com        throwToScMain();
32212954Sgabeblack@google.com    }
32312953Sgabeblack@google.com}
32412953Sgabeblack@google.com
32512961Sgabeblack@google.comvoid
32613186Sgabeblack@google.comScheduler::runDelta()
32713186Sgabeblack@google.com{
32813186Sgabeblack@google.com    status(StatusDelta);
32913188Sgabeblack@google.com
33013188Sgabeblack@google.com    try {
33113188Sgabeblack@google.com        while (!deltas.empty())
33213188Sgabeblack@google.com            deltas.front()->run();
33313188Sgabeblack@google.com    } catch (...) {
33413188Sgabeblack@google.com        throwToScMain();
33513188Sgabeblack@google.com    }
33613186Sgabeblack@google.com}
33713186Sgabeblack@google.com
33813186Sgabeblack@google.comvoid
33912961Sgabeblack@google.comScheduler::pause()
34012961Sgabeblack@google.com{
34113186Sgabeblack@google.com    status(StatusPaused);
34212982Sgabeblack@google.com    kernel->status(::sc_core::SC_PAUSED);
34313061Sgabeblack@google.com    runOnce = false;
34413182Sgabeblack@google.com    if (scMain && !scMain->finished())
34513182Sgabeblack@google.com        scMain->run();
34612961Sgabeblack@google.com}
34712961Sgabeblack@google.com
34812961Sgabeblack@google.comvoid
34912961Sgabeblack@google.comScheduler::stop()
35012961Sgabeblack@google.com{
35113186Sgabeblack@google.com    status(StatusStopped);
35212982Sgabeblack@google.com    kernel->stop();
35313074Sgabeblack@google.com
35413076Sgabeblack@google.com    clear();
35513074Sgabeblack@google.com
35613061Sgabeblack@google.com    runOnce = false;
35713182Sgabeblack@google.com    if (scMain && !scMain->finished())
35813182Sgabeblack@google.com        scMain->run();
35912961Sgabeblack@google.com}
36012961Sgabeblack@google.com
36112961Sgabeblack@google.comvoid
36212961Sgabeblack@google.comScheduler::start(Tick max_tick, bool run_to_time)
36312961Sgabeblack@google.com{
36412961Sgabeblack@google.com    // We should be running from sc_main. Keep track of that Fiber to return
36512961Sgabeblack@google.com    // to later.
36612961Sgabeblack@google.com    scMain = Fiber::currentFiber();
36712961Sgabeblack@google.com
36812961Sgabeblack@google.com    _started = true;
36913186Sgabeblack@google.com    status(StatusOther);
37012987Sgabeblack@google.com    runToTime = run_to_time;
37112961Sgabeblack@google.com
37212961Sgabeblack@google.com    maxTick = max_tick;
37313140Sgabeblack@google.com    lastReadyTick = getCurTick();
37412961Sgabeblack@google.com
37513067Sgabeblack@google.com    if (initDone) {
37613096Sgabeblack@google.com        if (!runToTime && starved())
37713068Sgabeblack@google.com            scheduleStarvationEvent();
37812982Sgabeblack@google.com        kernel->status(::sc_core::SC_RUNNING);
37912982Sgabeblack@google.com    }
38012961Sgabeblack@google.com
38113069Sgabeblack@google.com    schedule(&maxTickEvent, maxTick);
38213245Sgabeblack@google.com    scheduleTimeAdvancesEvent();
38313069Sgabeblack@google.com
38412961Sgabeblack@google.com    // Return to gem5 to let it run events, etc.
38512961Sgabeblack@google.com    Fiber::primaryFiber()->run();
38612961Sgabeblack@google.com
38712961Sgabeblack@google.com    if (pauseEvent.scheduled())
38813088Sgabeblack@google.com        deschedule(&pauseEvent);
38912961Sgabeblack@google.com    if (stopEvent.scheduled())
39013088Sgabeblack@google.com        deschedule(&stopEvent);
39112961Sgabeblack@google.com    if (maxTickEvent.scheduled())
39213088Sgabeblack@google.com        deschedule(&maxTickEvent);
39312987Sgabeblack@google.com    if (starvationEvent.scheduled())
39413088Sgabeblack@google.com        deschedule(&starvationEvent);
39513182Sgabeblack@google.com
39613182Sgabeblack@google.com    if (_throwToScMain) {
39713182Sgabeblack@google.com        const ::sc_core::sc_report *to_throw = _throwToScMain;
39813182Sgabeblack@google.com        _throwToScMain = nullptr;
39913182Sgabeblack@google.com        throw *to_throw;
40013182Sgabeblack@google.com    }
40112961Sgabeblack@google.com}
40212961Sgabeblack@google.com
40312961Sgabeblack@google.comvoid
40413061Sgabeblack@google.comScheduler::oneCycle()
40513061Sgabeblack@google.com{
40613061Sgabeblack@google.com    runOnce = true;
40713095Sgabeblack@google.com    scheduleReadyEvent();
40813061Sgabeblack@google.com    start(::MaxTick, false);
40913061Sgabeblack@google.com}
41013061Sgabeblack@google.com
41113061Sgabeblack@google.comvoid
41212961Sgabeblack@google.comScheduler::schedulePause()
41312961Sgabeblack@google.com{
41412961Sgabeblack@google.com    if (pauseEvent.scheduled())
41512961Sgabeblack@google.com        return;
41612961Sgabeblack@google.com
41713088Sgabeblack@google.com    schedule(&pauseEvent);
41812961Sgabeblack@google.com}
41912961Sgabeblack@google.com
42012961Sgabeblack@google.comvoid
42113182Sgabeblack@google.comScheduler::throwToScMain(const ::sc_core::sc_report *r)
42213182Sgabeblack@google.com{
42313182Sgabeblack@google.com    if (!r)
42413182Sgabeblack@google.com        r = reportifyException();
42513182Sgabeblack@google.com    _throwToScMain = r;
42613188Sgabeblack@google.com    status(StatusOther);
42713182Sgabeblack@google.com    scMain->run();
42813182Sgabeblack@google.com}
42913182Sgabeblack@google.com
43013182Sgabeblack@google.comvoid
43112961Sgabeblack@google.comScheduler::scheduleStop(bool finish_delta)
43212961Sgabeblack@google.com{
43312961Sgabeblack@google.com    if (stopEvent.scheduled())
43412961Sgabeblack@google.com        return;
43512961Sgabeblack@google.com
43612961Sgabeblack@google.com    if (!finish_delta) {
43713154Sgabeblack@google.com        _stopNow = true;
43813076Sgabeblack@google.com        // If we're not supposed to finish the delta cycle, flush all
43913076Sgabeblack@google.com        // pending activity.
44013076Sgabeblack@google.com        clear();
44112961Sgabeblack@google.com    }
44213088Sgabeblack@google.com    schedule(&stopEvent);
44312961Sgabeblack@google.com}
44412961Sgabeblack@google.com
44513245Sgabeblack@google.comvoid
44613245Sgabeblack@google.comScheduler::trace(bool delta)
44713245Sgabeblack@google.com{
44813245Sgabeblack@google.com    for (auto tf: traceFiles)
44913245Sgabeblack@google.com        tf->trace(delta);
45013245Sgabeblack@google.com}
45113245Sgabeblack@google.com
45212953Sgabeblack@google.comScheduler scheduler;
45312953Sgabeblack@google.com
45413182Sgabeblack@google.comnamespace {
45513182Sgabeblack@google.com
45613182Sgabeblack@google.comvoid
45713182Sgabeblack@google.comthrowingReportHandler(const ::sc_core::sc_report &r,
45813182Sgabeblack@google.com                      const ::sc_core::sc_actions &)
45913182Sgabeblack@google.com{
46013182Sgabeblack@google.com    throw r;
46113182Sgabeblack@google.com}
46213182Sgabeblack@google.com
46313182Sgabeblack@google.com} // anonymous namespace
46413182Sgabeblack@google.com
46513182Sgabeblack@google.comconst ::sc_core::sc_report *
46613182Sgabeblack@google.comreportifyException()
46713182Sgabeblack@google.com{
46813182Sgabeblack@google.com    ::sc_core::sc_report_handler_proc old_handler =
46913182Sgabeblack@google.com        ::sc_core::sc_report_handler::get_handler();
47013182Sgabeblack@google.com    ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);
47113182Sgabeblack@google.com
47213182Sgabeblack@google.com    try {
47313182Sgabeblack@google.com        try {
47413182Sgabeblack@google.com            // Rethrow the current exception so we can catch it and throw an
47513182Sgabeblack@google.com            // sc_report instead if it's not a type we recognize/can handle.
47613182Sgabeblack@google.com            throw;
47713182Sgabeblack@google.com        } catch (const ::sc_core::sc_report &) {
47813182Sgabeblack@google.com            // It's already a sc_report, so nothing to do.
47913182Sgabeblack@google.com            throw;
48013182Sgabeblack@google.com        } catch (const ::sc_core::sc_unwind_exception &) {
48113182Sgabeblack@google.com            panic("Kill/reset exception escaped a Process::run()");
48213182Sgabeblack@google.com        } catch (const std::exception &e) {
48313182Sgabeblack@google.com            SC_REPORT_ERROR("uncaught exception", e.what());
48413182Sgabeblack@google.com        } catch (const char *msg) {
48513182Sgabeblack@google.com            SC_REPORT_ERROR("uncaught exception", msg);
48613182Sgabeblack@google.com        } catch (...) {
48713182Sgabeblack@google.com            SC_REPORT_ERROR("uncaught exception", "UNKNOWN EXCEPTION");
48813182Sgabeblack@google.com        }
48913182Sgabeblack@google.com    } catch (const ::sc_core::sc_report &r) {
49013182Sgabeblack@google.com        ::sc_core::sc_report_handler::set_handler(old_handler);
49113182Sgabeblack@google.com        return &r;
49213182Sgabeblack@google.com    }
49313182Sgabeblack@google.com    panic("No exception thrown in reportifyException.");
49413182Sgabeblack@google.com}
49513182Sgabeblack@google.com
49612953Sgabeblack@google.com} // namespace sc_gem5
497