| /* | |
| * Copyright 2018 Google, Inc. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution; | |
| * neither the name of the copyright holders nor the names of its | |
| * contributors may be used to endorse or promote products derived from | |
| * this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * Authors: Gabe Black | |
| */ | |
| #ifndef __SYSTEMC_CORE_PROCESS_HH__ | |
| #define __SYSTEMC_CORE_PROCESS_HH__ | |
| #include <functional> | |
| #include <memory> | |
| #include <vector> | |
| #include "base/fiber.hh" | |
| #include "systemc/core/list.hh" | |
| #include "systemc/core/module.hh" | |
| #include "systemc/core/object.hh" | |
| #include "systemc/core/sched_event.hh" | |
| #include "systemc/core/sensitivity.hh" | |
| #include "systemc/ext/channel/sc_signal_in_if.hh" | |
| #include "systemc/ext/core/sc_event.hh" | |
| #include "systemc/ext/core/sc_module.hh" | |
| #include "systemc/ext/core/sc_process_handle.hh" | |
| namespace sc_core | |
| { | |
| class sc_join; | |
| } // namespace sc_core | |
| namespace sc_gem5 | |
| { | |
| class ScHalt | |
| {}; | |
| class Process; | |
| class Reset; | |
| class Process : public ::sc_core::sc_process_b, public ListNode | |
| { | |
| public: | |
| virtual ::sc_core::sc_curr_proc_kind procKind() const = 0; | |
| bool needsStart() const { return _needsStart; } | |
| void needsStart(bool ns) { _needsStart = ns; } | |
| bool dynamic() const { return _dynamic; } | |
| bool isUnwinding() const { return _isUnwinding; } | |
| void isUnwinding(bool v) { _isUnwinding = v; } | |
| bool terminated() const { return _terminated; } | |
| bool scheduled() const { return _scheduled; } | |
| void scheduled(bool new_val) { _scheduled = new_val; } | |
| void forEachKid(const std::function<void(Process *)> &work); | |
| bool suspended() const { return _suspended; } | |
| bool disabled() const { return _disabled; } | |
| void suspend(bool inc_kids); | |
| void resume(bool inc_kids); | |
| void disable(bool inc_kids); | |
| void enable(bool inc_kids); | |
| void kill(bool inc_kids); | |
| void reset(bool inc_kids); | |
| void throw_it(ExceptionWrapperBase &exc, bool inc_kids); | |
| void injectException(ExceptionWrapperBase &exc); | |
| ExceptionWrapperBase *excWrapper; | |
| void syncResetOn(bool inc_kids); | |
| void syncResetOff(bool inc_kids); | |
| void signalReset(bool set, bool sync); | |
| void incref() { refCount++; } | |
| void decref() { refCount--; } | |
| ::sc_core::sc_event &resetEvent() { return _resetEvent; } | |
| ::sc_core::sc_event &terminatedEvent() { return _terminatedEvent; } | |
| void setStackSize(size_t size) { stackSize = size; } | |
| void run(); | |
| void addStatic(StaticSensitivity *); | |
| void setDynamic(DynamicSensitivity *); | |
| void clearDynamic() { setDynamic(nullptr); } | |
| void addReset(Reset *); | |
| ScEvent timeoutEvent; | |
| void setTimeout(::sc_core::sc_time t); | |
| void cancelTimeout(); | |
| void satisfySensitivity(Sensitivity *); | |
| void ready(); | |
| virtual Fiber *fiber() { return Fiber::primaryFiber(); } | |
| static Process *newest() { return _newest; } | |
| void lastReport(::sc_core::sc_report *report); | |
| ::sc_core::sc_report *lastReport() const; | |
| bool hasStaticSensitivities() { return !staticSensitivities.empty(); } | |
| bool internal() { return _internal; } | |
| bool timedOut() { return _timedOut; } | |
| bool inReset() { return _syncReset || syncResetCount || asyncResetCount; } | |
| bool dontInitialize() { return _dontInitialize; } | |
| void dontInitialize(bool di) { _dontInitialize = di; } | |
| void joinWait(::sc_core::sc_join *join) { joinWaiters.push_back(join); } | |
| void waitCount(int count) { _waitCount = count; } | |
| const char *uniqueName(const char *seed) { return nameGen.gen(seed); } | |
| protected: | |
| void timeout(); | |
| Process(const char *name, ProcessFuncWrapper *func, bool internal=false); | |
| static Process *_newest; | |
| virtual ~Process() | |
| { | |
| popListNode(); | |
| delete func; | |
| for (auto s: staticSensitivities) { | |
| s->clear(); | |
| delete s; | |
| } | |
| clearDynamic(); | |
| } | |
| InternalScEvent _resetEvent; | |
| InternalScEvent _terminatedEvent; | |
| ProcessFuncWrapper *func; | |
| bool _internal; | |
| // Needed to support the deprecated "timed_out" function. | |
| bool _timedOut; | |
| bool _dontInitialize; | |
| bool _needsStart; | |
| bool _dynamic; | |
| bool _isUnwinding; | |
| bool _terminated; | |
| bool _scheduled; | |
| void terminate(); | |
| bool _suspended; | |
| bool _suspendedReady; | |
| bool _disabled; | |
| bool _syncReset; | |
| int syncResetCount; | |
| int asyncResetCount; | |
| int _waitCount; | |
| int refCount; | |
| size_t stackSize; | |
| StaticSensitivities staticSensitivities; | |
| DynamicSensitivity *dynamicSensitivity; | |
| std::vector<Reset *> resets; | |
| std::unique_ptr<::sc_core::sc_report> _lastReport; | |
| std::vector<::sc_core::sc_join *> joinWaiters; | |
| UniqueNameGen nameGen; | |
| }; | |
| class Reset | |
| { | |
| public: | |
| Reset(Process *p, bool s, bool v) : | |
| _process(p), _signal(nullptr), _sync(s), _value(v) | |
| {} | |
| bool | |
| install(const sc_core::sc_signal_in_if<bool> *s) | |
| { | |
| _signal = s; | |
| if (_signal->_addReset(this)) { | |
| _process->addReset(this); | |
| if (_signal->read() == _value) | |
| update(); | |
| return true; | |
| } | |
| return false; | |
| } | |
| void update() { _process->signalReset(_signal->read() == _value, _sync); } | |
| Process *process() { return _process; } | |
| const sc_core::sc_signal_in_if<bool> *signal() { return _signal; } | |
| bool sync() { return _sync; } | |
| bool value() { return _value; } | |
| private: | |
| Process *_process; | |
| const sc_core::sc_signal_in_if<bool> *_signal; | |
| bool _sync; | |
| bool _value; | |
| }; | |
| void newReset(const sc_core::sc_port_base *pb, Process *p, bool s, bool v); | |
| void newReset(const sc_core::sc_signal_in_if<bool> *sig, Process *p, | |
| bool s, bool v); | |
| } // namespace sc_gem5 | |
| #endif //__SYSTEMC_CORE_PROCESS_HH__ |