process.cc revision 12996
12810SN/A/*
22810SN/A * Copyright 2018 Google, Inc.
32810SN/A *
42810SN/A * Redistribution and use in source and binary forms, with or without
52810SN/A * modification, are permitted provided that the following conditions are
62810SN/A * met: redistributions of source code must retain the above copyright
72810SN/A * notice, this list of conditions and the following disclaimer;
82810SN/A * redistributions in binary form must reproduce the above copyright
92810SN/A * notice, this list of conditions and the following disclaimer in the
102810SN/A * documentation and/or other materials provided with the distribution;
112810SN/A * neither the name of the copyright holders nor the names of its
122810SN/A * contributors may be used to endorse or promote products derived from
132810SN/A * this software without specific prior written permission.
142810SN/A *
152810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
182810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
192810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
202810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
212810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
252810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262810SN/A *
272810SN/A * Authors: Gabe Black
282810SN/A */
294458SN/A
304458SN/A#include "systemc/core/process.hh"
312810SN/A
322810SN/A#include "base/logging.hh"
332810SN/A#include "systemc/core/event.hh"
342810SN/A#include "systemc/core/scheduler.hh"
352810SN/A
362810SN/Anamespace sc_gem5
372810SN/A{
382810SN/A
392810SN/ASensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) :
402810SN/A    Sensitivity(p), timeoutEvent(this), time(t)
417676Snate@binkert.org{
427676Snate@binkert.org    Tick when = scheduler.getCurTick() + time.value();
437676Snate@binkert.org    scheduler.schedule(&timeoutEvent, when);
442810SN/A}
452810SN/A
462825SN/ASensitivityTimeout::~SensitivityTimeout()
472810SN/A{
482810SN/A    if (timeoutEvent.scheduled())
496215Snate@binkert.org        scheduler.deschedule(&timeoutEvent);
508232Snate@binkert.org}
518232Snate@binkert.org
525338Sstever@gmail.comvoid
532810SN/ASensitivityTimeout::timeout()
542810SN/A{
558229Snate@binkert.org    scheduler.eventHappened();
564626SN/A    notify();
575034SN/A}
582811SN/A
598786Sgblack@eecs.umich.eduSensitivityEvent::SensitivityEvent(
604626SN/A        Process *p, const ::sc_core::sc_event *e) : Sensitivity(p), event(e)
618833Sdam.sunwoo@arm.com{
622810SN/A    Event::getFromScEvent(event)->addSensitivity(this);
633194SN/A}
642810SN/A
652810SN/ASensitivityEvent::~SensitivityEvent()
662810SN/A{
672810SN/A    Event::getFromScEvent(event)->delSensitivity(this);
682810SN/A}
694628SN/A
704628SN/ASensitivityEventAndList::SensitivityEventAndList(
714628SN/A        Process *p, const ::sc_core::sc_event_and_list *list) :
724628SN/A    Sensitivity(p), list(list), count(0)
734628SN/A{
744628SN/A    for (auto e: list->events)
754628SN/A        Event::getFromScEvent(e)->addSensitivity(this);
764628SN/A}
778737Skoansin.tan@gmail.com
784628SN/ASensitivityEventAndList::~SensitivityEventAndList()
794628SN/A{
804628SN/A    for (auto e: list->events)
814628SN/A        Event::getFromScEvent(e)->delSensitivity(this);
824628SN/A}
834628SN/A
844628SN/Avoid
854628SN/ASensitivityEventAndList::notifyWork(Event *e)
864628SN/A{
874628SN/A    e->delSensitivity(this);
884628SN/A    count++;
894628SN/A    if (count == list->events.size())
904628SN/A        process->satisfySensitivity(this);
914628SN/A}
924628SN/A
934628SN/ASensitivityEventOrList::SensitivityEventOrList(
944628SN/A        Process *p, const ::sc_core::sc_event_or_list *list) :
954628SN/A    Sensitivity(p), list(list)
964628SN/A{
974628SN/A    for (auto e: list->events)
988737Skoansin.tan@gmail.com        Event::getFromScEvent(e)->addSensitivity(this);
994628SN/A}
1004626SN/A
1012810SN/ASensitivityEventOrList::~SensitivityEventOrList()
1022844SN/A{
1032810SN/A    for (auto e: list->events)
1042810SN/A        Event::getFromScEvent(e)->delSensitivity(this);
1053738SN/A}
1064965SN/A
1076122SSteve.Reinhardt@amd.com
1084458SN/Aclass UnwindExceptionReset : public ::sc_core::sc_unwind_exception
1096227Snate@binkert.org{
1102810SN/A  public:
1114458SN/A    UnwindExceptionReset() { _isReset = true; }
1123013SN/A};
1134666SN/A
1144666SN/Aclass UnwindExceptionKill : public ::sc_core::sc_unwind_exception
1154666SN/A{
1165314SN/A  public:
1175314SN/A    UnwindExceptionKill() {}
1182811SN/A};
1192810SN/A
1202810SN/Atemplate <typename T>
1212810SN/Astruct BuiltinExceptionWrapper : public ExceptionWrapperBase
1222810SN/A{
1235314SN/A  public:
1243606SN/A    T t;
1252810SN/A    void throw_it() override { throw t; }
1262810SN/A};
1272897SN/A
1282897SN/ABuiltinExceptionWrapper<UnwindExceptionReset> resetException;
1294458SN/ABuiltinExceptionWrapper<UnwindExceptionKill> killException;
1304458SN/A
1314888SN/A
1324666SN/Avoid
1334666SN/AProcess::forEachKid(const std::function<void(Process *)> &work)
1344458SN/A{
1354458SN/A    for (auto &kid: get_child_objects()) {
1364458SN/A        Process *p_kid = dynamic_cast<Process *>(kid);
1374626SN/A        if (p_kid)
1384626SN/A            work(p_kid);
1394626SN/A    }
1402811SN/A}
1412810SN/A
1423338SN/Avoid
1433738SN/AProcess::suspend(bool inc_kids)
1443338SN/A{
1454626SN/A    if (inc_kids)
1464626SN/A        forEachKid([](Process *p) { p->suspend(true); });
1474626SN/A
1484626SN/A    if (!_suspended) {
1494626SN/A        _suspended = true;
1504626SN/A        _suspendedReady = false;
1514626SN/A    }
1524626SN/A
1534628SN/A    if (procKind() != ::sc_core::SC_METHOD_PROC_ &&
1544628SN/A            scheduler.current() == this) {
1554628SN/A        scheduler.yield();
1564666SN/A    }
1574628SN/A}
1584628SN/A
1594628SN/Avoid
1604628SN/AProcess::resume(bool inc_kids)
1614628SN/A{
1624628SN/A    if (inc_kids)
1634628SN/A        forEachKid([](Process *p) { p->resume(true); });
1644628SN/A
1654628SN/A    if (_suspended) {
1664628SN/A        _suspended = false;
1674628SN/A        if (_suspendedReady)
1684628SN/A            ready();
1697667Ssteve.reinhardt@amd.com        _suspendedReady = false;
1704628SN/A    }
1714628SN/A}
1724628SN/A
1737667Ssteve.reinhardt@amd.comvoid
1744628SN/AProcess::disable(bool inc_kids)
1754628SN/A{
1764628SN/A    if (inc_kids)
1774628SN/A        forEachKid([](Process *p) { p->disable(true); });
1784628SN/A
1794626SN/A    _disabled = true;
1806227Snate@binkert.org}
1814626SN/A
1824630SN/Avoid
1834630SN/AProcess::enable(bool inc_kids)
1844630SN/A{
1854630SN/A
1864630SN/A    if (inc_kids)
1874626SN/A        forEachKid([](Process *p) { p->enable(true); });
1884626SN/A
1894626SN/A    _disabled = false;
1906122SSteve.Reinhardt@amd.com}
1916122SSteve.Reinhardt@amd.com
1924626SN/Avoid
1938134SAli.Saidi@ARM.comProcess::kill(bool inc_kids)
1948134SAli.Saidi@ARM.com{
1958134SAli.Saidi@ARM.com    // Propogate the kill to our children no matter what happens to us.
1968134SAli.Saidi@ARM.com    if (inc_kids)
1978134SAli.Saidi@ARM.com        forEachKid([](Process *p) { p->kill(true); });
1982810SN/A
1992810SN/A    // If we're in the middle of unwinding, ignore the kill request.
2002810SN/A    if (_isUnwinding)
2012810SN/A        return;
2022810SN/A
2032810SN/A    // Update our state.
2046122SSteve.Reinhardt@amd.com    _terminated = true;
2056122SSteve.Reinhardt@amd.com    _isUnwinding = true;
2066122SSteve.Reinhardt@amd.com    _suspendedReady = false;
2072810SN/A    _suspended = false;
2082810SN/A    _syncReset = false;
2092810SN/A
2104626SN/A    // Inject the kill exception into this process.
2114626SN/A    injectException(killException);
2122810SN/A
2132810SN/A    _terminatedEvent.notify();
2142810SN/A}
2152810SN/A
2163503SN/Avoid
2173503SN/AProcess::reset(bool inc_kids)
2183503SN/A{
2196122SSteve.Reinhardt@amd.com    // Propogate the reset to our children no matter what happens to us.
2206122SSteve.Reinhardt@amd.com    if (inc_kids)
2216122SSteve.Reinhardt@amd.com        forEachKid([](Process *p) { p->reset(true); });
2226122SSteve.Reinhardt@amd.com
2236122SSteve.Reinhardt@amd.com    // If we're in the middle of unwinding, ignore the reset request.
2248833Sdam.sunwoo@arm.com    if (_isUnwinding)
2258833Sdam.sunwoo@arm.com        return;
2268833Sdam.sunwoo@arm.com
2276978SLisa.Hsu@amd.com    // Update our state.
2282810SN/A    _isUnwinding = true;
2292810SN/A
2302810SN/A    // Inject the reset exception into this process.
2312810SN/A    injectException(resetException);
2322810SN/A
2332810SN/A    _resetEvent.notify();
2342810SN/A}
2355999Snate@binkert.org
2362810SN/Avoid
2372810SN/AProcess::throw_it(ExceptionWrapperBase &exc, bool inc_kids)
2382810SN/A{
2392810SN/A    if (inc_kids)
2402810SN/A        forEachKid([&exc](Process *p) { p->throw_it(exc, true); });
2412810SN/A}
2425999Snate@binkert.org
2432810SN/Avoid
2442810SN/AProcess::injectException(ExceptionWrapperBase &exc)
2452810SN/A{
2462810SN/A    excWrapper = &exc;
2472810SN/A    scheduler.runNow(this);
2482810SN/A};
2492810SN/A
2502810SN/Avoid
2512810SN/AProcess::syncResetOn(bool inc_kids)
2525999Snate@binkert.org{
2532810SN/A    if (inc_kids)
2542810SN/A        forEachKid([](Process *p) { p->syncResetOn(true); });
2552810SN/A
2562810SN/A    _syncReset = true;
2572810SN/A}
2582810SN/A
2594022SN/Avoid
2602810SN/AProcess::syncResetOff(bool inc_kids)
2612810SN/A{
2622810SN/A    if (inc_kids)
2632810SN/A        forEachKid([](Process *p) { p->syncResetOff(true); });
2642810SN/A
2652810SN/A    _syncReset = false;
2664022SN/A}
2672810SN/A
2682810SN/Avoid
2692810SN/AProcess::dontInitialize()
2702810SN/A{
2712810SN/A    scheduler.dontInitialize(this);
2722810SN/A}
2734022SN/A
2742810SN/Avoid
2752810SN/AProcess::finalize()
2762810SN/A{
2772810SN/A    for (auto &s: pendingStaticSensitivities) {
2782810SN/A        s->finalize(staticSensitivities);
2792810SN/A        delete s;
2805999Snate@binkert.org        s = nullptr;
2812810SN/A    }
2825999Snate@binkert.org    pendingStaticSensitivities.clear();
2832810SN/A};
2842810SN/A
2852810SN/Avoid
2862810SN/AProcess::run()
2872810SN/A{
2885999Snate@binkert.org    bool reset;
2892810SN/A    do {
2902810SN/A        reset = false;
2915999Snate@binkert.org        try {
2922810SN/A            func->call();
2934626SN/A        } catch(const ::sc_core::sc_unwind_exception &exc) {
2945999Snate@binkert.org            reset = exc.is_reset();
2954626SN/A            _isUnwinding = false;
2964626SN/A        }
2975999Snate@binkert.org    } while (reset);
2984626SN/A    _terminated = true;
2994626SN/A}
3004626SN/A
3014626SN/Avoid
3024626SN/AProcess::addStatic(PendingSensitivity *s)
3034626SN/A{
3045999Snate@binkert.org    pendingStaticSensitivities.push_back(s);
3054626SN/A}
3064626SN/A
3074626SN/Avoid
3084626SN/AProcess::setDynamic(Sensitivity *s)
3094626SN/A{
3104626SN/A    delete dynamicSensitivity;
3115999Snate@binkert.org    dynamicSensitivity = s;
3124626SN/A}
3134626SN/A
3144626SN/Avoid
3154626SN/AProcess::satisfySensitivity(Sensitivity *s)
3165999Snate@binkert.org{
3174626SN/A    // If there's a dynamic sensitivity and this wasn't it, ignore.
3184626SN/A    if (dynamicSensitivity && dynamicSensitivity != s)
3194626SN/A        return;
3204626SN/A
3214626SN/A    setDynamic(nullptr);
3224626SN/A    ready();
3235999Snate@binkert.org}
3244626SN/A
3254626SN/Avoid
3264626SN/AProcess::ready()
3277461Snate@binkert.org{
3284626SN/A    if (disabled())
3294626SN/A        return;
3304626SN/A    if (suspended())
3314626SN/A        _suspendedReady = true;
3324626SN/A    else
3334626SN/A        scheduler.ready(this);
3347461Snate@binkert.org}
3354626SN/A
3364626SN/AProcess::Process(const char *name, ProcessFuncWrapper *func,
3374626SN/A        bool _dynamic, bool needs_start) :
3384626SN/A    ::sc_core::sc_object(name), excWrapper(nullptr), func(func),
3394626SN/A    _needsStart(needs_start), _dynamic(_dynamic), _isUnwinding(false),
3404626SN/A    _terminated(false), _suspended(false), _disabled(false),
3414626SN/A    _syncReset(false), refCount(0), stackSize(::Fiber::DefaultStackSize),
3424626SN/A    dynamicSensitivity(nullptr)
3434626SN/A{
3444626SN/A    _newest = this;
3454626SN/A}
3464626SN/A
3474626SN/AProcess *Process::_newest;
3484626SN/A
3494626SN/Avoid
3504626SN/Athrow_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids)
3514626SN/A{
3524626SN/A    p->throw_it(exc, inc_kids);
3534626SN/A}
3544626SN/A
3554626SN/A} // namespace sc_gem5
3565999Snate@binkert.org