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 #ifndef _SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR
00098 #define _SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR "SYSC_PRINT_VERBOSE_MESSAGE"
00099 #endif
00100 namespace sc_core {
00101
00102
00103 class sc_process_handle;
00104 class sc_thread_process;
00105 class sc_reset;
00106
00107 const char* sc_gen_unique_name( const char*, bool preserve_first );
00108 sc_process_handle sc_get_current_process_handle();
00109 void sc_thread_cor_fn( void* arg );
00110 bool timed_out( sc_simcontext* );
00111
00112 extern bool sc_allow_process_control_corners;
00113
00114
00115
00116
00117 typedef class sc_cthread_process* sc_cthread_handle;
00118 typedef class sc_method_process* sc_method_handle;
00119 typedef class sc_thread_process* sc_thread_handle;
00120
00121
00122
00123
00124 enum sc_curr_proc_kind
00125 {
00126 SC_NO_PROC_,
00127 SC_METHOD_PROC_,
00128 SC_THREAD_PROC_,
00129 SC_CTHREAD_PROC_
00130 };
00131
00132
00133
00134 enum sc_descendant_inclusion_info {
00135 SC_NO_DESCENDANTS=0,
00136 SC_INCLUDE_DESCENDANTS,
00137 SC_INVALID_DESCENDANTS
00138 };
00139
00140
00147 class sc_process_host
00148 {
00149 public:
00150 sc_process_host() {}
00151 virtual ~sc_process_host() { }
00152 void defunct() {}
00153 };
00154
00155
00156
00166 class sc_process_monitor {
00167 public:
00168 enum {
00169 spm_exit = 0
00170 };
00171 virtual ~sc_process_monitor() {}
00172 virtual void signal(sc_thread_handle thread_p, int type);
00173 };
00174 inline void sc_process_monitor::signal(sc_thread_handle , int ) {}
00175
00176
00193 #if defined(_MSC_VER)
00194 #if ( _MSC_VER > 1200 )
00195 # define SC_USE_MEMBER_FUNC_PTR
00196 #endif
00197 #else
00198 # define SC_USE_MEMBER_FUNC_PTR
00199 #endif
00200
00201
00202
00203
00204 #if defined(SC_USE_MEMBER_FUNC_PTR)
00205
00206 typedef void (sc_process_host::*SC_ENTRY_FUNC)();
00207 # define SC_DECL_HELPER_STRUCT(callback_tag, func)
00208 # define SC_MAKE_FUNC_PTR(callback_tag, func) \
00209 static_cast<sc_core::SC_ENTRY_FUNC>(&callback_tag::func)
00210
00211
00212
00213
00214 #else // !defined(SC_USE_MEMBER_FUNC_PTR)
00215 class sc_process_call_base {
00216 public:
00217 inline sc_process_call_base()
00218 {
00219 }
00220
00221 virtual ~sc_process_call_base()
00222 {
00223 }
00224
00225 virtual void invoke(sc_process_host* host_p)
00226 {
00227 }
00228 };
00229 extern sc_process_call_base sc_process_defunct;
00230
00231 template<class T>
00232 class sc_process_call : public sc_process_call_base {
00233 public:
00234 sc_process_call( void (T::*method_p)() ) :
00235 sc_process_call_base()
00236 {
00237 m_method_p = method_p;
00238 }
00239
00240 virtual ~sc_process_call()
00241 {
00242 }
00243
00244 virtual void invoke(sc_process_host* host_p)
00245 {
00246 (((T*)host_p)->*m_method_p)();
00247 }
00248
00249 protected:
00250 void (T::*m_method_p)();
00251 };
00252
00253 typedef sc_process_call_base* SC_ENTRY_FUNC;
00254 # define SC_DECL_HELPER_STRUCT(callback_tag, func)
00255 # define SC_MAKE_FUNC_PTR(callback_tag, func) \
00256 (::sc_core::SC_ENTRY_FUNC) (new \
00257 ::sc_core::sc_process_call<callback_tag>(&callback_tag::func))
00258
00259 #endif // !defined(SC_USE_MEMBER_FUNC_PTR)
00260
00261
00262 extern void sc_set_stack_size( sc_thread_handle, std::size_t );
00263
00264
00265 extern void sc_set_stack_size( sc_method_handle, std::size_t );
00266
00267 class sc_event;
00268 class sc_event_list;
00269 class sc_name_gen;
00270 class sc_spawn_options;
00271 class sc_unwind_exception;
00272
00273
00295 class sc_throw_it_helper {
00296 public:
00297 virtual sc_throw_it_helper* clone() const = 0;
00298 virtual void throw_it() = 0;
00299 sc_throw_it_helper() {}
00300 virtual ~sc_throw_it_helper() {}
00301 };
00302
00303 template<typename EXCEPT>
00304 class sc_throw_it : public sc_throw_it_helper
00305 {
00306 typedef sc_throw_it<EXCEPT> this_type;
00307 public:
00308 sc_throw_it( const EXCEPT& value ) : m_value(value) { }
00309 virtual ~sc_throw_it() {}
00310 virtual inline this_type* clone() const { return new this_type(m_value); }
00311 virtual inline void throw_it() { throw m_value; }
00312 protected:
00313 EXCEPT m_value;
00314 };
00315
00316
00347
00351 struct sc_chnl_lock {
00355 CHNL_MTX_TYPE_ *lock_p;
00356
00360 unsigned int counter;
00361
00365 sc_chnl_lock( CHNL_MTX_TYPE_ *m ): lock_p( m ), counter( 1 ) {}
00366 };
00367
00368 class sc_acq_chnl_lock_queue {
00369 public:
00382 void lock_and_push( CHNL_MTX_TYPE_ *lock );
00383
00394 void pop_and_unlock( CHNL_MTX_TYPE_ *lock );
00395
00401 void lock_all( void );
00402
00408 void unlock_all( void );
00409
00410 private:
00414 std::list<sc_chnl_lock*> queue;
00415 };
00416
00417
00426
00427 class sc_timestamp
00428 {
00429 public:
00430
00434 typedef sc_dt::uint64 value_type;
00435
00436
00437
00438 sc_timestamp();
00439 sc_timestamp( sc_time, value_type );
00440 sc_timestamp( long long, int );
00441 sc_timestamp( const sc_timestamp& );
00442
00443
00444
00448 sc_timestamp& operator = ( const sc_timestamp& );
00449
00450
00451
00455 bool operator == ( const sc_timestamp& ) const;
00456
00460 bool operator != ( const sc_timestamp& ) const;
00461
00465 bool operator < ( const sc_timestamp& ) const;
00466
00470 bool operator <= ( const sc_timestamp& ) const;
00471
00475 bool operator > ( const sc_timestamp& ) const;
00476
00480 bool operator >= ( const sc_timestamp& ) const;
00481
00482
00483
00487 sc_timestamp operator + ( const sc_timestamp& );
00488
00489
00490
00494 const sc_time& get_time_count() const;
00495
00499 value_type get_delta_count() const;
00500
00504 bool get_infinite() const;
00505
00506 private:
00507
00511 sc_time m_time_count;
00512
00516 value_type m_delta_count;
00517
00521 bool m_infinite;
00522 };
00523
00524
00545 class sc_process_b : public sc_object {
00546 friend class sc_simcontext;
00547 friend class sc_cthread_process;
00548 friend class sc_method_process;
00549 friend class sc_process_handle;
00550 friend class sc_thread_process;
00551
00552 friend class sc_object;
00553 friend class sc_port_base;
00554 friend class sc_runnable;
00555 friend class sc_sensitive;
00556 friend class sc_sensitive_pos;
00557 friend class sc_sensitive_neg;
00558 friend class sc_module;
00559
00560
00561 friend class sc_channel;
00562
00563 friend class sc_report_handler;
00564 friend class sc_reset;
00565 friend class sc_reset_finder;
00566 friend class sc_unwind_exception;
00567
00568 friend const char* sc_gen_unique_name( const char*, bool preserve_first );
00569 friend sc_process_handle sc_get_current_process_handle();
00570 friend void sc_thread_cor_fn( void* arg );
00571 friend bool timed_out( sc_simcontext* );
00572
00573
00574
00575
00576 public:
00577
00582 void set_upcoming_segment_ids(int *segment_ids)
00583 {
00584 this->segment_ids = segment_ids;
00585 }
00586
00591 int* get_upcoming_segment_ids()
00592 {
00593 return segment_ids;
00594 }
00595
00600 int *segment_ids;
00601
00602 enum process_throw_type {
00603 THROW_NONE = 0,
00604 THROW_KILL,
00605 THROW_USER,
00606 THROW_ASYNC_RESET,
00607 THROW_SYNC_RESET
00608 };
00609
00610 enum process_state {
00611 ps_bit_disabled = 1,
00612 ps_bit_ready_to_run = 2,
00613 ps_bit_suspended = 4,
00614 ps_bit_zombie = 8,
00615 ps_normal = 0
00616 };
00617
00618 enum reset_type {
00619 reset_asynchronous = 0,
00620 reset_synchronous_off,
00621 reset_synchronous_on
00622 };
00623
00624 enum trigger_t
00625 {
00626 STATIC,
00627 EVENT,
00628 OR_LIST,
00629 AND_LIST,
00630 TIMEOUT,
00631 EVENT_TIMEOUT,
00632 OR_LIST_TIMEOUT,
00633 AND_LIST_TIMEOUT
00634 };
00635
00636 public:
00637 sc_process_b( const char* name_p, bool is_thread, bool free_host,
00638 SC_ENTRY_FUNC method_p, sc_process_host* host_p,
00639 const sc_spawn_options* opt_p );
00640
00641 protected:
00642
00643 virtual ~sc_process_b();
00644
00645 public:
00646 inline int current_state() { return m_state; }
00647 bool dont_initialize() const { return m_dont_init; }
00648 virtual void dont_initialize( bool dont );
00649 std::string dump_state() const;
00650 const ::std::vector<sc_object*>& get_child_objects() const;
00651 inline sc_curr_proc_kind proc_kind() const;
00652 sc_event& reset_event();
00653 sc_event& terminated_event();
00654
00662
00663 void lock_and_push( CHNL_MTX_TYPE_ *lock );
00664
00671
00672 void pop_and_unlock( CHNL_MTX_TYPE_ *lock );
00673
00680
00681 void lock_all_channels( void );
00682
00689
00690 void unlock_all_channels( void );
00691
00695
00696 int get_segment_id();
00697
00701
00702 void set_segment_id( int id );
00703
00707
00708 const sc_timestamp& get_timestamp();
00709
00713
00714 void set_timestamp( const sc_timestamp& ts );
00715
00719
00720 int get_instance_id();
00721
00725 void set_instance_id( int id );
00726
00727 public:
00728 static inline sc_process_handle last_created_process_handle();
00729
00730 protected:
00731 virtual void add_child_object( sc_object* );
00732 void add_static_event( const sc_event& );
00733 bool dynamic() const { return m_dynamic_proc; }
00734 const char* gen_unique_name( const char* basename_, bool preserve_first );
00735 inline sc_report* get_last_report() { return m_last_report_p; }
00736 inline bool is_disabled() const;
00737 inline bool is_runnable() const;
00738 static inline sc_process_b* last_created_process_base();
00739 virtual bool remove_child_object( sc_object* );
00740 void remove_dynamic_events( bool skip_timeout = false );
00741 void remove_static_events();
00742 inline void set_last_report( sc_report* last_p )
00743 {
00744 delete m_last_report_p;
00745 m_last_report_p = last_p;
00746 }
00747 inline bool timed_out() const;
00748 void report_error( const char* msgid, const char* msg = "" ) const;
00749 void report_immediate_self_notification() const;
00750
00751 protected:
00752 virtual void disable_process(
00753 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00754 void disconnect_process();
00755 virtual void enable_process(
00756 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00757 inline void initially_in_reset( bool async );
00758 inline bool is_unwinding() const;
00759 inline bool start_unwinding();
00760 inline bool clear_unwinding();
00761 virtual void kill_process(
00762 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00763 void reset_changed( bool async, bool asserted );
00764 void reset_process( reset_type rt,
00765 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
00766 virtual void resume_process(
00767 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00768 virtual void suspend_process(
00769 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00770 virtual void throw_user( const sc_throw_it_helper& helper,
00771 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00772 virtual void throw_reset( bool async ) = 0;
00773 virtual bool terminated() const;
00774 void trigger_reset_event();
00775
00776 private:
00777 void delete_process();
00778 inline void reference_decrement();
00779 inline void reference_increment();
00780
00781 protected:
00782 inline void semantics();
00783
00784
00785
00786 public:
00787 const char* file;
00788 int lineno;
00789 int proc_id;
00793
00794
00795 int m_process_state;
00796 protected:
00797 int m_active_areset_n;
00798 int m_active_reset_n;
00799 bool m_dont_init;
00800 bool m_dynamic_proc;
00801 const sc_event* m_event_p;
00802
00803 int m_event_count;
00804 const sc_event_list* m_event_list_p;
00805 sc_process_b* m_exist_p;
00806 bool m_free_host;
00807 bool m_has_reset_signal;
00808 bool m_has_stack;
00809 bool m_is_thread;
00810 sc_report* m_last_report_p;
00811 sc_name_gen* m_name_gen_p;
00812 sc_curr_proc_kind m_process_kind;
00813 int m_references_n;
00814 std::vector<sc_reset*> m_resets;
00815 sc_event* m_reset_event_p;
00816 sc_event* m_resume_event_p;
00817 sc_process_b* m_runnable_p;
00818 sc_process_host* m_semantics_host_p;
00819 SC_ENTRY_FUNC m_semantics_method_p;
00820 int m_state;
00821 std::vector<const sc_event*> m_static_events;
00822 bool m_sticky_reset;
00823 sc_event* m_term_event_p;
00824 sc_throw_it_helper* m_throw_helper_p;
00825 process_throw_type m_throw_status;
00826 bool m_timed_out;
00827 sc_event* m_timeout_event_p;
00828 trigger_t m_trigger_type;
00829 bool m_unwinding;
00830
00834
00835 sc_acq_chnl_lock_queue m_acq_chnl_lock_queue;
00836
00840
00841 int m_segment_id;
00842
00846
00847 sc_timestamp m_timestamp;
00848
00852
00853 int m_instance_id;
00854
00855
00856
00857
00858 protected:
00859 static sc_process_b* m_last_created_process_p;
00860 };
00861
00862 typedef sc_process_b sc_process_b;
00863
00864
00865
00866
00867
00868
00869
00870 inline void
00871 sc_process_b::add_child_object( sc_object* object_p )
00872 {
00873 sc_object::add_child_object( object_p );
00874 reference_increment();
00875 }
00876
00877
00878
00879 inline bool
00880 sc_process_b::remove_child_object( sc_object* object_p )
00881 {
00882 if ( sc_object::remove_child_object( object_p ) ) {
00883 reference_decrement();
00884 return true;
00885 }
00886 else
00887 {
00888 return false;
00889 }
00890 }
00891
00892 inline const ::std::vector<sc_object*>&
00893 sc_process_b::get_child_objects() const
00894 {
00895 return m_child_objects;
00896 }
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 inline void sc_process_b::initially_in_reset( bool async )
00909 {
00910 if ( async )
00911 m_active_areset_n++;
00912 else
00913 m_active_reset_n++;
00914 }
00915
00916
00917
00918
00919
00920
00921 inline bool sc_process_b::is_disabled() const
00922 {
00923 return (m_state & ps_bit_disabled) ? true : false;
00924 }
00925
00926
00927
00928
00929
00930
00931
00932 inline bool sc_process_b::is_runnable() const
00933 {
00934 return m_runnable_p != 0;
00935 }
00936
00937
00938
00939
00940
00941
00942 inline bool sc_process_b::is_unwinding() const
00943 {
00944 return m_unwinding;
00945 }
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955 inline bool sc_process_b::start_unwinding()
00956 {
00957 if ( !m_unwinding )
00958 {
00959 switch( m_throw_status )
00960 {
00961 case THROW_KILL:
00962 case THROW_ASYNC_RESET:
00963 case THROW_SYNC_RESET:
00964 m_unwinding = true;
00965 return true;
00966 case THROW_USER:
00967 default:
00968 break;
00969 }
00970 }
00971 return false;
00972 }
00973
00974
00975
00976
00977
00978
00979
00980 inline bool sc_process_b::clear_unwinding()
00981 {
00982 m_unwinding = false;
00983 return true;
00984 }
00985
00986
00987
00988
00989
00990
00991
00992
00993 inline sc_process_b* sc_process_b::last_created_process_base()
00994 {
00995 return m_last_created_process_p;
00996 }
00997
00998
00999
01000
01001
01002
01003
01004
01005 inline sc_curr_proc_kind sc_process_b::proc_kind() const
01006 {
01007 return m_process_kind;
01008 }
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018 inline void sc_process_b::reference_decrement()
01019 {
01020 m_references_n--;
01021 if ( m_references_n == 0 ) delete_process();
01022 }
01023
01024
01025
01026
01027
01028
01029
01030
01031 inline void sc_process_b::reference_increment()
01032 {
01033 assert(m_references_n != 0);
01034 m_references_n++;
01035 }
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048 struct scoped_flag
01049 {
01050 scoped_flag( bool& b ) : ref(b){ ref = true; }
01051 ~scoped_flag() { ref = false; }
01052 bool& ref;
01053 };
01054 inline void sc_process_b::semantics()
01055 {
01056
01057
01058
01059 scoped_flag scoped_stack_flag( m_has_stack );
01060
01061 assert( m_process_kind != SC_NO_PROC_ );
01062
01063
01064
01065
01066
01067
01068 if ( m_reset_event_p &&
01069 ( (m_throw_status == THROW_SYNC_RESET) ||
01070 (m_throw_status == THROW_ASYNC_RESET) )
01071 ) {
01072 trigger_reset_event();
01073 }
01074
01075
01076
01077 m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET :
01078 ( m_active_reset_n ? THROW_SYNC_RESET : THROW_NONE);
01079
01080
01081
01082 # ifndef SC_USE_MEMBER_FUNC_PTR
01083 m_semantics_method_p->invoke( m_semantics_host_p );
01084 # else
01085 (m_semantics_host_p->*m_semantics_method_p)();
01086 # endif
01087 }
01088
01089
01090
01091
01092
01093
01094
01095 inline bool sc_process_b::terminated() const
01096 {
01097 return (m_state & ps_bit_zombie) != 0;
01098 }
01099
01100
01101
01102
01103
01104
01105
01106 inline bool sc_process_b::timed_out() const
01107 {
01108 return m_timed_out;
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
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303 #endif // !defined(sc_process_h_INCLUDED)