1/* 2 * Copyright 2018 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution; 11 * neither the name of the copyright holders nor the names of its 12 * contributors may be used to endorse or promote products derived from 13 * this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Authors: Gabe Black 28 */ 29 30#ifndef __SYSTEMC_EXT_CORE_SC_SPAWN_HH__ 31#define __SYSTEMC_EXT_CORE_SC_SPAWN_HH__ 32 33#include <functional> 34#include <vector> 35 36#include "sc_join.hh" 37#include "sc_process_handle.hh" 38 39namespace sc_core 40{ 41 42class sc_spawn_options; 43 44} // namespace sc_core 45 46namespace sc_gem5 47{ 48 49class Process; 50 51template <typename T> 52struct ProcessObjFuncWrapper : public ProcessFuncWrapper 53{ 54 T t; 55 56 ProcessObjFuncWrapper(T t) : t(t) {} 57 58 void call() override { t(); } 59}; 60 61template <typename T, typename R> 62struct ProcessObjRetFuncWrapper : public ProcessFuncWrapper 63{ 64 T t; 65 R *r; 66 67 ProcessObjRetFuncWrapper(T t, R *r) : t(t), r(r) {} 68 69 void call() override { *r = t(); } 70}; 71 72Process *spawnWork(ProcessFuncWrapper *func, const char *name, 73 const ::sc_core::sc_spawn_options *); 74 75} // namespace sc_gem5 76 77namespace sc_core 78{ 79 80template <class T> 81class sc_in; 82template <class T> 83class sc_inout; 84template <class T> 85class sc_out; 86template <class T> 87class sc_signal_in_if; 88 89class sc_event; 90class sc_event_finder; 91class sc_export_base; 92class sc_interface; 93class sc_port_base; 94 95class sc_spawn_options 96{ 97 public: 98 friend ::sc_gem5::Process *::sc_gem5::spawnWork( 99 ::sc_gem5::ProcessFuncWrapper *, const char *, 100 const sc_spawn_options *); 101 102 sc_spawn_options(); 103 104 void spawn_method(); 105 void dont_initialize(); 106 void set_stack_size(int); 107 108 void set_sensitivity(const sc_event *); 109 void set_sensitivity(sc_port_base *); 110 void set_sensitivity(sc_export_base *); 111 void set_sensitivity(sc_interface *); 112 void set_sensitivity(sc_event_finder *); 113 114 void reset_signal_is(const sc_in<bool> &, bool); 115 void reset_signal_is(const sc_inout<bool> &, bool); 116 void reset_signal_is(const sc_out<bool> &, bool); 117 void reset_signal_is(const sc_signal_in_if<bool> &, bool); 118 119 void async_reset_signal_is(const sc_in<bool> &, bool); 120 void async_reset_signal_is(const sc_inout<bool> &, bool); 121 void async_reset_signal_is(const sc_out<bool> &, bool); 122 void async_reset_signal_is(const sc_signal_in_if<bool> &, bool); 123 124 private: 125 bool _spawnMethod; 126 bool _dontInitialize; 127 int _stackSize; 128 std::vector<const sc_event *> _events; 129 std::vector<sc_port_base *> _ports; 130 std::vector<sc_export_base *> _exports; 131 std::vector<sc_interface *> _interfaces; 132 std::vector<sc_event_finder *> _finders; 133 134 template <typename T> 135 struct Reset 136 { 137 Reset(T *t, bool v, bool s) : target(t), value(v), sync(s) {} 138 139 T *target; 140 bool value; 141 bool sync; 142 }; 143 144 std::vector<Reset<const sc_in<bool> > > _in_resets; 145 std::vector<Reset<const sc_inout<bool> > > _inout_resets; 146 std::vector<Reset<const sc_out<bool> > > _out_resets; 147 std::vector<Reset<const sc_signal_in_if<bool> > > _if_resets; 148 149 // Disabled 150 sc_spawn_options(const sc_spawn_options &) {} 151 sc_spawn_options &operator = (const sc_spawn_options &) { return *this; } 152}; 153 154template <typename T> 155sc_process_handle 156sc_spawn(T object, const char *name_p=nullptr, 157 const sc_spawn_options *opt_p=nullptr) 158{ 159 auto func = new ::sc_gem5::ProcessObjFuncWrapper<T>(object); 160 ::sc_gem5::Process *p = spawnWork(func, name_p, opt_p); 161 return sc_process_handle() = p; 162} 163 164template <typename T> 165sc_process_handle 166sc_spawn(typename T::result_type *r_p, T object, const char *name_p=nullptr, 167 const sc_spawn_options *opt_p=nullptr) 168{ 169 auto func = new ::sc_gem5::ProcessObjRetFuncWrapper< 170 T, typename T::result_type>(object, r_p); 171 ::sc_gem5::Process *p = spawnWork(func, name_p, opt_p); 172 return sc_process_handle() = p; 173} 174 175#define SC_FORK \ 176{ \ 177 ::sc_core::sc_process_handle forkees[] = { 178 179#define SC_JOIN \ 180 }; \ 181 ::sc_core::sc_join join; \ 182 for (int i = 0; i < sizeof(forkees) / sizeof(forkees[0]); i++) \ 183 join.add_process(forkees[i]); \ 184 join.wait(); \ 185} 186 187// Non-standard 188#define SC_CJOIN \ 189 }; \ 190 ::sc_core::sc_join join; \ 191 for (int i = 0; i < sizeof(forkees) / sizeof(forkees[0]); i++) \ 192 join.add_process(forkees[i]); \ 193 join.wait_clocked(); \ 194} 195 196// This avoids boost introduces a dependency on c++11. If that's a problem, 197// we could imitate Accellera and pick which one to use on the fly. 198 199template <typename F, typename... Args> 200auto sc_bind(F &&f, Args && ...args) -> 201 decltype(std::bind(std::forward<F>(f), std::forward<Args>(args)...)) 202{ 203 return std::bind(std::forward<F>(f), std::forward<Args>(args)...); 204} 205 206template <typename T> 207auto sc_ref(T &&v) -> decltype(std::ref(std::forward<T>(v))) 208{ 209 return std::ref(std::forward<T>(v)); 210} 211 212template <typename T> 213auto sc_cref(T &&v) -> decltype(std::cref(std::forward<T>(v))) 214{ 215 return std::cref(std::forward<T>(v)); 216} 217 218} // namespace sc_core 219 220using sc_core::sc_bind; 221using sc_core::sc_ref; 222using sc_core::sc_cref; 223 224namespace sc_unnamed 225{ 226 227using namespace std::placeholders; 228 229} // namespace sc_unnamed 230 231#endif //__SYSTEMC_EXT_CORE_SC_SPAWN_HH__ 232