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 #include <set>
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_event_or_list;
00270 class sc_name_gen;
00271 class sc_spawn_options;
00272 class sc_unwind_exception;
00273
00274
00296 class sc_throw_it_helper {
00297 public:
00298 virtual sc_throw_it_helper* clone() const = 0;
00299 virtual void throw_it() = 0;
00300 sc_throw_it_helper() {}
00301 virtual ~sc_throw_it_helper() {}
00302 };
00303
00304 template<typename EXCEPT>
00305 class sc_throw_it : public sc_throw_it_helper
00306 {
00307 typedef sc_throw_it<EXCEPT> this_type;
00308 public:
00309 sc_throw_it( const EXCEPT& value ) : m_value(value) { }
00310 virtual ~sc_throw_it() {}
00311 virtual inline this_type* clone() const { return new this_type(m_value); }
00312 virtual inline void throw_it() { throw m_value; }
00313 protected:
00314 EXCEPT m_value;
00315 };
00316
00317
00348
00352 struct sc_chnl_lock {
00356 CHNL_MTX_TYPE_ *lock_p;
00357
00361 unsigned int counter;
00362
00366 sc_chnl_lock( CHNL_MTX_TYPE_ *m ): lock_p( m ), counter( 1 ) {}
00367 };
00368
00369 class sc_acq_chnl_lock_queue {
00370 public:
00383 void lock_and_push( CHNL_MTX_TYPE_ *lock );
00384
00395 void pop_and_unlock( CHNL_MTX_TYPE_ *lock );
00396
00402 void lock_all( void );
00403
00409 void unlock_all( void );
00410
00411 private:
00415 std::list<sc_chnl_lock*> queue;
00416 };
00417
00418
00427
00428 class sc_timestamp
00429 {
00430 public:
00431
00435 typedef sc_dt::uint64 value_type;
00436
00437
00438
00439 sc_timestamp();
00440 sc_timestamp( sc_time, value_type );
00441 sc_timestamp( long long, int );
00442 sc_timestamp( const sc_timestamp& );
00443
00444
00445
00449 sc_timestamp& operator = ( const sc_timestamp& );
00450
00451
00452
00456 bool operator == ( const sc_timestamp& ) const;
00457
00461 bool operator != ( const sc_timestamp& ) const;
00462
00466 bool operator < ( const sc_timestamp& ) const;
00467
00471 bool operator <= ( const sc_timestamp& ) const;
00472
00476 bool operator > ( const sc_timestamp& ) const;
00477
00481 bool operator >= ( const sc_timestamp& ) const;
00482
00483
00484
00488 sc_timestamp operator + ( const sc_timestamp& );
00489
00490
00491
00495 const sc_time& get_time_count() const;
00496
00500 value_type get_delta_count() const;
00501
00505 bool get_infinite() const;
00506
00507 void show() const;
00508
00512 sc_time m_time_count;
00513
00517 value_type m_delta_count;
00518
00519 private:
00520
00521
00522
00526 bool m_infinite;
00527 };
00528
00529
00550 class sc_process_b : public sc_object {
00551 friend class sc_simcontext;
00552 friend class sc_cthread_process;
00553 friend class sc_method_process;
00554 friend class sc_process_handle;
00555 friend class sc_thread_process;
00556
00557 friend class sc_object;
00558 friend class sc_port_base;
00559 friend class sc_runnable;
00560 friend class sc_sensitive;
00561 friend class sc_sensitive_pos;
00562 friend class sc_sensitive_neg;
00563 friend class sc_module;
00564
00565
00566 friend class sc_channel;
00567
00568 friend class sc_report_handler;
00569 friend class sc_reset;
00570 friend class sc_reset_finder;
00571 friend class sc_unwind_exception;
00572
00573 friend const char* sc_gen_unique_name( const char*, bool preserve_first );
00574 friend sc_process_handle sc_get_current_process_handle();
00575 friend void sc_thread_cor_fn( void* arg );
00576 friend bool timed_out( sc_simcontext* );
00577
00578
00579
00580
00581 public:
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 bool event_list_member_triggered;
00596
00597
00598
00599
00600
00601
00602
00603 sc_timestamp wake_up_time_for_event_list;
00604
00605
00606
00607
00612 void set_upcoming_segment_ids(int *segment_ids)
00613 {
00614 this->segment_ids = segment_ids;
00615 }
00616
00621 int* get_upcoming_segment_ids()
00622 {
00623 return segment_ids;
00624 }
00625
00630 int *segment_ids;
00631
00632 enum process_throw_type {
00633 THROW_NONE = 0,
00634 THROW_KILL,
00635 THROW_USER,
00636 THROW_ASYNC_RESET,
00637 THROW_SYNC_RESET
00638 };
00639
00640 enum process_state {
00641 ps_bit_disabled = 1,
00642 ps_bit_ready_to_run = 2,
00643 ps_bit_suspended = 4,
00644 ps_bit_zombie = 8,
00645 ps_normal = 0
00646 };
00647
00648 enum reset_type {
00649 reset_asynchronous = 0,
00650 reset_synchronous_off,
00651 reset_synchronous_on
00652 };
00653
00654 enum trigger_t
00655 {
00656 STATIC,
00657 EVENT,
00658 OR_LIST,
00659 AND_LIST,
00660 TIMEOUT,
00661 EVENT_TIMEOUT,
00662 OR_LIST_TIMEOUT,
00663 AND_LIST_TIMEOUT
00664 };
00665
00666 public:
00667 sc_process_b( const char* name_p, bool is_thread, bool free_host,
00668 SC_ENTRY_FUNC method_p, sc_process_host* host_p,
00669 const sc_spawn_options* opt_p );
00670
00671 protected:
00672
00673 virtual ~sc_process_b();
00674
00675 public:
00676 inline int current_state() { return m_state; }
00677 bool dont_initialize() const { return m_dont_init; }
00678 virtual void dont_initialize( bool dont );
00679 std::string dump_state() const;
00680 const ::std::vector<sc_object*>& get_child_objects() const;
00681 inline sc_curr_proc_kind proc_kind() const;
00682 sc_event& reset_event();
00683 sc_event& terminated_event();
00684
00692
00693 void lock_and_push( CHNL_MTX_TYPE_ *lock );
00694
00701
00702 void pop_and_unlock( CHNL_MTX_TYPE_ *lock );
00703
00710
00711 void lock_all_channels( void );
00712
00719
00720 void unlock_all_channels( void );
00721
00725
00726 int get_segment_id();
00727
00731
00732 void set_segment_id( int id );
00733
00737
00738 const sc_timestamp& get_timestamp();
00739
00743
00744 void set_timestamp( const sc_timestamp& ts );
00745
00749
00750 int get_instance_id();
00751
00755 void set_instance_id( int id );
00756
00757 public:
00758 static inline sc_process_handle last_created_process_handle();
00759 void add_sensitivity_event(const sc_event& e);
00760 protected:
00761 virtual void add_child_object( sc_object* );
00762 void add_static_event( const sc_event& );
00763 bool dynamic() const { return m_dynamic_proc; }
00764 const char* gen_unique_name( const char* basename_, bool preserve_first );
00765 inline sc_report* get_last_report() { return m_last_report_p; }
00766 inline bool is_disabled() const;
00767 inline bool is_runnable() const;
00768 static inline sc_process_b* last_created_process_base();
00769 virtual bool remove_child_object( sc_object* );
00770 void remove_dynamic_events( bool skip_timeout = false );
00771 void remove_static_events();
00772 inline void set_last_report( sc_report* last_p )
00773 {
00774 delete m_last_report_p;
00775 m_last_report_p = last_p;
00776 }
00777 inline bool timed_out() const;
00778 void report_error( const char* msgid, const char* msg = "" ) const;
00779 void report_immediate_self_notification() const;
00780
00781 protected:
00782 virtual void disable_process(
00783 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00784 void disconnect_process();
00785 virtual void enable_process(
00786 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00787 inline void initially_in_reset( bool async );
00788 inline bool is_unwinding() const;
00789 inline bool start_unwinding();
00790 inline bool clear_unwinding();
00791 virtual void kill_process(
00792 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00793 void reset_changed( bool async, bool asserted );
00794 void reset_process( reset_type rt,
00795 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
00796 virtual void resume_process(
00797 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00798 virtual void suspend_process(
00799 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00800 virtual void throw_user( const sc_throw_it_helper& helper,
00801 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0;
00802 virtual void throw_reset( bool async ) = 0;
00803 virtual bool terminated() const;
00804 void trigger_reset_event();
00805
00806 private:
00807 void delete_process();
00808 inline void reference_decrement();
00809 inline void reference_increment();
00810
00811 protected:
00812 inline void semantics();
00813
00814
00815
00816 public:
00817 const char* file;
00818 int lineno;
00819 int proc_id;
00823
00824
00825 int m_process_state;
00826
00827 sc_event_or_list* m_sensitivity_events;
00828 protected:
00829 int m_active_areset_n;
00830 int m_active_reset_n;
00831 bool m_dont_init;
00832 bool m_dynamic_proc;
00833 const sc_event* m_event_p;
00834
00835 int m_event_count;
00836 const sc_event_list* m_event_list_p;
00837 sc_process_b* m_exist_p;
00838 bool m_free_host;
00839 bool m_has_reset_signal;
00840 bool m_has_stack;
00841 bool m_is_thread;
00842 sc_report* m_last_report_p;
00843 sc_name_gen* m_name_gen_p;
00844 sc_curr_proc_kind m_process_kind;
00845 int m_references_n;
00846 std::vector<sc_reset*> m_resets;
00847 sc_event* m_reset_event_p;
00848 sc_event* m_resume_event_p;
00849 sc_process_b* m_runnable_p;
00850 sc_process_host* m_semantics_host_p;
00851 SC_ENTRY_FUNC m_semantics_method_p;
00852 int m_state;
00853 std::vector<const sc_event*> m_static_events;
00854 bool m_sticky_reset;
00855 sc_event* m_term_event_p;
00856 sc_throw_it_helper* m_throw_helper_p;
00857 process_throw_type m_throw_status;
00858 bool m_timed_out;
00859 sc_event* m_timeout_event_p;
00860 trigger_t m_trigger_type;
00861 bool m_unwinding;
00862
00866
00867 sc_acq_chnl_lock_queue m_acq_chnl_lock_queue;
00868
00872
00873 int m_segment_id;
00874
00878
00879 sc_timestamp m_timestamp;
00880
00884
00885 int m_instance_id;
00886
00887
00888
00889
00890 protected:
00891 static sc_process_b* m_last_created_process_p;
00892 };
00893
00894 typedef sc_process_b sc_process_b;
00895
00896
00897
00898
00899
00900
00901
00902 inline void
00903 sc_process_b::add_child_object( sc_object* object_p )
00904 {
00905 sc_object::add_child_object( object_p );
00906 reference_increment();
00907 }
00908
00909
00910
00911 inline bool
00912 sc_process_b::remove_child_object( sc_object* object_p )
00913 {
00914 if ( sc_object::remove_child_object( object_p ) ) {
00915 reference_decrement();
00916 return true;
00917 }
00918 else
00919 {
00920 return false;
00921 }
00922 }
00923
00924 inline const ::std::vector<sc_object*>&
00925 sc_process_b::get_child_objects() const
00926 {
00927 return m_child_objects;
00928 }
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940 inline void sc_process_b::initially_in_reset( bool async )
00941 {
00942 if ( async )
00943 m_active_areset_n++;
00944 else
00945 m_active_reset_n++;
00946 }
00947
00948
00949
00950
00951
00952
00953 inline bool sc_process_b::is_disabled() const
00954 {
00955 return (m_state & ps_bit_disabled) ? true : false;
00956 }
00957
00958
00959
00960
00961
00962
00963
00964 inline bool sc_process_b::is_runnable() const
00965 {
00966 return m_runnable_p != 0;
00967 }
00968
00969
00970
00971
00972
00973
00974 inline bool sc_process_b::is_unwinding() const
00975 {
00976 return m_unwinding;
00977 }
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987 inline bool sc_process_b::start_unwinding()
00988 {
00989 if ( !m_unwinding )
00990 {
00991 switch( m_throw_status )
00992 {
00993 case THROW_KILL:
00994 case THROW_ASYNC_RESET:
00995 case THROW_SYNC_RESET:
00996 m_unwinding = true;
00997 return true;
00998 case THROW_USER:
00999 default:
01000 break;
01001 }
01002 }
01003 return false;
01004 }
01005
01006
01007
01008
01009
01010
01011
01012 inline bool sc_process_b::clear_unwinding()
01013 {
01014 m_unwinding = false;
01015 return true;
01016 }
01017
01018
01019
01020
01021
01022
01023
01024
01025 inline sc_process_b* sc_process_b::last_created_process_base()
01026 {
01027 return m_last_created_process_p;
01028 }
01029
01030
01031
01032
01033
01034
01035
01036
01037 inline sc_curr_proc_kind sc_process_b::proc_kind() const
01038 {
01039 return m_process_kind;
01040 }
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 inline void sc_process_b::reference_decrement()
01051 {
01052 m_references_n--;
01053 if ( m_references_n == 0 ) delete_process();
01054 }
01055
01056
01057
01058
01059
01060
01061
01062
01063 inline void sc_process_b::reference_increment()
01064 {
01065 assert(m_references_n != 0);
01066 m_references_n++;
01067 }
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080 struct scoped_flag
01081 {
01082 scoped_flag( bool& b ) : ref(b){ ref = true; }
01083 ~scoped_flag() { ref = false; }
01084 bool& ref;
01085 };
01086 inline void sc_process_b::semantics()
01087 {
01088
01089
01090
01091 scoped_flag scoped_stack_flag( m_has_stack );
01092
01093 assert( m_process_kind != SC_NO_PROC_ );
01094
01095
01096
01097
01098
01099
01100 if ( m_reset_event_p &&
01101 ( (m_throw_status == THROW_SYNC_RESET) ||
01102 (m_throw_status == THROW_ASYNC_RESET) )
01103 ) {
01104 trigger_reset_event();
01105 }
01106
01107
01108
01109 m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET :
01110 ( m_active_reset_n ? THROW_SYNC_RESET : THROW_NONE);
01111
01112
01113
01114 # ifndef SC_USE_MEMBER_FUNC_PTR
01115 m_semantics_method_p->invoke( m_semantics_host_p );
01116 # else
01117 (m_semantics_host_p->*m_semantics_method_p)();
01118 # endif
01119 }
01120
01121
01122
01123
01124
01125
01126
01127 inline bool sc_process_b::terminated() const
01128 {
01129 return (m_state & ps_bit_zombie) != 0;
01130 }
01131
01132
01133
01134
01135
01136
01137
01138 inline bool sc_process_b::timed_out() const
01139 {
01140 return m_timed_out;
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
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335 #endif // !defined(sc_process_h_INCLUDED)