scheduler.cc revision 13209
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"
3912953Sgabeblack@google.com
4012953Sgabeblack@google.comnamespace sc_gem5
4112953Sgabeblack@google.com{
4212953Sgabeblack@google.com
4312954Sgabeblack@google.comScheduler::Scheduler() :
4412962Sgabeblack@google.com    eq(nullptr), readyEvent(this, false, ReadyPriority),
4512961Sgabeblack@google.com    pauseEvent(this, false, PausePriority),
4612961Sgabeblack@google.com    stopEvent(this, false, StopPriority),
4713182Sgabeblack@google.com    scMain(nullptr), _throwToScMain(nullptr),
4812987Sgabeblack@google.com    starvationEvent(this, false, StarvationPriority),
4913203Sgabeblack@google.com    _elaborationDone(false), _started(false), _stopNow(false),
5013203Sgabeblack@google.com    _status(StatusOther), maxTickEvent(this, false, MaxTickPriority),
5113140Sgabeblack@google.com    _numCycles(0), _changeStamp(0), _current(nullptr), initDone(false),
5213209Sgabeblack@google.com    runOnce(false)
5312954Sgabeblack@google.com{}
5412953Sgabeblack@google.com
5513072Sgabeblack@google.comScheduler::~Scheduler()
5613072Sgabeblack@google.com{
5713072Sgabeblack@google.com    // Clear out everything that belongs to us to make sure nobody tries to
5813072Sgabeblack@google.com    // clear themselves out after the scheduler goes away.
5913076Sgabeblack@google.com    clear();
6013076Sgabeblack@google.com}
6113072Sgabeblack@google.com
6213076Sgabeblack@google.comvoid
6313076Sgabeblack@google.comScheduler::clear()
6413076Sgabeblack@google.com{
6513072Sgabeblack@google.com    // Delta notifications.
6613144Sgabeblack@google.com    while (!deltas.empty())
6713144Sgabeblack@google.com        deltas.front()->deschedule();
6813072Sgabeblack@google.com
6913072Sgabeblack@google.com    // Timed notifications.
7013076Sgabeblack@google.com    for (auto &tsp: timeSlots) {
7113076Sgabeblack@google.com        TimeSlot *&ts = tsp.second;
7213144Sgabeblack@google.com        while (!ts->events.empty())
7313144Sgabeblack@google.com            ts->events.front()->deschedule();
7413088Sgabeblack@google.com        deschedule(ts);
7513072Sgabeblack@google.com    }
7613076Sgabeblack@google.com    timeSlots.clear();
7713072Sgabeblack@google.com
7813072Sgabeblack@google.com    // gem5 events.
7913072Sgabeblack@google.com    if (readyEvent.scheduled())
8013088Sgabeblack@google.com        deschedule(&readyEvent);
8113072Sgabeblack@google.com    if (pauseEvent.scheduled())
8213088Sgabeblack@google.com        deschedule(&pauseEvent);
8313072Sgabeblack@google.com    if (stopEvent.scheduled())
8413088Sgabeblack@google.com        deschedule(&stopEvent);
8513072Sgabeblack@google.com    if (starvationEvent.scheduled())
8613088Sgabeblack@google.com        deschedule(&starvationEvent);
8713072Sgabeblack@google.com    if (maxTickEvent.scheduled())
8813088Sgabeblack@google.com        deschedule(&maxTickEvent);
8913072Sgabeblack@google.com
9013072Sgabeblack@google.com    Process *p;
9113072Sgabeblack@google.com    while ((p = initList.getNext()))
9213072Sgabeblack@google.com        p->popListNode();
9313176Sgabeblack@google.com    while ((p = readyListMethods.getNext()))
9413176Sgabeblack@google.com        p->popListNode();
9513176Sgabeblack@google.com    while ((p = readyListThreads.getNext()))
9613072Sgabeblack@google.com        p->popListNode();
9713072Sgabeblack@google.com
9813072Sgabeblack@google.com    Channel *c;
9913072Sgabeblack@google.com    while ((c = updateList.getNext()))
10013072Sgabeblack@google.com        c->popListNode();
10113072Sgabeblack@google.com}
10213072Sgabeblack@google.com
10312953Sgabeblack@google.comvoid
10413067Sgabeblack@google.comScheduler::initPhase()
10512953Sgabeblack@google.com{
10613194Sgabeblack@google.com    for (Process *p = initList.getNext(); p; p = initList.getNext()) {
10712957Sgabeblack@google.com        p->popListNode();
10813180Sgabeblack@google.com
10913194Sgabeblack@google.com        if (p->dontInitialize()) {
11013194Sgabeblack@google.com            if (!p->hasStaticSensitivities() && !p->internal()) {
11113194Sgabeblack@google.com                SC_REPORT_WARNING(
11213194Sgabeblack@google.com                        "(W558) disable() or dont_initialize() called on "
11313194Sgabeblack@google.com                        "process with no static sensitivity, it will be "
11413194Sgabeblack@google.com                        "orphaned", p->name());
11513194Sgabeblack@google.com            }
11613194Sgabeblack@google.com        } else {
11713194Sgabeblack@google.com            p->ready();
11813180Sgabeblack@google.com        }
11912957Sgabeblack@google.com    }
12012957Sgabeblack@google.com
12113186Sgabeblack@google.com    runUpdate();
12213186Sgabeblack@google.com    runDelta();
12313067Sgabeblack@google.com
12412985Sgabeblack@google.com    for (auto ets: eventsToSchedule)
12512985Sgabeblack@google.com        eq->schedule(ets.first, ets.second);
12612985Sgabeblack@google.com    eventsToSchedule.clear();
12712985Sgabeblack@google.com
12813068Sgabeblack@google.com    if (_started) {
12913096Sgabeblack@google.com        if (!runToTime && starved())
13013068Sgabeblack@google.com            scheduleStarvationEvent();
13113069Sgabeblack@google.com        kernel->status(::sc_core::SC_RUNNING);
13213068Sgabeblack@google.com    }
13312961Sgabeblack@google.com
13413067Sgabeblack@google.com    initDone = true;
13513186Sgabeblack@google.com
13613186Sgabeblack@google.com    status(StatusOther);
13712957Sgabeblack@google.com}
13812957Sgabeblack@google.com
13912957Sgabeblack@google.comvoid
14012957Sgabeblack@google.comScheduler::reg(Process *p)
14112957Sgabeblack@google.com{
14213067Sgabeblack@google.com    if (initDone) {
14313194Sgabeblack@google.com        // If not marked as dontInitialize, mark as ready.
14413194Sgabeblack@google.com        if (!p->dontInitialize())
14513194Sgabeblack@google.com            p->ready();
14612957Sgabeblack@google.com    } else {
14712957Sgabeblack@google.com        // Otherwise, record that this process should be initialized once we
14812957Sgabeblack@google.com        // get there.
14912957Sgabeblack@google.com        initList.pushLast(p);
15012957Sgabeblack@google.com    }
15112957Sgabeblack@google.com}
15212957Sgabeblack@google.com
15312957Sgabeblack@google.comvoid
15412953Sgabeblack@google.comScheduler::yield()
15512953Sgabeblack@google.com{
15613176Sgabeblack@google.com    // Pull a process from the active list.
15713209Sgabeblack@google.com    _current = getNextReady();
15812953Sgabeblack@google.com    if (!_current) {
15912953Sgabeblack@google.com        // There are no more processes, so return control to evaluate.
16012953Sgabeblack@google.com        Fiber::primaryFiber()->run();
16112953Sgabeblack@google.com    } else {
16212953Sgabeblack@google.com        _current->popListNode();
16312953Sgabeblack@google.com        // Switch to whatever Fiber is supposed to run this process. All
16412953Sgabeblack@google.com        // Fibers which aren't running should be parked at this line.
16512953Sgabeblack@google.com        _current->fiber()->run();
16612961Sgabeblack@google.com        // If the current process needs to be manually started, start it.
16713093Sgabeblack@google.com        if (_current && _current->needsStart()) {
16813093Sgabeblack@google.com            _current->needsStart(false);
16913182Sgabeblack@google.com            try {
17013182Sgabeblack@google.com                _current->run();
17113182Sgabeblack@google.com            } catch (...) {
17213182Sgabeblack@google.com                throwToScMain();
17313182Sgabeblack@google.com            }
17413093Sgabeblack@google.com        }
17512953Sgabeblack@google.com    }
17612995Sgabeblack@google.com    if (_current && _current->excWrapper) {
17712995Sgabeblack@google.com        // Make sure this isn't a method process.
17812995Sgabeblack@google.com        assert(!_current->needsStart());
17912995Sgabeblack@google.com        auto ew = _current->excWrapper;
18012995Sgabeblack@google.com        _current->excWrapper = nullptr;
18112995Sgabeblack@google.com        ew->throw_it();
18212995Sgabeblack@google.com    }
18312953Sgabeblack@google.com}
18412953Sgabeblack@google.com
18512953Sgabeblack@google.comvoid
18612954Sgabeblack@google.comScheduler::ready(Process *p)
18712953Sgabeblack@google.com{
18813154Sgabeblack@google.com    if (_stopNow)
18913154Sgabeblack@google.com        return;
19013154Sgabeblack@google.com
19113176Sgabeblack@google.com    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
19213176Sgabeblack@google.com        readyListMethods.pushLast(p);
19312954Sgabeblack@google.com    else
19413176Sgabeblack@google.com        readyListThreads.pushLast(p);
19512953Sgabeblack@google.com
19612954Sgabeblack@google.com    scheduleReadyEvent();
19712954Sgabeblack@google.com}
19812954Sgabeblack@google.com
19912954Sgabeblack@google.comvoid
20013133Sgabeblack@google.comScheduler::resume(Process *p)
20113133Sgabeblack@google.com{
20213133Sgabeblack@google.com    if (initDone)
20313133Sgabeblack@google.com        ready(p);
20413133Sgabeblack@google.com    else
20513133Sgabeblack@google.com        initList.pushLast(p);
20613133Sgabeblack@google.com}
20713133Sgabeblack@google.com
20813133Sgabeblack@google.combool
20913176Sgabeblack@google.comlistContains(ListNode *list, ListNode *target)
21013176Sgabeblack@google.com{
21113176Sgabeblack@google.com    ListNode *n = list->nextListNode;
21213176Sgabeblack@google.com    while (n != list)
21313176Sgabeblack@google.com        if (n == target)
21413176Sgabeblack@google.com            return true;
21513176Sgabeblack@google.com    return false;
21613176Sgabeblack@google.com}
21713176Sgabeblack@google.com
21813176Sgabeblack@google.combool
21913133Sgabeblack@google.comScheduler::suspend(Process *p)
22013133Sgabeblack@google.com{
22113176Sgabeblack@google.com    bool was_ready;
22213133Sgabeblack@google.com    if (initDone) {
22313194Sgabeblack@google.com        // After initialization, check if we're on a ready list.
22413176Sgabeblack@google.com        was_ready = (p->nextListNode != nullptr);
22513133Sgabeblack@google.com        p->popListNode();
22613133Sgabeblack@google.com    } else {
22713194Sgabeblack@google.com        // Nothing is ready before init.
22813194Sgabeblack@google.com        was_ready = false;
22913133Sgabeblack@google.com    }
23013176Sgabeblack@google.com    return was_ready;
23113133Sgabeblack@google.com}
23213133Sgabeblack@google.com
23313133Sgabeblack@google.comvoid
23412954Sgabeblack@google.comScheduler::requestUpdate(Channel *c)
23512954Sgabeblack@google.com{
23612954Sgabeblack@google.com    updateList.pushLast(c);
23713069Sgabeblack@google.com    scheduleReadyEvent();
23812954Sgabeblack@google.com}
23912954Sgabeblack@google.com
24012954Sgabeblack@google.comvoid
24112954Sgabeblack@google.comScheduler::scheduleReadyEvent()
24212954Sgabeblack@google.com{
24312954Sgabeblack@google.com    // Schedule the evaluate and update phases.
24412954Sgabeblack@google.com    if (!readyEvent.scheduled()) {
24513069Sgabeblack@google.com        schedule(&readyEvent);
24612987Sgabeblack@google.com        if (starvationEvent.scheduled())
24713069Sgabeblack@google.com            deschedule(&starvationEvent);
24812987Sgabeblack@google.com    }
24912987Sgabeblack@google.com}
25012987Sgabeblack@google.com
25112987Sgabeblack@google.comvoid
25212987Sgabeblack@google.comScheduler::scheduleStarvationEvent()
25312987Sgabeblack@google.com{
25412987Sgabeblack@google.com    if (!starvationEvent.scheduled()) {
25513069Sgabeblack@google.com        schedule(&starvationEvent);
25612987Sgabeblack@google.com        if (readyEvent.scheduled())
25713069Sgabeblack@google.com            deschedule(&readyEvent);
25812954Sgabeblack@google.com    }
25912954Sgabeblack@google.com}
26012954Sgabeblack@google.com
26112954Sgabeblack@google.comvoid
26212954Sgabeblack@google.comScheduler::runReady()
26312954Sgabeblack@google.com{
26413176Sgabeblack@google.com    bool empty = readyListMethods.empty() && readyListThreads.empty();
26513140Sgabeblack@google.com    lastReadyTick = getCurTick();
26612954Sgabeblack@google.com
26712954Sgabeblack@google.com    // The evaluation phase.
26812953Sgabeblack@google.com    do {
26913209Sgabeblack@google.com        yield();
27013209Sgabeblack@google.com    } while (getNextReady());
27112954Sgabeblack@google.com
27213140Sgabeblack@google.com    if (!empty) {
27312954Sgabeblack@google.com        _numCycles++;
27413140Sgabeblack@google.com        _changeStamp++;
27513140Sgabeblack@google.com    }
27612954Sgabeblack@google.com
27713154Sgabeblack@google.com    if (_stopNow)
27813154Sgabeblack@google.com        return;
27913154Sgabeblack@google.com
28013186Sgabeblack@google.com    runUpdate();
28113186Sgabeblack@google.com    runDelta();
28213061Sgabeblack@google.com
28313096Sgabeblack@google.com    if (!runToTime && starved())
28413096Sgabeblack@google.com        scheduleStarvationEvent();
28513096Sgabeblack@google.com
28613064Sgabeblack@google.com    if (runOnce)
28713064Sgabeblack@google.com        schedulePause();
28813186Sgabeblack@google.com
28913186Sgabeblack@google.com    status(StatusOther);
29012953Sgabeblack@google.com}
29112953Sgabeblack@google.com
29212953Sgabeblack@google.comvoid
29313186Sgabeblack@google.comScheduler::runUpdate()
29412953Sgabeblack@google.com{
29513186Sgabeblack@google.com    status(StatusUpdate);
29613186Sgabeblack@google.com
29713188Sgabeblack@google.com    try {
29813188Sgabeblack@google.com        Channel *channel = updateList.getNext();
29913188Sgabeblack@google.com        while (channel) {
30013188Sgabeblack@google.com            channel->popListNode();
30113188Sgabeblack@google.com            channel->update();
30213188Sgabeblack@google.com            channel = updateList.getNext();
30313188Sgabeblack@google.com        }
30413188Sgabeblack@google.com    } catch (...) {
30513188Sgabeblack@google.com        throwToScMain();
30612954Sgabeblack@google.com    }
30712953Sgabeblack@google.com}
30812953Sgabeblack@google.com
30912961Sgabeblack@google.comvoid
31013186Sgabeblack@google.comScheduler::runDelta()
31113186Sgabeblack@google.com{
31213186Sgabeblack@google.com    status(StatusDelta);
31313188Sgabeblack@google.com
31413188Sgabeblack@google.com    try {
31513188Sgabeblack@google.com        while (!deltas.empty())
31613188Sgabeblack@google.com            deltas.front()->run();
31713188Sgabeblack@google.com    } catch (...) {
31813188Sgabeblack@google.com        throwToScMain();
31913188Sgabeblack@google.com    }
32013186Sgabeblack@google.com}
32113186Sgabeblack@google.com
32213186Sgabeblack@google.comvoid
32312961Sgabeblack@google.comScheduler::pause()
32412961Sgabeblack@google.com{
32513186Sgabeblack@google.com    status(StatusPaused);
32612982Sgabeblack@google.com    kernel->status(::sc_core::SC_PAUSED);
32713061Sgabeblack@google.com    runOnce = false;
32813182Sgabeblack@google.com    if (scMain && !scMain->finished())
32913182Sgabeblack@google.com        scMain->run();
33012961Sgabeblack@google.com}
33112961Sgabeblack@google.com
33212961Sgabeblack@google.comvoid
33312961Sgabeblack@google.comScheduler::stop()
33412961Sgabeblack@google.com{
33513186Sgabeblack@google.com    status(StatusStopped);
33612982Sgabeblack@google.com    kernel->stop();
33713074Sgabeblack@google.com
33813076Sgabeblack@google.com    clear();
33913074Sgabeblack@google.com
34013061Sgabeblack@google.com    runOnce = false;
34113182Sgabeblack@google.com    if (scMain && !scMain->finished())
34213182Sgabeblack@google.com        scMain->run();
34312961Sgabeblack@google.com}
34412961Sgabeblack@google.com
34512961Sgabeblack@google.comvoid
34612961Sgabeblack@google.comScheduler::start(Tick max_tick, bool run_to_time)
34712961Sgabeblack@google.com{
34812961Sgabeblack@google.com    // We should be running from sc_main. Keep track of that Fiber to return
34912961Sgabeblack@google.com    // to later.
35012961Sgabeblack@google.com    scMain = Fiber::currentFiber();
35112961Sgabeblack@google.com
35212961Sgabeblack@google.com    _started = true;
35313186Sgabeblack@google.com    status(StatusOther);
35412987Sgabeblack@google.com    runToTime = run_to_time;
35512961Sgabeblack@google.com
35612961Sgabeblack@google.com    maxTick = max_tick;
35713140Sgabeblack@google.com    lastReadyTick = getCurTick();
35812961Sgabeblack@google.com
35913067Sgabeblack@google.com    if (initDone) {
36013096Sgabeblack@google.com        if (!runToTime && starved())
36113068Sgabeblack@google.com            scheduleStarvationEvent();
36212982Sgabeblack@google.com        kernel->status(::sc_core::SC_RUNNING);
36312982Sgabeblack@google.com    }
36412961Sgabeblack@google.com
36513069Sgabeblack@google.com    schedule(&maxTickEvent, maxTick);
36613069Sgabeblack@google.com
36712961Sgabeblack@google.com    // Return to gem5 to let it run events, etc.
36812961Sgabeblack@google.com    Fiber::primaryFiber()->run();
36912961Sgabeblack@google.com
37012961Sgabeblack@google.com    if (pauseEvent.scheduled())
37113088Sgabeblack@google.com        deschedule(&pauseEvent);
37212961Sgabeblack@google.com    if (stopEvent.scheduled())
37313088Sgabeblack@google.com        deschedule(&stopEvent);
37412961Sgabeblack@google.com    if (maxTickEvent.scheduled())
37513088Sgabeblack@google.com        deschedule(&maxTickEvent);
37612987Sgabeblack@google.com    if (starvationEvent.scheduled())
37713088Sgabeblack@google.com        deschedule(&starvationEvent);
37813182Sgabeblack@google.com
37913182Sgabeblack@google.com    if (_throwToScMain) {
38013182Sgabeblack@google.com        const ::sc_core::sc_report *to_throw = _throwToScMain;
38113182Sgabeblack@google.com        _throwToScMain = nullptr;
38213182Sgabeblack@google.com        throw *to_throw;
38313182Sgabeblack@google.com    }
38412961Sgabeblack@google.com}
38512961Sgabeblack@google.com
38612961Sgabeblack@google.comvoid
38713061Sgabeblack@google.comScheduler::oneCycle()
38813061Sgabeblack@google.com{
38913061Sgabeblack@google.com    runOnce = true;
39013095Sgabeblack@google.com    scheduleReadyEvent();
39113061Sgabeblack@google.com    start(::MaxTick, false);
39213061Sgabeblack@google.com}
39313061Sgabeblack@google.com
39413061Sgabeblack@google.comvoid
39512961Sgabeblack@google.comScheduler::schedulePause()
39612961Sgabeblack@google.com{
39712961Sgabeblack@google.com    if (pauseEvent.scheduled())
39812961Sgabeblack@google.com        return;
39912961Sgabeblack@google.com
40013088Sgabeblack@google.com    schedule(&pauseEvent);
40112961Sgabeblack@google.com}
40212961Sgabeblack@google.com
40312961Sgabeblack@google.comvoid
40413182Sgabeblack@google.comScheduler::throwToScMain(const ::sc_core::sc_report *r)
40513182Sgabeblack@google.com{
40613182Sgabeblack@google.com    if (!r)
40713182Sgabeblack@google.com        r = reportifyException();
40813182Sgabeblack@google.com    _throwToScMain = r;
40913188Sgabeblack@google.com    status(StatusOther);
41013182Sgabeblack@google.com    scMain->run();
41113182Sgabeblack@google.com}
41213182Sgabeblack@google.com
41313182Sgabeblack@google.comvoid
41412961Sgabeblack@google.comScheduler::scheduleStop(bool finish_delta)
41512961Sgabeblack@google.com{
41612961Sgabeblack@google.com    if (stopEvent.scheduled())
41712961Sgabeblack@google.com        return;
41812961Sgabeblack@google.com
41912961Sgabeblack@google.com    if (!finish_delta) {
42013154Sgabeblack@google.com        _stopNow = true;
42113076Sgabeblack@google.com        // If we're not supposed to finish the delta cycle, flush all
42213076Sgabeblack@google.com        // pending activity.
42313076Sgabeblack@google.com        clear();
42412961Sgabeblack@google.com    }
42513088Sgabeblack@google.com    schedule(&stopEvent);
42612961Sgabeblack@google.com}
42712961Sgabeblack@google.com
42812953Sgabeblack@google.comScheduler scheduler;
42912953Sgabeblack@google.com
43013182Sgabeblack@google.comnamespace {
43113182Sgabeblack@google.com
43213182Sgabeblack@google.comvoid
43313182Sgabeblack@google.comthrowingReportHandler(const ::sc_core::sc_report &r,
43413182Sgabeblack@google.com                      const ::sc_core::sc_actions &)
43513182Sgabeblack@google.com{
43613182Sgabeblack@google.com    throw r;
43713182Sgabeblack@google.com}
43813182Sgabeblack@google.com
43913182Sgabeblack@google.com} // anonymous namespace
44013182Sgabeblack@google.com
44113182Sgabeblack@google.comconst ::sc_core::sc_report *
44213182Sgabeblack@google.comreportifyException()
44313182Sgabeblack@google.com{
44413182Sgabeblack@google.com    ::sc_core::sc_report_handler_proc old_handler =
44513182Sgabeblack@google.com        ::sc_core::sc_report_handler::get_handler();
44613182Sgabeblack@google.com    ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);
44713182Sgabeblack@google.com
44813182Sgabeblack@google.com    try {
44913182Sgabeblack@google.com        try {
45013182Sgabeblack@google.com            // Rethrow the current exception so we can catch it and throw an
45113182Sgabeblack@google.com            // sc_report instead if it's not a type we recognize/can handle.
45213182Sgabeblack@google.com            throw;
45313182Sgabeblack@google.com        } catch (const ::sc_core::sc_report &) {
45413182Sgabeblack@google.com            // It's already a sc_report, so nothing to do.
45513182Sgabeblack@google.com            throw;
45613182Sgabeblack@google.com        } catch (const ::sc_core::sc_unwind_exception &) {
45713182Sgabeblack@google.com            panic("Kill/reset exception escaped a Process::run()");
45813182Sgabeblack@google.com        } catch (const std::exception &e) {
45913182Sgabeblack@google.com            SC_REPORT_ERROR("uncaught exception", e.what());
46013182Sgabeblack@google.com        } catch (const char *msg) {
46113182Sgabeblack@google.com            SC_REPORT_ERROR("uncaught exception", msg);
46213182Sgabeblack@google.com        } catch (...) {
46313182Sgabeblack@google.com            SC_REPORT_ERROR("uncaught exception", "UNKNOWN EXCEPTION");
46413182Sgabeblack@google.com        }
46513182Sgabeblack@google.com    } catch (const ::sc_core::sc_report &r) {
46613182Sgabeblack@google.com        ::sc_core::sc_report_handler::set_handler(old_handler);
46713182Sgabeblack@google.com        return &r;
46813182Sgabeblack@google.com    }
46913182Sgabeblack@google.com    panic("No exception thrown in reportifyException.");
47013182Sgabeblack@google.com}
47113182Sgabeblack@google.com
47212953Sgabeblack@google.com} // namespace sc_gem5
473