00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #if !defined(sc_process_h_INCLUDED)
00030 #define sc_process_h_INCLUDED
00031
00032 #include <cassert>
00033 #include "sysc/utils/sc_iostream.h"
00034 #include "sysc/kernel/sc_constants.h"
00035 #include "sysc/kernel/sc_object.h"
00036 #include "sysc/kernel/sc_kernel_ids.h"
00037 #include "sysc/communication/sc_export.h"
00038
00039 #include <list>
00040
00041 #ifndef SC_INCLUDE_WINDOWS_H // 02/20/2015 GL
00042 # define SC_INCLUDE_WINDOWS_H // include Windows.h, if needed
00043 #endif
00044 #include "sysc/kernel/sc_cmnhdr.h"
00045
00046 #if defined(WIN32) || defined(_WIN32)
00047
00048 #define CHNL_MTX_TYPE_ CRITICAL_SECTION
00049
00050 #define CHNL_MTX_INIT_( Mutex ) \
00051 InitializeCriticalSection( &(Mutex) )
00052 #define CHNL_MTX_LOCK_( Mutex ) \
00053 EnterCriticalSection( &(Mutex) )
00054 #define CHNL_MTX_UNLOCK_( Mutex ) \
00055 LeaveCriticalSection( &(Mutex) )
00056 #define CHNL_MTX_TRYLOCK_( Mutex ) \
00057 ( TryEnterCriticalSection( &(Mutex) ) != 0 )
00058 #define CHNL_MTX_DESTROY_( Mutex ) \
00059 DeleteCriticalSection( &(Mutex) )
00060
00061 #else // use pthread mutex
00062
00063 #include <pthread.h>
00064 #define CHNL_MTX_TYPE_ pthread_mutex_t
00065
00066 #if defined(__hpux)
00067 # define CHNL_PTHREAD_NULL_ cma_c_null
00068 #else // !defined(__hpux)
00069 # define CHNL_PTHREAD_NULL_ NULL
00070 #endif
00071
00072 #define CHNL_MTX_INIT_( Mutex ) \
00073 pthread_mutex_init( &(Mutex), CHNL_PTHREAD_NULL_ )
00074 #define CHNL_MTX_LOCK_( Mutex ) \
00075 pthread_mutex_lock( &(Mutex) )
00076 #define CHNL_MTX_UNLOCK_( Mutex ) \
00077 pthread_mutex_unlock( &(Mutex) )
00078
00079 #ifdef _XOPEN_SOURCE
00080 # define CHNL_MTX_TRYLOCK_( Mutex ) \
00081 ( pthread_mutex_trylock( &(Mutex) ) == 0 )
00082 #else // no try_lock available
00083 # define CHNL_MTX_TRYLOCK_( Mutex ) \
00084 ( false )
00085 #endif
00086
00087 #define CHNL_MTX_DESTROY_( Mutex ) \
00088 pthread_mutex_destroy( &(Mutex) )
00089
00090 #endif
00091
00092 #include "sysc/kernel/sc_time.h"
00093
00094
00095 #include "sysc/datatypes/int/sc_nbdefs.h"
00096
00097 namespace sc_core {
00098
00099
00100 class sc_process_handle;
00101 class sc_thread_process;
00102 class sc_reset;
00103
00104 const char* sc_gen_unique_name( const char*, bool preserve_first );
00105 sc_process_handle sc_get_current_process_handle();
00106 void sc_thread_cor_fn( void* arg );
00107 bool timed_out( sc_simcontext* );
00108
00109 extern bool sc_allow_process_control_corners;
00110
00111
00112
00113
00114 typedef class sc_cthread_process* sc_cthread_handle;
00115 typedef class sc_method_process* sc_method_handle;
00116 typedef class sc_thread_process* sc_thread_handle;
00117
00118
00119
00120
00121 enum sc_curr_proc_kind
00122 {
00123 SC_NO_PROC_,
00124 SC_METHOD_PROC_,
00125 SC_THREAD_PROC_,
00126 SC_CTHREAD_PROC_
00127 };
00128
00129
00130
00131 enum sc_descendant_inclusion_info {
00132 SC_NO_DESCENDANTS=0,
00133 SC_INCLUDE_DESCENDANTS,
00134 SC_INVALID_DESCENDANTS
00135 };
00136
00137
00144 class sc_process_host
00145 {
00146 public:
00147 sc_process_host() {}
00148 virtual ~sc_process_host() { }
00149 void defunct() {}
00150 };
00151
00152
00153
00163 class sc_process_monitor {
00164 public:
00165 enum {
00166 spm_exit = 0
00167 };
00168 virtual ~sc_process_monitor() {}
00169 virtual void signal(sc_thread_handle thread_p, int type);
00170 };
00171 inline void sc_process_monitor::signal(sc_thread_handle , int ) {}
00172
00173
00190 #if defined(_MSC_VER)
00191 #if ( _MSC_VER > 1200 )
00192 # define SC_USE_MEMBER_FUNC_PTR
00193 #endif
00194 #else
00195 # define SC_USE_MEMBER_FUNC_PTR
00196 #endif
00197
00198
00199
00200
00201 #if defined(SC_USE_MEMBER_FUNC_PTR)
00202
00203 typedef void (sc_process_host::*SC_ENTRY_FUNC)();
00204 # define SC_DECL_HELPER_STRUCT(callback_tag, func)
00205 # define SC_MAKE_FUNC_PTR(callback_tag, func) \
00206 static_cast<sc_core::SC_ENTRY_FUNC>(&callback_tag::func)
00207
00208
00209
00210
00211 #else // !defined(SC_USE_MEMBER_FUNC_PTR)
00212 class sc_process_call_base {
00213 public:
00214 inline sc_process_call_base()
00215 {
00216 }
00217
00218 virtual ~sc_process_call_base()
00219 {
00220 }
00221
00222 virtual void invoke(sc_process_host* host_p)
00223 {
00224 }
00225 };
00226 extern sc_process_call_base sc_process_defunct;
00227
00228 template<class T>
00229 class sc_process_call : public sc_process_call_base {
00230 public:
00231 sc_process_call( void (T::*method_p)() ) :
00232 sc_process_call_base()
00233 {
00234 m_method_p = method_p;
00235 }
00236
00237 virtual ~sc_process_call()
00238 {
00239 }
00240
00241 virtual void invoke(sc_process_host* host_p)
00242 {
00243 (((T*)host_p)->*m_method_p)();
00244 }
00245
00246 protected:
00247 void (T::*m_method_p)();
00248 };
00249
00250 typedef sc_process_call_base* SC_ENTRY_FUNC;
00251 # define SC_DECL_HELPER_STRUCT(callback_tag, func)
00252 # define SC_MAKE_FUNC_PTR(callback_tag, func) \
00253 (::sc_core::SC_ENTRY_FUNC) (new \
00254 ::sc_core::sc_process_call<callback_tag>(&callback_tag::func))
00255
00256 #endif // !defined(SC_USE_MEMBER_FUNC_PTR)
00257
00258
00259 extern void sc_set_stack_size( sc_thread_handle, std::size_t );
00260
00261
00262 extern void sc_set_stack_size( sc_method_handle, std::size_t );
00263
00264 class sc_event;
00265 class sc_event_list;
00266 class sc_name_gen;
00267 class sc_spawn_options;
00268 class sc_unwind_exception;
00269
00270
00292 class sc_throw_it_helper {
00293 public:
00294 virtual sc_throw_it_helper* clone() const = 0;
00295 virtual void throw_it() = 0;
00296 sc_throw_it_helper() {}
00297 virtual ~sc_throw_it_helper() {}
00298 };
00299
00300 template<typename EXCEPT>
00301 class sc_throw_it : public sc_throw_it_helper
00302 {
00303 typedef sc_throw_it<EXCEPT> this_type;
00304 public:
00305 sc_throw_it( const EXCEPT& value ) : m_value(value) { }
00306 virtual ~sc_throw_it() {}
00307 virtual inline this_type* clone() const { return new this_type(m_value); }
00308 virtual inline void throw_it() { throw m_value; }
00309 protected:
00310 EXCEPT m_value;
00311 };
00312
00313
00344
00348 struct sc_chnl_lock {
00352 CHNL_MTX_TYPE_ *lock_p;
00353
00357 unsigned int counter;
00358
00362 sc_chnl_lock( CHNL_MTX_TYPE_ *m ): lock_p( m ), counter( 1 ) {}
00363 };
00364
00365 class sc_acq_chnl_lock_queue {
00366 public:
00379 void lock_and_push( CHNL_MTX_TYPE_ *lock );
00380
00391 void pop_and_unlock( CHNL_MTX_TYPE_ *lock );
00392
00398 void lock_all( void );
00399
00405 void unlock_all( void );
00406
00407 private:
00411 std::list<sc_chnl_lock*> queue;
00412 };
00413
00414
00423
00424 class sc_timestamp
00425 {
00426 public:
00427
00431 typedef sc_dt::uint64 value_type;
00432
00433
00434
00435 sc_timestamp();
00436 sc_timestamp( sc_time, value_type );
00437 sc_timestamp( long long, int );
00438 sc_timestamp( const sc_timestamp& );
00439
00440
00441
00445 sc_timestamp& operator = ( const sc_timestamp& );
00446
00447
00448
00452 bool operator == ( const sc_timestamp& ) const;
00453
00457 bool operator != ( const sc_timestamp& ) const;
00458
00462 bool operator < ( const sc_timestamp& ) const;
00463
00467 bool operator <= ( const sc_timestamp& ) const;
00468
00472 bool operator > ( const sc_timestamp& ) const;
00473
00477 bool operator >= ( const sc_timestamp& ) const;
00478
00479
00480
00484 sc_timestamp operator + ( const sc_timestamp& );
00485
00486
00487
00491 const sc_time& get_time_count() const;
00492
00496 value_type get_delta_count() const;
00497
00501 bool get_infinite() const;
00502
00503 private:
00504
00508 sc_time m_time_count;
00509
00513 value_type m_delta_count;
00514
00518 bool m_infinite;
00519 };
00520
00521
00542 class sc_process_b : public sc_object {
00543 friend class sc_simcontext;
00544 friend class sc_cthread_process;
00545 friend class sc_method_process;
00546 friend class sc_process_handle;
00547 friend class sc_thread_process;
00548
00549 friend class sc_object;
00550 friend class sc_port_base;
00551 friend class sc_runnable;
00552 friend class sc_sensitive;
00553 friend class sc_sensitive_pos;
00554 friend class sc_sensitive_neg;
00555 friend class sc_module;
00556
00557
00558 friend class sc_channel;
00559
00560 friend class sc_report_handler;
00561 friend class sc_reset;
00562 friend class sc_reset_finder;
00563 friend class sc_unwind_exception;
00564
00565 friend const char* sc_gen_unique_name( const char*, bool preserve_first );
00566 friend sc_process_handle sc_get_current_process_handle();
00567 friend void sc_thread_cor_fn( void* arg );
00568 friend bool timed_out( sc_simcontext* );
00569
00570 public:
00571 enum process_throw_type {
00572 THROW_NONE = 0,
00573 THROW_KILL,
00574 THROW_USER,
00575 THROW_ASYNC_RESET,
00576 THROW_SYNC_RESET
00577 };
00578
00579 enum process_state {
00580 ps_bit_disabled = 1,
00581 ps_bit_ready_to_run = 2,
00582 ps_bit_suspended = 4,
00583 ps_bit_zombie = 8,
00584 ps_normal = 0
00585 };
00586
00587 enum reset_type {
00588 reset_asynchronous = 0,
00589 reset_synchronous_off,
00590 reset_synchronous_on
00591 };
00592
00593 enum trigger_t
00594 {
00595 STATIC,
00596 EVENT,
00597 OR_LIST,
00598 AND_LIST,
00599 TIMEOUT,
00600 EVENT_TIMEOUT,
00601 OR_LIST_TIMEOUT,
00602 AND_LIST_TIMEOUT
00603 };
00604
00605 public:
00606 sc_process_b( const char* name_p, bool is_thread, bool free_host,
00607 SC_ENTRY_FUNC method_p, sc_process_host* host_p,
00608 const sc_spawn_options* opt_p );
00609
00610 protected:
00611
00612 virtual ~sc_process_b();
00613
00614 public:
00615 inline int current_state() { return m_state; }
00616 bool dont_initialize() const { return m_dont_init; }
00617 virtual void dont_initialize( bool dont );
00618 std::string dump_state() const;
00619 const ::std::vector<sc_object*>& get_child_objects() const;
00620 inline sc_curr_proc_kind proc_kind() const;
00621 sc_event& reset_event();
00622 sc_event& terminated_event();
00623
00631
00632 void lock_and_push( CHNL_MTX_TYPE_ *lock );
00633
00640
00641 void pop_and_unlock( CHNL_MTX_TYPE_ *lock );
00642
00649
00650 void lock_all_channels( void );
00651
00658
00659 void unlock_all_channels( void );
00660
00664
00665 int get_segment_id();
00666
00670
00671 void set_segment_id( int id );
00672
00676
00677 const sc_timestamp& get_timestamp();
00678
00682
00683 void set_timestamp( const sc_timestamp& ts );
00684
00688
00689 int get_instance_id();
00690
00694 void set_instance_id( int id );
00695
00696 public:
00697 static inline sc_process_handle last_created_process_handle();
00698
00699 protected:
00700 virtual void add_child_object( sc_object* );
00701 void add_static_event( const sc_event& );
00702 bool dynamic() const { return m_dynamic_proc; }
00703 const char* gen_unique_name( const char* basename_, bool preserve_first );
00704 inline sc_report* get_last_report() { return m_last_report_p; }
00705 inline bool is_disabled() const;
00706 inline bool is_runnable() const;
00707 static inline sc_process_b* last_created_process_base();
00708 virtual bool remove_child_object( sc_object* );
00709 void remove_dynamic_events( bool skip_timeout = false );
00710 void remove_static_events();
00711 inline void set_last_report( sc_report* last_p )
00712 {
00713 delete m_last_report_p;
00714 m_last_report_p = last_p;
00715 }
00716 inline bool timed_out() const;
00717 void report_error( const char* msgid, const char* msg = "" ) const;
00718 void report_immediate_self_notification() const;
00719
00720 protected:
00721 virtual void disable_process(
00722 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00723 void disconnect_process();
00724 virtual void enable_process(
00725 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00726 inline void initially_in_reset( bool async );
00727 inline bool is_unwinding() const;
00728 inline bool start_unwinding();
00729 inline bool clear_unwinding();
00730 virtual void kill_process(
00731 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00732 void reset_changed( bool async, bool asserted );
00733 void reset_process( reset_type rt,
00734 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
00735 virtual void resume_process(
00736 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00737 virtual void suspend_process(
00738 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00739 virtual void throw_user( const sc_throw_it_helper& helper,
00740 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00741 virtual void throw_reset( bool async ) = 0;
00742 virtual bool terminated() const;
00743 void trigger_reset_event();
00744
00745 private:
00746 void delete_process();
00747 inline void reference_decrement();
00748 inline void reference_increment();
00749
00750 protected:
00751 inline void semantics();
00752
00753
00754
00755 public:
00756 const char* file;
00757 int lineno;
00758 int proc_id;
00759
00760 protected:
00761 int m_active_areset_n;
00762 int m_active_reset_n;
00763 bool m_dont_init;
00764 bool m_dynamic_proc;
00765 const sc_event* m_event_p;
00766 int m_event_count;
00767 const sc_event_list* m_event_list_p;
00768 sc_process_b* m_exist_p;
00769 bool m_free_host;
00770 bool m_has_reset_signal;
00771 bool m_has_stack;
00772 bool m_is_thread;
00773 sc_report* m_last_report_p;
00774 sc_name_gen* m_name_gen_p;
00775 sc_curr_proc_kind m_process_kind;
00776 int m_references_n;
00777 std::vector<sc_reset*> m_resets;
00778 sc_event* m_reset_event_p;
00779 sc_event* m_resume_event_p;
00780 sc_process_b* m_runnable_p;
00781 sc_process_host* m_semantics_host_p;
00782 SC_ENTRY_FUNC m_semantics_method_p;
00783 int m_state;
00784 std::vector<const sc_event*> m_static_events;
00785 bool m_sticky_reset;
00786 sc_event* m_term_event_p;
00787 sc_throw_it_helper* m_throw_helper_p;
00788 process_throw_type m_throw_status;
00789 bool m_timed_out;
00790 sc_event* m_timeout_event_p;
00791 trigger_t m_trigger_type;
00792 bool m_unwinding;
00793
00797
00798 sc_acq_chnl_lock_queue m_acq_chnl_lock_queue;
00799
00803
00804 int m_segment_id;
00805
00809
00810 sc_timestamp m_timestamp;
00811
00815
00816 int m_instance_id;
00817
00818 protected:
00819 static sc_process_b* m_last_created_process_p;
00820 };
00821
00822 typedef sc_process_b sc_process_b;
00823
00824
00825
00826
00827
00828
00829
00830 inline void
00831 sc_process_b::add_child_object( sc_object* object_p )
00832 {
00833 sc_object::add_child_object( object_p );
00834 reference_increment();
00835 }
00836
00837 inline bool
00838 sc_process_b::remove_child_object( sc_object* object_p )
00839 {
00840 if ( sc_object::remove_child_object( object_p ) ) {
00841 reference_decrement();
00842 return true;
00843 }
00844 else
00845 {
00846 return false;
00847 }
00848 }
00849
00850 inline const ::std::vector<sc_object*>&
00851 sc_process_b::get_child_objects() const
00852 {
00853 return m_child_objects;
00854 }
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866 inline void sc_process_b::initially_in_reset( bool async )
00867 {
00868 if ( async )
00869 m_active_areset_n++;
00870 else
00871 m_active_reset_n++;
00872 }
00873
00874
00875
00876
00877
00878
00879 inline bool sc_process_b::is_disabled() const
00880 {
00881 return (m_state & ps_bit_disabled) ? true : false;
00882 }
00883
00884
00885
00886
00887
00888
00889
00890 inline bool sc_process_b::is_runnable() const
00891 {
00892 return m_runnable_p != 0;
00893 }
00894
00895
00896
00897
00898
00899
00900 inline bool sc_process_b::is_unwinding() const
00901 {
00902 return m_unwinding;
00903 }
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 inline bool sc_process_b::start_unwinding()
00914 {
00915 if ( !m_unwinding )
00916 {
00917 switch( m_throw_status )
00918 {
00919 case THROW_KILL:
00920 case THROW_ASYNC_RESET:
00921 case THROW_SYNC_RESET:
00922 m_unwinding = true;
00923 return true;
00924 case THROW_USER:
00925 default:
00926 break;
00927 }
00928 }
00929 return false;
00930 }
00931
00932
00933
00934
00935
00936
00937
00938 inline bool sc_process_b::clear_unwinding()
00939 {
00940 m_unwinding = false;
00941 return true;
00942 }
00943
00944
00945
00946
00947
00948
00949
00950
00951 inline sc_process_b* sc_process_b::last_created_process_base()
00952 {
00953 return m_last_created_process_p;
00954 }
00955
00956
00957
00958
00959
00960
00961
00962
00963 inline sc_curr_proc_kind sc_process_b::proc_kind() const
00964 {
00965 return m_process_kind;
00966 }
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976 inline void sc_process_b::reference_decrement()
00977 {
00978 m_references_n--;
00979 if ( m_references_n == 0 ) delete_process();
00980 }
00981
00982
00983
00984
00985
00986
00987
00988
00989 inline void sc_process_b::reference_increment()
00990 {
00991 assert(m_references_n != 0);
00992 m_references_n++;
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006 struct scoped_flag
01007 {
01008 scoped_flag( bool& b ) : ref(b){ ref = true; }
01009 ~scoped_flag() { ref = false; }
01010 bool& ref;
01011 };
01012 inline void sc_process_b::semantics()
01013 {
01014
01015
01016
01017 scoped_flag scoped_stack_flag( m_has_stack );
01018
01019 assert( m_process_kind != SC_NO_PROC_ );
01020
01021
01022
01023
01024
01025
01026 if ( m_reset_event_p &&
01027 ( (m_throw_status == THROW_SYNC_RESET) ||
01028 (m_throw_status == THROW_ASYNC_RESET) )
01029 ) {
01030 trigger_reset_event();
01031 }
01032
01033
01034
01035 m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET :
01036 ( m_active_reset_n ? THROW_SYNC_RESET : THROW_NONE);
01037
01038
01039
01040 # ifndef SC_USE_MEMBER_FUNC_PTR
01041 m_semantics_method_p->invoke( m_semantics_host_p );
01042 # else
01043 (m_semantics_host_p->*m_semantics_method_p)();
01044 # endif
01045 }
01046
01047
01048
01049
01050
01051
01052
01053 inline bool sc_process_b::terminated() const
01054 {
01055 return (m_state & ps_bit_zombie) != 0;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064 inline bool sc_process_b::timed_out() const
01065 {
01066 return m_timed_out;
01067 }
01068
01069
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261 #endif // !defined(sc_process_h_INCLUDED)