rc_process_support.h

Go to the documentation of this file.
00001 // vim:set et sts=4 ts=4 tw=75 sw=4 ai ci cin cino=g0,t0:
00002 /*
00003  * Copyright (C) 2007, Technical Computer Science Group,
00004  *                     University of Bonn
00005  *
00006  * This file is part of the ReChannel library.
00007  *
00008  * The ReChannel library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License as
00010  * published by the Free Software Foundation; either version 2 of the
00011  * License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be
00014  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this library; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
00021  * Boston, MA 02110-1301, USA.
00022  *
00023  * Authors: Andreas Raabe and Armin Felke. Implementation by Armin Felke.
00024  *          {raabe, felke}@cs.uni-bonn.de
00025  */
00037 #ifndef RC_PROCESS_SUPPORT_H_
00038 #define RC_PROCESS_SUPPORT_H_
00039 
00040 #include "ReChannel/core/rc_reconfigurable.h"
00041 #include "ReChannel/core/rc_non_reconfigurable.h"
00042 #include "ReChannel/core/rc_reset_channel_if.h"
00043 
00044 namespace ReChannel {
00045 
00046 class rc_process_reset;
00047 
00048 namespace internals {
00049 
00068 class process_support
00069     : public sc_prim_channel
00070 {
00071 private:
00072     class process_info;
00073 
00074 private:
00075     typedef rc_hash_map<sc_object*, process_info*> process_info_map;
00076 
00077 public:
00078     process_support();
00079 
00080     inline bool has_reconfigurable_context() const
00081         { return (&p_reconf != &rc_non_reconfigurable::get_instance()); }
00082 
00083     inline bool has_non_reconfigurable_context() const
00084         { return (&p_reconf == &rc_non_reconfigurable::get_instance()); }
00085 
00086     inline rc_reconfigurable& get_context() const
00087         { return p_reconf; }
00088 
00089     inline rc_reconfigurable* get_reconfigurable_context() const;
00090 
00091     void declare_process(
00092         const sc_object& host,
00093         const boost::function<void (void)>& declare_proc_callback,
00094         const boost::function<void (void)>& func, sc_sensitive& sensitive,
00095         bool is_thread=false, bool dont_initialize=false,
00096         bool has_sync_reset=false);
00097 
00098     void method_process();
00099 
00100     void thread_process();
00101 
00102     void dont_initialize(const sc_object& host) const;
00103 
00104     // spawns a new, reconfigurable process
00105      rc_process_handle rc_spawn(
00106         boost::function<void (void)> func, const char* name_p=NULL,
00107         rc_spawn_options* opt_p=NULL);
00108 
00109     void terminate();
00110 
00111     bool reset_signal_is(
00112         const sc_object& host, const sc_in<bool>& port_,
00113         bool active_level);
00114 
00115     bool reset_signal_is(
00116         const sc_object& host, const sc_signal<bool>& signal_,
00117         bool active_level);
00118 
00119     const sc_signal<bool>* reset_channel_is(
00120         const sc_object& host, rc_reset_channel_if& reset_,
00121         bool active_level);
00122 
00123     void reset_is(const sc_object& host, rc_process_reset& process_reset);
00124 
00125     void set_sync_reset(const sc_object& host, bool b) const;
00126 
00127     rc_process_behavior_change disable_process_control() const;
00128 
00129 protected:
00130     void before_end_of_elaboration();
00131 
00132 private:
00133     process_info* _rc_find_process_info(sc_object* proc_obj) const;
00134 
00135     process_info* _rc_fetch_process_info(sc_object* proc_obj);
00136 
00137     bool _rc_check_valid_last_proc(const sc_object& host) const;
00138 
00139 private:
00140     static rc_reconfigurable& _rc_find_context(sc_object* start_search);
00141 
00142     static inline void register_process_control(
00143         const rc_reset_channel_if& reset_channel,
00144         rc_process_control& pctrl, bool active_level)
00145         { reset_channel.register_process_control(pctrl, active_level); }
00146 
00147     static inline void unregister_process_control(
00148         const rc_reset_channel_if& reset_channel,
00149         rc_process_control& pctrl)
00150         { reset_channel.unregister_process_control(pctrl); }
00151 
00152     static inline bool get_current_level(
00153         const rc_reset_channel_if& reset_channel)
00154         { return reset_channel.get_current_level(); }
00155 
00156 private:
00157     rc_reconfigurable& p_reconf;
00158     process_info_map   p_reconf_pinfo_map; // TODO: static hashmap?
00159     process_info*      p_last_pinfo;
00160     const sc_object*   p_last_host;
00161     unsigned int       p_last_host_child_count;
00162 };
00163 
00168 class process_support::process_info
00169 {
00170 private:
00171     typedef std::vector<const rc_reset_channel_if*> reset_channel_vector;
00172     typedef std::vector<const sc_in<bool>*>         reset_port_vector;
00173     typedef internals::reset_signal                 reset_signal;
00174     typedef std::map<const sc_signal_in_if<bool>*, reset_signal*>
00175                                                     reset_signal_map;
00176 public:
00177     process_info(
00178         boost::function<void (void)> func_,
00179         const rc_process_control& parent_pctrl, bool is_thread_=false,
00180         bool is_dont_initialize=false, bool has_sync_reset=false);
00181 
00182     inline bool is_thread() const
00183         { return p_is_thread; }
00184 
00185     inline bool is_dont_initialize() const
00186         { return p_is_dont_initialize; }
00187 
00188     inline void set_dont_initialize(bool b)
00189         { p_is_dont_initialize = b; }
00190 
00191     inline bool has_sync_reset() const
00192         { return process_control.is_deactivate_silently(); }
00193 
00194     inline void set_sync_reset(bool b)
00195         { process_control.set_deactivate_silently(b); }
00196 
00197     inline bool is_init_run() const
00198         { return p_is_init_run; }
00199 
00200     inline void set_init_run(bool b)
00201         { p_is_init_run = b; }
00202 
00203     void register_reset_channel(
00204         const rc_reset_channel_if& reset_channel, bool active_level);
00205 
00206     void register_reset_interface(
00207         const sc_signal_in_if<bool>& reset_interface, bool active_level);
00208 
00209     void register_reset_signal(
00210         const sc_signal<bool>& reset_signal, bool active_level);
00211 
00212     void register_reset_port(
00213         const sc_in<bool>& reset_port, bool active_level);
00214 
00215     void register_reset_port_interfaces();
00216 
00217     void update_process_control_state();
00218 
00219     ~process_info();
00220 
00221 private:
00222     static const rc_reset_channel_if& _rc_get_reset_channel(
00223         const sc_signal_in_if<bool>& signal_interface);
00224 
00225     static void _rc_reset_updater_proc(
00226         const sc_signal_in_if<bool>& from_, reset_signal& to_);
00227 
00228 public:
00229     boost::function<void (void)> func;
00230     rc_process_control     process_control;
00231 
00232 private:
00233     bool                   p_is_thread          : 1;
00234     bool                   p_is_dont_initialize : 1;
00235     bool                   p_is_init_run        : 1;
00236     reset_channel_vector   p_reset_channels[2];
00237     reset_port_vector      p_reset_ports[2];
00238 
00239 private:
00240     static reset_signal_map p_reset_signal_map;
00241 };
00242 
00243 } // namespace internals
00244 
00266 class rc_process_reset
00267     : public sc_prim_channel,
00268       protected rc_reset_channel_if
00269 {
00270     friend class internals::process_support;
00271 
00272 private:
00273     typedef std::set<rc_process_control*> pctrl_set;
00274 
00275 public:
00276     explicit rc_process_reset();
00277 
00278     explicit rc_process_reset(const char* name_);
00279 
00280 public:
00284     virtual void trigger();
00285 
00286 protected:
00287     // registers a process control at the reset list
00288     virtual void register_process_control(
00289         rc_process_control& pctrl, bool active_level) const;
00290 
00291     // unregisters a process control from the reset list
00292     virtual void unregister_process_control(
00293         rc_process_control& pctrl) const;
00294 
00295     // always returns the inactive level: 'false'
00296     virtual bool get_current_level() const
00297         { return false; }
00298 
00299     // always returns NULL
00300     virtual const sc_signal<bool>* get_underlying_reset_signal() const
00301         { return NULL; }
00302 
00303 private:
00304     mutable pctrl_set p_pctrl_set;
00305 };
00306 
00307 /* inline code */
00308 
00309 namespace internals {
00310 
00311 inline
00312 rc_reconfigurable* process_support::get_reconfigurable_context() const
00313 {
00314     if (&p_reconf != &rc_non_reconfigurable::get_instance()) {
00315         return &p_reconf;
00316     } else {
00317         return NULL;
00318     }
00319 }
00320 
00321 } // namespace internals
00322 
00323 } // namespace ReChannel
00324 
00325 /* construction and helper macros */
00326 
00327 #define RC_HAS_RECONFIGURABLE_PROCESS(user_module_name) \
00328     SC_HAS_PROCESS(user_module_name); \
00329     private: \
00330         internals::process_support \
00331             _rc_process_support; \
00332         void _rc_declare_method() \
00333             { SC_METHOD(_rc_method_process); } \
00334         void _rc_declare_thread() \
00335             { SC_THREAD(_rc_thread_process); } \
00336         void _rc_method_process() \
00337             { this->_rc_process_support.method_process(); } \
00338         void _rc_thread_process() \
00339             { this->_rc_process_support.thread_process(); } \
00340     protected: \
00341         inline void next_trigger() \
00342             { rc_next_trigger(); } \
00343         inline void next_trigger(const sc_event& e) \
00344             { rc_next_trigger(e); } \
00345         inline void next_trigger(sc_event_or_list& el) \
00346             { rc_next_trigger(el); } \
00347         inline void next_trigger(sc_event_and_list& el) \
00348             { rc_next_trigger(el); } \
00349         inline void next_trigger(const sc_time& t) \
00350             { rc_next_trigger(t); } \
00351         inline void next_trigger(double v, sc_time_unit tu) \
00352             { rc_next_trigger(v, tu); } \
00353         inline void next_trigger(const sc_time& t, const sc_event& e) \
00354             { rc_next_trigger(t, e); } \
00355         inline void next_trigger( \
00356             double v, sc_time_unit tu, const sc_event& e) \
00357             { rc_next_trigger(v, tu, e); } \
00358         inline void next_trigger(const sc_time& t, sc_event_or_list& el) \
00359             { rc_next_trigger(t, el); } \
00360         inline void next_trigger( \
00361             double v, sc_time_unit t, sc_event_or_list& el) \
00362             { rc_next_trigger(v, t, el); } \
00363         inline void next_trigger(const sc_time& t, sc_event_and_list& el) \
00364             { rc_next_trigger(t, el); } \
00365         inline void next_trigger( \
00366             double v, sc_time_unit tu, sc_event_and_list& el) \
00367             { rc_next_trigger(v, tu, el); } \
00368         inline void wait() \
00369             { rc_wait(); } \
00370         inline void wait(int n) \
00371             { rc_wait(n); } \
00372         inline void wait(const sc_event& e) \
00373             { rc_wait(e); } \
00374         inline void wait(sc_event_or_list& el) \
00375             { rc_wait(el); } \
00376         inline void wait(sc_event_and_list& el) \
00377             { rc_wait(el); } \
00378         inline void wait(const sc_time& t) \
00379             { rc_wait(t); } \
00380         inline void wait(double v, sc_time_unit tu) \
00381             { rc_wait(v, tu); } \
00382         inline void wait(const sc_time& t, const sc_event& e) \
00383             { rc_wait(t, e); } \
00384         inline void wait(double v, sc_time_unit tu, const sc_event& e) \
00385             { rc_wait(v, tu, e); } \
00386         inline void wait(const sc_time& t, sc_event_or_list& el) \
00387             { rc_wait(t, el); } \
00388         inline void wait(double v, sc_time_unit t, sc_event_or_list& el) \
00389             { rc_wait(v, t, el); } \
00390         inline void wait(const sc_time& t, sc_event_and_list& el) \
00391             { rc_wait(t, el); } \
00392         inline void wait( \
00393             double v, sc_time_unit tu, sc_event_and_list& el) \
00394             { rc_wait(v, tu, el); } \
00395         template<class _rc_T_param> \
00396         inline rc_process_handle rc_spawn( \
00397             _rc_T_param object, const char* name_p=NULL, \
00398             rc_spawn_options* opt_p=NULL) \
00399         { \
00400             return this->_rc_process_support.rc_spawn( \
00401                 object, name_p, opt_p); \
00402         } \
00403         inline bool rc_is_reconfigurable() const \
00404         { \
00405             return this->_rc_process_support.has_reconfigurable_context(); \
00406         } \
00407         inline void rc_terminate() \
00408             { this->_rc_process_support.terminate(); } \
00409     public: \
00410         inline void dont_initialize() \
00411         { \
00412             this->_rc_process_support.dont_initialize(*this); \
00413             sc_module::dont_initialize(); \
00414         } \
00415         inline void reset_signal_is( \
00416             const sc_in<bool>& reset_port, bool active_level) \
00417         { \
00418             bool success = this->_rc_process_support.reset_signal_is( \
00419                 *this, reset_port, active_level); \
00420             if (!success) { \
00421                 sc_module::reset_signal_is(reset_port, active_level); \
00422             } \
00423         } \
00424         inline void reset_signal_is( \
00425             const sc_signal<bool>& reset_signal, bool active_level) \
00426         { \
00427             bool success = this->_rc_process_support.reset_signal_is( \
00428                 *this, reset_signal, active_level); \
00429             if (!success) { \
00430                 sc_module::reset_signal_is(reset_signal, active_level); \
00431             } \
00432         } \
00433         inline void reset_signal_is( \
00434             rc_reset_channel_if& reset_channel, bool active_level) \
00435         { \
00436             const sc_signal<bool>* reset_signal = \
00437                 this->_rc_process_support.reset_channel_is( \
00438                     *this, reset_channel, active_level); \
00439             if (reset_signal != NULL) { \
00440                 sc_module::reset_signal_is(*reset_signal, active_level); \
00441             } \
00442         } \
00443         inline void reset_is(rc_process_reset& process_reset) \
00444             { this->_rc_process_support.reset_is(*this, process_reset); } \
00445         inline void rc_set_sync_reset() \
00446             { this->_rc_process_support.set_sync_reset(*this, true); } \
00447         inline void rc_set_async_reset() \
00448             { this->_rc_process_support.set_sync_reset(*this, false); } \
00449         typedef user_module_name RC_CURRENT_USER_MODULE
00450 
00451 #define RC_RECONFIGURABLE_METHOD(func) \
00452     if (true) { \
00453         if (this->_rc_process_support.has_reconfigurable_context()) { \
00454             this->_rc_process_support.declare_process( \
00455                 *this, \
00456                 boost::bind( \
00457                     &RC_CURRENT_USER_MODULE::_rc_declare_method, this), \
00458                 boost::bind( \
00459                     &RC_CURRENT_USER_MODULE::func, this), \
00460                 this->sensitive); \
00461         } else { \
00462             SC_METHOD(func); \
00463         } \
00464     } else (void)0
00465 
00466 #define RC_RECONFIGURABLE_THREAD(func) \
00467     if (true) { \
00468         this->_rc_process_support.declare_process( \
00469             *this, \
00470             boost::bind( \
00471                 &RC_CURRENT_USER_MODULE::_rc_declare_thread, this), \
00472             boost::bind( \
00473                 &RC_CURRENT_USER_MODULE::func, this), \
00474             this->sensitive, true, false, false); \
00475     } else (void)0
00476 
00477 #define RC_RECONFIGURABLE_CTHREAD(func, edge) \
00478     if (true) { \
00479         this->_rc_process_support.declare_process( \
00480             *this, \
00481             boost::bind( \
00482                 &RC_CURRENT_USER_MODULE::_rc_declare_thread, this), \
00483             boost::bind( \
00484                 &RC_CURRENT_USER_MODULE::func, this), \
00485             this->sensitive, true, true, true); \
00486         this->sensitive << edge; \
00487     } else (void)0
00488 
00489 #define RC_NO_RECONFIGURABLE_PROCESS_RESET(pbc_name) \
00490     for(rc_process_behavior_change pbc_name = \
00491         this->_rc_process_support.disable_process_control(); \
00492         !pbc_name.is_released(); \
00493         pbc_name.release())
00494 
00495 #define RC_HAS_PROCESS(user_module_name) \
00496     RC_HAS_RECONFIGURABLE_PROCESS(user_module_name)
00497 
00498 #define RC_METHOD(func) \
00499     RC_RECONFIGURABLE_METHOD(func)
00500 
00501 #define RC_THREAD(func) \
00502     RC_RECONFIGURABLE_THREAD(func)
00503 
00504 #define RC_CTHREAD(func, edge) \
00505     RC_RECONFIGURABLE_CTHREAD(func, edge)
00506 
00507 #define RC_NO_RESET \
00508     RC_NO_RECONFIGURABLE_PROCESS_RESET(_rc_tmp_pbc)
00509 
00510 #define _RC_DECLARE_TRANSACTION \
00511     for(rc_transaction _rc_tmp_trans( \
00512         this->_rc_process_support.get_reconfigurable_context()); \
00513         !_rc_tmp_trans.has_ended(); \
00514         _rc_tmp_trans.end())
00515 
00516 #define RC_TRANSACTION _RC_DECLARE_TRANSACTION
00517 
00518 #endif // RC_PROCESS_SUPPORT_H_
00519 
00520 //
00521 // $Id: rc_process_support.h,v 1.11 2007/10/24 23:55:23 felke Exp $
00522 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/core/rc_process_support.h,v $
00523 //

Generated on Tue Jan 1 23:13:41 2008 for ReChannel by  doxygen 1.5.3