process.cc revision 12996
114184Sgabeblack@google.com/*
214184Sgabeblack@google.com * Copyright 2018 Google, Inc.
314184Sgabeblack@google.com *
414184Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
514184Sgabeblack@google.com * modification, are permitted provided that the following conditions are
614184Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
714184Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
814184Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
914184Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1014184Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1114184Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1214184Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1314184Sgabeblack@google.com * this software without specific prior written permission.
1414184Sgabeblack@google.com *
1514184Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1614184Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1714184Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1814184Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1914184Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2014184Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2114184Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2214184Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2314184Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2414184Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2514184Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2614184Sgabeblack@google.com *
2714184Sgabeblack@google.com * Authors: Gabe Black
2814184Sgabeblack@google.com */
2914184Sgabeblack@google.com
3014184Sgabeblack@google.com#include "systemc/core/process.hh"
3114184Sgabeblack@google.com
3214184Sgabeblack@google.com#include "base/logging.hh"
3314184Sgabeblack@google.com#include "systemc/core/event.hh"
3414184Sgabeblack@google.com#include "systemc/core/scheduler.hh"
3514184Sgabeblack@google.com
3614184Sgabeblack@google.comnamespace sc_gem5
3714184Sgabeblack@google.com{
3814184Sgabeblack@google.com
3914184Sgabeblack@google.comSensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) :
4014184Sgabeblack@google.com    Sensitivity(p), timeoutEvent(this), time(t)
4114184Sgabeblack@google.com{
4214184Sgabeblack@google.com    Tick when = scheduler.getCurTick() + time.value();
4314184Sgabeblack@google.com    scheduler.schedule(&timeoutEvent, when);
4414184Sgabeblack@google.com}
4514184Sgabeblack@google.com
4614184Sgabeblack@google.comSensitivityTimeout::~SensitivityTimeout()
4714184Sgabeblack@google.com{
4814184Sgabeblack@google.com    if (timeoutEvent.scheduled())
4914184Sgabeblack@google.com        scheduler.deschedule(&timeoutEvent);
5014184Sgabeblack@google.com}
5114184Sgabeblack@google.com
5214184Sgabeblack@google.comvoid
5314184Sgabeblack@google.comSensitivityTimeout::timeout()
5414184Sgabeblack@google.com{
5514184Sgabeblack@google.com    scheduler.eventHappened();
5614184Sgabeblack@google.com    notify();
5714184Sgabeblack@google.com}
5814184Sgabeblack@google.com
5914184Sgabeblack@google.comSensitivityEvent::SensitivityEvent(
6014184Sgabeblack@google.com        Process *p, const ::sc_core::sc_event *e) : Sensitivity(p), event(e)
6114184Sgabeblack@google.com{
6214184Sgabeblack@google.com    Event::getFromScEvent(event)->addSensitivity(this);
6314184Sgabeblack@google.com}
6414184Sgabeblack@google.com
6514184Sgabeblack@google.comSensitivityEvent::~SensitivityEvent()
6614184Sgabeblack@google.com{
6714184Sgabeblack@google.com    Event::getFromScEvent(event)->delSensitivity(this);
6814184Sgabeblack@google.com}
6914184Sgabeblack@google.com
7014184Sgabeblack@google.comSensitivityEventAndList::SensitivityEventAndList(
7114184Sgabeblack@google.com        Process *p, const ::sc_core::sc_event_and_list *list) :
7214184Sgabeblack@google.com    Sensitivity(p), list(list), count(0)
7314184Sgabeblack@google.com{
7414184Sgabeblack@google.com    for (auto e: list->events)
7514184Sgabeblack@google.com        Event::getFromScEvent(e)->addSensitivity(this);
7614184Sgabeblack@google.com}
7714184Sgabeblack@google.com
7814184Sgabeblack@google.comSensitivityEventAndList::~SensitivityEventAndList()
7914184Sgabeblack@google.com{
8014184Sgabeblack@google.com    for (auto e: list->events)
8114184Sgabeblack@google.com        Event::getFromScEvent(e)->delSensitivity(this);
8214184Sgabeblack@google.com}
8314184Sgabeblack@google.com
8414184Sgabeblack@google.comvoid
8514184Sgabeblack@google.comSensitivityEventAndList::notifyWork(Event *e)
8614184Sgabeblack@google.com{
8714184Sgabeblack@google.com    e->delSensitivity(this);
8814184Sgabeblack@google.com    count++;
8914184Sgabeblack@google.com    if (count == list->events.size())
9014184Sgabeblack@google.com        process->satisfySensitivity(this);
9114184Sgabeblack@google.com}
9214184Sgabeblack@google.com
9314184Sgabeblack@google.comSensitivityEventOrList::SensitivityEventOrList(
9414184Sgabeblack@google.com        Process *p, const ::sc_core::sc_event_or_list *list) :
9514184Sgabeblack@google.com    Sensitivity(p), list(list)
9614184Sgabeblack@google.com{
9714184Sgabeblack@google.com    for (auto e: list->events)
9814184Sgabeblack@google.com        Event::getFromScEvent(e)->addSensitivity(this);
9914184Sgabeblack@google.com}
10014184Sgabeblack@google.com
10114184Sgabeblack@google.comSensitivityEventOrList::~SensitivityEventOrList()
10214184Sgabeblack@google.com{
10314184Sgabeblack@google.com    for (auto e: list->events)
10414184Sgabeblack@google.com        Event::getFromScEvent(e)->delSensitivity(this);
10514184Sgabeblack@google.com}
10614184Sgabeblack@google.com
10714184Sgabeblack@google.com
10814184Sgabeblack@google.comclass UnwindExceptionReset : public ::sc_core::sc_unwind_exception
10914184Sgabeblack@google.com{
11014184Sgabeblack@google.com  public:
11114184Sgabeblack@google.com    UnwindExceptionReset() { _isReset = true; }
11214184Sgabeblack@google.com};
11314184Sgabeblack@google.com
11414184Sgabeblack@google.comclass UnwindExceptionKill : public ::sc_core::sc_unwind_exception
11514184Sgabeblack@google.com{
11614184Sgabeblack@google.com  public:
11714184Sgabeblack@google.com    UnwindExceptionKill() {}
11814184Sgabeblack@google.com};
11914184Sgabeblack@google.com
12014184Sgabeblack@google.comtemplate <typename T>
12114184Sgabeblack@google.comstruct BuiltinExceptionWrapper : public ExceptionWrapperBase
12214184Sgabeblack@google.com{
12314184Sgabeblack@google.com  public:
12414184Sgabeblack@google.com    T t;
12514184Sgabeblack@google.com    void throw_it() override { throw t; }
12614184Sgabeblack@google.com};
12714184Sgabeblack@google.com
12814184Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionReset> resetException;
12914184Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionKill> killException;
13014184Sgabeblack@google.com
13114184Sgabeblack@google.com
13214184Sgabeblack@google.comvoid
13314184Sgabeblack@google.comProcess::forEachKid(const std::function<void(Process *)> &work)
13414184Sgabeblack@google.com{
13514184Sgabeblack@google.com    for (auto &kid: get_child_objects()) {
13614184Sgabeblack@google.com        Process *p_kid = dynamic_cast<Process *>(kid);
13714184Sgabeblack@google.com        if (p_kid)
13814184Sgabeblack@google.com            work(p_kid);
13914184Sgabeblack@google.com    }
14014184Sgabeblack@google.com}
14114184Sgabeblack@google.com
14214184Sgabeblack@google.comvoid
14314184Sgabeblack@google.comProcess::suspend(bool inc_kids)
14414184Sgabeblack@google.com{
14514184Sgabeblack@google.com    if (inc_kids)
14614184Sgabeblack@google.com        forEachKid([](Process *p) { p->suspend(true); });
14714184Sgabeblack@google.com
14814184Sgabeblack@google.com    if (!_suspended) {
14914184Sgabeblack@google.com        _suspended = true;
15014184Sgabeblack@google.com        _suspendedReady = false;
15114184Sgabeblack@google.com    }
15214184Sgabeblack@google.com
15314184Sgabeblack@google.com    if (procKind() != ::sc_core::SC_METHOD_PROC_ &&
15414184Sgabeblack@google.com            scheduler.current() == this) {
15514184Sgabeblack@google.com        scheduler.yield();
15614184Sgabeblack@google.com    }
15714184Sgabeblack@google.com}
15814184Sgabeblack@google.com
15914184Sgabeblack@google.comvoid
16014184Sgabeblack@google.comProcess::resume(bool inc_kids)
16114184Sgabeblack@google.com{
16214184Sgabeblack@google.com    if (inc_kids)
16314184Sgabeblack@google.com        forEachKid([](Process *p) { p->resume(true); });
16414184Sgabeblack@google.com
16514184Sgabeblack@google.com    if (_suspended) {
16614184Sgabeblack@google.com        _suspended = false;
16714184Sgabeblack@google.com        if (_suspendedReady)
16814184Sgabeblack@google.com            ready();
16914184Sgabeblack@google.com        _suspendedReady = false;
17014184Sgabeblack@google.com    }
17114184Sgabeblack@google.com}
17214184Sgabeblack@google.com
17314184Sgabeblack@google.comvoid
17414184Sgabeblack@google.comProcess::disable(bool inc_kids)
17514184Sgabeblack@google.com{
17614184Sgabeblack@google.com    if (inc_kids)
17714184Sgabeblack@google.com        forEachKid([](Process *p) { p->disable(true); });
17814184Sgabeblack@google.com
17914184Sgabeblack@google.com    _disabled = true;
18014184Sgabeblack@google.com}
18114184Sgabeblack@google.com
18214184Sgabeblack@google.comvoid
18314184Sgabeblack@google.comProcess::enable(bool inc_kids)
18414184Sgabeblack@google.com{
18514184Sgabeblack@google.com
18614184Sgabeblack@google.com    if (inc_kids)
18714184Sgabeblack@google.com        forEachKid([](Process *p) { p->enable(true); });
18814184Sgabeblack@google.com
18914184Sgabeblack@google.com    _disabled = false;
19014184Sgabeblack@google.com}
19114184Sgabeblack@google.com
19214184Sgabeblack@google.comvoid
19314184Sgabeblack@google.comProcess::kill(bool inc_kids)
19414184Sgabeblack@google.com{
19514184Sgabeblack@google.com    // Propogate the kill to our children no matter what happens to us.
19614184Sgabeblack@google.com    if (inc_kids)
19714184Sgabeblack@google.com        forEachKid([](Process *p) { p->kill(true); });
19814184Sgabeblack@google.com
19914184Sgabeblack@google.com    // If we're in the middle of unwinding, ignore the kill request.
20014184Sgabeblack@google.com    if (_isUnwinding)
20114184Sgabeblack@google.com        return;
20214184Sgabeblack@google.com
20314184Sgabeblack@google.com    // Update our state.
20414184Sgabeblack@google.com    _terminated = true;
20514184Sgabeblack@google.com    _isUnwinding = true;
20614184Sgabeblack@google.com    _suspendedReady = false;
20714184Sgabeblack@google.com    _suspended = false;
20814184Sgabeblack@google.com    _syncReset = false;
20914184Sgabeblack@google.com
21014184Sgabeblack@google.com    // Inject the kill exception into this process.
21114184Sgabeblack@google.com    injectException(killException);
21214184Sgabeblack@google.com
21314184Sgabeblack@google.com    _terminatedEvent.notify();
21414184Sgabeblack@google.com}
21514184Sgabeblack@google.com
21614184Sgabeblack@google.comvoid
21714184Sgabeblack@google.comProcess::reset(bool inc_kids)
21814184Sgabeblack@google.com{
21914184Sgabeblack@google.com    // Propogate the reset to our children no matter what happens to us.
22014184Sgabeblack@google.com    if (inc_kids)
22114184Sgabeblack@google.com        forEachKid([](Process *p) { p->reset(true); });
22214184Sgabeblack@google.com
22314184Sgabeblack@google.com    // If we're in the middle of unwinding, ignore the reset request.
22414184Sgabeblack@google.com    if (_isUnwinding)
22514184Sgabeblack@google.com        return;
22614184Sgabeblack@google.com
22714184Sgabeblack@google.com    // Update our state.
22814184Sgabeblack@google.com    _isUnwinding = true;
22914184Sgabeblack@google.com
23014184Sgabeblack@google.com    // Inject the reset exception into this process.
23114184Sgabeblack@google.com    injectException(resetException);
23214184Sgabeblack@google.com
23314184Sgabeblack@google.com    _resetEvent.notify();
23414184Sgabeblack@google.com}
23514184Sgabeblack@google.com
23614184Sgabeblack@google.comvoid
23714184Sgabeblack@google.comProcess::throw_it(ExceptionWrapperBase &exc, bool inc_kids)
23814184Sgabeblack@google.com{
23914184Sgabeblack@google.com    if (inc_kids)
24014184Sgabeblack@google.com        forEachKid([&exc](Process *p) { p->throw_it(exc, true); });
24114184Sgabeblack@google.com}
24214184Sgabeblack@google.com
24314184Sgabeblack@google.comvoid
24414184Sgabeblack@google.comProcess::injectException(ExceptionWrapperBase &exc)
24514184Sgabeblack@google.com{
24614184Sgabeblack@google.com    excWrapper = &exc;
24714184Sgabeblack@google.com    scheduler.runNow(this);
24814184Sgabeblack@google.com};
24914184Sgabeblack@google.com
25014184Sgabeblack@google.comvoid
25114184Sgabeblack@google.comProcess::syncResetOn(bool inc_kids)
25214184Sgabeblack@google.com{
25314184Sgabeblack@google.com    if (inc_kids)
25414184Sgabeblack@google.com        forEachKid([](Process *p) { p->syncResetOn(true); });
25514184Sgabeblack@google.com
25614184Sgabeblack@google.com    _syncReset = true;
25714184Sgabeblack@google.com}
25814184Sgabeblack@google.com
25914184Sgabeblack@google.comvoid
26014184Sgabeblack@google.comProcess::syncResetOff(bool inc_kids)
26114184Sgabeblack@google.com{
26214184Sgabeblack@google.com    if (inc_kids)
26314184Sgabeblack@google.com        forEachKid([](Process *p) { p->syncResetOff(true); });
26414184Sgabeblack@google.com
26514184Sgabeblack@google.com    _syncReset = false;
26614184Sgabeblack@google.com}
26714184Sgabeblack@google.com
26814184Sgabeblack@google.comvoid
26914184Sgabeblack@google.comProcess::dontInitialize()
27014184Sgabeblack@google.com{
27114184Sgabeblack@google.com    scheduler.dontInitialize(this);
27214184Sgabeblack@google.com}
27314184Sgabeblack@google.com
27414184Sgabeblack@google.comvoid
27514184Sgabeblack@google.comProcess::finalize()
27614184Sgabeblack@google.com{
27714184Sgabeblack@google.com    for (auto &s: pendingStaticSensitivities) {
27814184Sgabeblack@google.com        s->finalize(staticSensitivities);
27914184Sgabeblack@google.com        delete s;
28014184Sgabeblack@google.com        s = nullptr;
28114184Sgabeblack@google.com    }
28214184Sgabeblack@google.com    pendingStaticSensitivities.clear();
28314184Sgabeblack@google.com};
28414184Sgabeblack@google.com
28514184Sgabeblack@google.comvoid
28614184Sgabeblack@google.comProcess::run()
28714184Sgabeblack@google.com{
28814184Sgabeblack@google.com    bool reset;
28914184Sgabeblack@google.com    do {
29014184Sgabeblack@google.com        reset = false;
29114184Sgabeblack@google.com        try {
29214184Sgabeblack@google.com            func->call();
29314184Sgabeblack@google.com        } catch(const ::sc_core::sc_unwind_exception &exc) {
29414184Sgabeblack@google.com            reset = exc.is_reset();
29514184Sgabeblack@google.com            _isUnwinding = false;
29614184Sgabeblack@google.com        }
29714184Sgabeblack@google.com    } while (reset);
29814184Sgabeblack@google.com    _terminated = true;
29914184Sgabeblack@google.com}
30014184Sgabeblack@google.com
30114184Sgabeblack@google.comvoid
30214184Sgabeblack@google.comProcess::addStatic(PendingSensitivity *s)
30314184Sgabeblack@google.com{
30414184Sgabeblack@google.com    pendingStaticSensitivities.push_back(s);
30514184Sgabeblack@google.com}
30614184Sgabeblack@google.com
30714184Sgabeblack@google.comvoid
30814184Sgabeblack@google.comProcess::setDynamic(Sensitivity *s)
30914184Sgabeblack@google.com{
31014184Sgabeblack@google.com    delete dynamicSensitivity;
31114184Sgabeblack@google.com    dynamicSensitivity = s;
31214184Sgabeblack@google.com}
31314184Sgabeblack@google.com
31414184Sgabeblack@google.comvoid
31514184Sgabeblack@google.comProcess::satisfySensitivity(Sensitivity *s)
31614184Sgabeblack@google.com{
31714184Sgabeblack@google.com    // If there's a dynamic sensitivity and this wasn't it, ignore.
31814184Sgabeblack@google.com    if (dynamicSensitivity && dynamicSensitivity != s)
31914184Sgabeblack@google.com        return;
32014184Sgabeblack@google.com
32114184Sgabeblack@google.com    setDynamic(nullptr);
32214184Sgabeblack@google.com    ready();
32314184Sgabeblack@google.com}
32414184Sgabeblack@google.com
32514184Sgabeblack@google.comvoid
32614184Sgabeblack@google.comProcess::ready()
32714184Sgabeblack@google.com{
32814184Sgabeblack@google.com    if (disabled())
32914184Sgabeblack@google.com        return;
33014184Sgabeblack@google.com    if (suspended())
33114184Sgabeblack@google.com        _suspendedReady = true;
33214184Sgabeblack@google.com    else
33314184Sgabeblack@google.com        scheduler.ready(this);
33414184Sgabeblack@google.com}
33514184Sgabeblack@google.com
33614184Sgabeblack@google.comProcess::Process(const char *name, ProcessFuncWrapper *func,
33714184Sgabeblack@google.com        bool _dynamic, bool needs_start) :
33814184Sgabeblack@google.com    ::sc_core::sc_object(name), excWrapper(nullptr), func(func),
33914184Sgabeblack@google.com    _needsStart(needs_start), _dynamic(_dynamic), _isUnwinding(false),
34014184Sgabeblack@google.com    _terminated(false), _suspended(false), _disabled(false),
34114184Sgabeblack@google.com    _syncReset(false), refCount(0), stackSize(::Fiber::DefaultStackSize),
34214184Sgabeblack@google.com    dynamicSensitivity(nullptr)
34314184Sgabeblack@google.com{
34414184Sgabeblack@google.com    _newest = this;
34514184Sgabeblack@google.com}
34614184Sgabeblack@google.com
34714184Sgabeblack@google.comProcess *Process::_newest;
34814184Sgabeblack@google.com
34914184Sgabeblack@google.comvoid
35014184Sgabeblack@google.comthrow_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids)
35114184Sgabeblack@google.com{
35214184Sgabeblack@google.com    p->throw_it(exc, inc_kids);
35314184Sgabeblack@google.com}
35414184Sgabeblack@google.com
35514184Sgabeblack@google.com} // namespace sc_gem5
35614184Sgabeblack@google.com