112839Sgabeblack@google.com/*
212839Sgabeblack@google.com * Copyright 2018 Google, Inc.
312839Sgabeblack@google.com *
412839Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
512839Sgabeblack@google.com * modification, are permitted provided that the following conditions are
612839Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
712839Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
812839Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
912839Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1012839Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1112839Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1212839Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1312839Sgabeblack@google.com * this software without specific prior written permission.
1412839Sgabeblack@google.com *
1512839Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1612839Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1712839Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1812839Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1912839Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2012839Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2112839Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2212839Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2312839Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2412839Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2512839Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2612839Sgabeblack@google.com *
2712839Sgabeblack@google.com * Authors: Gabe Black
2812839Sgabeblack@google.com */
2912839Sgabeblack@google.com
3012839Sgabeblack@google.com#ifndef __SYSTEMC_EXT_CORE_SC_SPAWN_HH__
3112839Sgabeblack@google.com#define __SYSTEMC_EXT_CORE_SC_SPAWN_HH__
3212839Sgabeblack@google.com
3313267Sgabeblack@google.com#include <functional>
3412993Sgabeblack@google.com#include <vector>
3512993Sgabeblack@google.com
3613196Sgabeblack@google.com#include "sc_join.hh"
3712839Sgabeblack@google.com#include "sc_process_handle.hh"
3812839Sgabeblack@google.com
3912839Sgabeblack@google.comnamespace sc_core
4012839Sgabeblack@google.com{
4112839Sgabeblack@google.com
4212993Sgabeblack@google.comclass sc_spawn_options;
4312993Sgabeblack@google.com
4412993Sgabeblack@google.com} // namespace sc_core
4512993Sgabeblack@google.com
4612993Sgabeblack@google.comnamespace sc_gem5
4712993Sgabeblack@google.com{
4812993Sgabeblack@google.com
4912993Sgabeblack@google.comclass Process;
5012993Sgabeblack@google.com
5112993Sgabeblack@google.comtemplate <typename T>
5212993Sgabeblack@google.comstruct ProcessObjFuncWrapper : public ProcessFuncWrapper
5312993Sgabeblack@google.com{
5412993Sgabeblack@google.com    T t;
5512993Sgabeblack@google.com
5612993Sgabeblack@google.com    ProcessObjFuncWrapper(T t) : t(t) {}
5712993Sgabeblack@google.com
5812993Sgabeblack@google.com    void call() override { t(); }
5912993Sgabeblack@google.com};
6012993Sgabeblack@google.com
6112993Sgabeblack@google.comtemplate <typename T, typename R>
6212993Sgabeblack@google.comstruct ProcessObjRetFuncWrapper : public ProcessFuncWrapper
6312993Sgabeblack@google.com{
6412993Sgabeblack@google.com    T t;
6512993Sgabeblack@google.com    R *r;
6612993Sgabeblack@google.com
6712993Sgabeblack@google.com    ProcessObjRetFuncWrapper(T t, R *r) : t(t), r(r) {}
6812993Sgabeblack@google.com
6912993Sgabeblack@google.com    void call() override { *r = t(); }
7012993Sgabeblack@google.com};
7112993Sgabeblack@google.com
7212993Sgabeblack@google.comProcess *spawnWork(ProcessFuncWrapper *func, const char *name,
7312993Sgabeblack@google.com                   const ::sc_core::sc_spawn_options *);
7412993Sgabeblack@google.com
7512993Sgabeblack@google.com} // namespace sc_gem5
7612993Sgabeblack@google.com
7712993Sgabeblack@google.comnamespace sc_core
7812993Sgabeblack@google.com{
7912993Sgabeblack@google.com
8012839Sgabeblack@google.comtemplate <class T>
8112839Sgabeblack@google.comclass sc_in;
8212839Sgabeblack@google.comtemplate <class T>
8312839Sgabeblack@google.comclass sc_inout;
8412839Sgabeblack@google.comtemplate <class T>
8512839Sgabeblack@google.comclass sc_out;
8612839Sgabeblack@google.comtemplate <class T>
8712839Sgabeblack@google.comclass sc_signal_in_if;
8812839Sgabeblack@google.com
8912839Sgabeblack@google.comclass sc_event;
9012839Sgabeblack@google.comclass sc_event_finder;
9112839Sgabeblack@google.comclass sc_export_base;
9212839Sgabeblack@google.comclass sc_interface;
9312839Sgabeblack@google.comclass sc_port_base;
9412839Sgabeblack@google.com
9512839Sgabeblack@google.comclass sc_spawn_options
9612839Sgabeblack@google.com{
9712839Sgabeblack@google.com  public:
9812993Sgabeblack@google.com    friend ::sc_gem5::Process *::sc_gem5::spawnWork(
9912993Sgabeblack@google.com            ::sc_gem5::ProcessFuncWrapper *, const char *,
10012993Sgabeblack@google.com            const sc_spawn_options *);
10112993Sgabeblack@google.com
10212839Sgabeblack@google.com    sc_spawn_options();
10312839Sgabeblack@google.com
10412839Sgabeblack@google.com    void spawn_method();
10512839Sgabeblack@google.com    void dont_initialize();
10612839Sgabeblack@google.com    void set_stack_size(int);
10712839Sgabeblack@google.com
10812839Sgabeblack@google.com    void set_sensitivity(const sc_event *);
10912839Sgabeblack@google.com    void set_sensitivity(sc_port_base *);
11012839Sgabeblack@google.com    void set_sensitivity(sc_export_base *);
11112839Sgabeblack@google.com    void set_sensitivity(sc_interface *);
11212839Sgabeblack@google.com    void set_sensitivity(sc_event_finder *);
11312839Sgabeblack@google.com
11412839Sgabeblack@google.com    void reset_signal_is(const sc_in<bool> &, bool);
11512839Sgabeblack@google.com    void reset_signal_is(const sc_inout<bool> &, bool);
11612839Sgabeblack@google.com    void reset_signal_is(const sc_out<bool> &, bool);
11712839Sgabeblack@google.com    void reset_signal_is(const sc_signal_in_if<bool> &, bool);
11812839Sgabeblack@google.com
11912839Sgabeblack@google.com    void async_reset_signal_is(const sc_in<bool> &, bool);
12012839Sgabeblack@google.com    void async_reset_signal_is(const sc_inout<bool> &, bool);
12112839Sgabeblack@google.com    void async_reset_signal_is(const sc_out<bool> &, bool);
12212839Sgabeblack@google.com    void async_reset_signal_is(const sc_signal_in_if<bool> &, bool);
12312839Sgabeblack@google.com
12412839Sgabeblack@google.com  private:
12512993Sgabeblack@google.com    bool _spawnMethod;
12612993Sgabeblack@google.com    bool _dontInitialize;
12712993Sgabeblack@google.com    int _stackSize;
12812993Sgabeblack@google.com    std::vector<const sc_event *> _events;
12912993Sgabeblack@google.com    std::vector<sc_port_base *> _ports;
13012993Sgabeblack@google.com    std::vector<sc_export_base *> _exports;
13112993Sgabeblack@google.com    std::vector<sc_interface *> _interfaces;
13212993Sgabeblack@google.com    std::vector<sc_event_finder *> _finders;
13312993Sgabeblack@google.com
13413260Sgabeblack@google.com    template <typename T>
13513260Sgabeblack@google.com    struct Reset
13613260Sgabeblack@google.com    {
13713260Sgabeblack@google.com        Reset(T *t, bool v, bool s) : target(t), value(v), sync(s) {}
13813260Sgabeblack@google.com
13913260Sgabeblack@google.com        T *target;
14013260Sgabeblack@google.com        bool value;
14113260Sgabeblack@google.com        bool sync;
14213260Sgabeblack@google.com    };
14313260Sgabeblack@google.com
14413260Sgabeblack@google.com    std::vector<Reset<const sc_in<bool> > > _in_resets;
14513260Sgabeblack@google.com    std::vector<Reset<const sc_inout<bool> > > _inout_resets;
14613260Sgabeblack@google.com    std::vector<Reset<const sc_out<bool> > > _out_resets;
14713260Sgabeblack@google.com    std::vector<Reset<const sc_signal_in_if<bool> > > _if_resets;
14813260Sgabeblack@google.com
14912839Sgabeblack@google.com    // Disabled
15012839Sgabeblack@google.com    sc_spawn_options(const sc_spawn_options &) {}
15112839Sgabeblack@google.com    sc_spawn_options &operator = (const sc_spawn_options &) { return *this; }
15212839Sgabeblack@google.com};
15312839Sgabeblack@google.com
15412839Sgabeblack@google.comtemplate <typename T>
15512839Sgabeblack@google.comsc_process_handle
15612839Sgabeblack@google.comsc_spawn(T object, const char *name_p=nullptr,
15712839Sgabeblack@google.com         const sc_spawn_options *opt_p=nullptr)
15812839Sgabeblack@google.com{
15912993Sgabeblack@google.com    auto func = new ::sc_gem5::ProcessObjFuncWrapper<T>(object);
16012993Sgabeblack@google.com    ::sc_gem5::Process *p = spawnWork(func, name_p, opt_p);
16112993Sgabeblack@google.com    return sc_process_handle() = p;
16212839Sgabeblack@google.com}
16312839Sgabeblack@google.com
16412839Sgabeblack@google.comtemplate <typename T>
16512839Sgabeblack@google.comsc_process_handle
16612839Sgabeblack@google.comsc_spawn(typename T::result_type *r_p, T object, const char *name_p=nullptr,
16712839Sgabeblack@google.com         const sc_spawn_options *opt_p=nullptr)
16812839Sgabeblack@google.com{
16912993Sgabeblack@google.com    auto func = new ::sc_gem5::ProcessObjRetFuncWrapper<
17012993Sgabeblack@google.com        T, typename T::result_type>(object, r_p);
17112993Sgabeblack@google.com    ::sc_gem5::Process *p = spawnWork(func, name_p, opt_p);
17212993Sgabeblack@google.com    return sc_process_handle() = p;
17312839Sgabeblack@google.com}
17412839Sgabeblack@google.com
17512879Sgabeblack@google.com#define SC_FORK \
17612879Sgabeblack@google.com{ \
17712879Sgabeblack@google.com    ::sc_core::sc_process_handle forkees[] = {
17812879Sgabeblack@google.com
17912879Sgabeblack@google.com#define SC_JOIN \
18013196Sgabeblack@google.com    }; \
18113196Sgabeblack@google.com    ::sc_core::sc_join join; \
18213196Sgabeblack@google.com    for (int i = 0; i < sizeof(forkees) / sizeof(forkees[0]); i++) \
18313196Sgabeblack@google.com        join.add_process(forkees[i]); \
18413196Sgabeblack@google.com    join.wait(); \
18512879Sgabeblack@google.com}
18612879Sgabeblack@google.com
18712879Sgabeblack@google.com// Non-standard
18813196Sgabeblack@google.com#define SC_CJOIN \
18913196Sgabeblack@google.com    }; \
19013196Sgabeblack@google.com    ::sc_core::sc_join join; \
19113196Sgabeblack@google.com    for (int i = 0; i < sizeof(forkees) / sizeof(forkees[0]); i++) \
19213196Sgabeblack@google.com        join.add_process(forkees[i]); \
19313196Sgabeblack@google.com    join.wait_clocked(); \
19413196Sgabeblack@google.com}
19513196Sgabeblack@google.com
19613267Sgabeblack@google.com// This avoids boost introduces a dependency on c++11. If that's a problem,
19713267Sgabeblack@google.com// we could imitate Accellera and pick which one to use on the fly.
19813267Sgabeblack@google.com
19913267Sgabeblack@google.comtemplate <typename F, typename... Args>
20013267Sgabeblack@google.comauto sc_bind(F &&f, Args && ...args) ->
20113267Sgabeblack@google.com    decltype(std::bind(std::forward<F>(f), std::forward<Args>(args)...))
20213267Sgabeblack@google.com{
20313267Sgabeblack@google.com    return std::bind(std::forward<F>(f), std::forward<Args>(args)...);
20413267Sgabeblack@google.com}
20513267Sgabeblack@google.com
20613267Sgabeblack@google.comtemplate <typename T>
20713267Sgabeblack@google.comauto sc_ref(T &&v) -> decltype(std::ref(std::forward<T>(v)))
20813267Sgabeblack@google.com{
20913267Sgabeblack@google.com    return std::ref(std::forward<T>(v));
21013267Sgabeblack@google.com}
21113267Sgabeblack@google.com
21213267Sgabeblack@google.comtemplate <typename T>
21313267Sgabeblack@google.comauto sc_cref(T &&v) -> decltype(std::cref(std::forward<T>(v)))
21413267Sgabeblack@google.com{
21513267Sgabeblack@google.com    return std::cref(std::forward<T>(v));
21613267Sgabeblack@google.com}
21712839Sgabeblack@google.com
21812839Sgabeblack@google.com} // namespace sc_core
21912839Sgabeblack@google.com
22013267Sgabeblack@google.comusing sc_core::sc_bind;
22113267Sgabeblack@google.comusing sc_core::sc_ref;
22213267Sgabeblack@google.comusing sc_core::sc_cref;
22313267Sgabeblack@google.com
22412839Sgabeblack@google.comnamespace sc_unnamed
22512839Sgabeblack@google.com{
22612839Sgabeblack@google.com
22713267Sgabeblack@google.comusing namespace std::placeholders;
22812839Sgabeblack@google.com
22912839Sgabeblack@google.com} // namespace sc_unnamed
23012839Sgabeblack@google.com
23112839Sgabeblack@google.com#endif  //__SYSTEMC_EXT_CORE_SC_SPAWN_HH__
232