sc_thread_process.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2006 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_thread_process.h -- Thread process declarations
00021 
00022   Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005
00023 
00024 
00025  *****************************************************************************/
00026 
00027 /*****************************************************************************
00028 
00029   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00030   changes you are making here.
00031 
00032       Name, Affiliation, Date:
00033   Description of Modification:
00034 
00035  *****************************************************************************/
00036 
00037 // $Log: sc_thread_process.h,v $
00038 // Revision 1.1.1.1  2006/12/15 20:31:37  acg
00039 // SystemC 2.2
00040 //
00041 // Revision 1.5  2006/04/11 23:13:21  acg
00042 //   Andy Goodrich: Changes for reduced reset support that only includes
00043 //   sc_cthread, but has preliminary hooks for expanding to method and thread
00044 //   processes also.
00045 //
00046 // Revision 1.4  2006/01/24 20:49:05  acg
00047 // Andy Goodrich: changes to remove the use of deprecated features within the
00048 // simulator, and to issue warning messages when deprecated features are used.
00049 //
00050 // Revision 1.3  2006/01/13 18:44:30  acg
00051 // Added $Log to record CVS changes into the source.
00052 //
00053 
00054 #if !defined(sc_thread_process_h_INCLUDED)
00055 #define sc_thread_process_h_INCLUDED
00056 
00057 #include "sysc/kernel/sc_spawn_options.h"
00058 #include "sysc/kernel/sc_process.h"
00059 #include "sysc/kernel/sc_cor.h"
00060 #include "sysc/kernel/sc_event.h"
00061 #include "sysc/kernel/sc_except.h"
00062 #include "sysc/kernel/sc_reset.h"
00063 
00064 
00065 namespace sc_core {
00066 
00067 class sc_event_and_list;
00068 class sc_event_or_list;
00069 class sc_reset;
00070 
00071 // friend function declarations
00072     void sc_thread_cor_fn( void* );
00073     void sc_cthread_cor_fn( void* );
00074     void sc_set_stack_size( sc_thread_handle, std::size_t );
00075     class sc_event;
00076     class sc_join;
00077     class sc_module;
00078     class sc_process_handle;
00079     class sc_process_table;
00080     class sc_simcontext;
00081     class sc_runnable;
00082     sc_cor* get_cor_pointer( sc_process_b* process_p );
00083 
00084     void wait( sc_simcontext* );
00085     void wait( const sc_event&,
00086               sc_simcontext* );
00087     void wait( sc_event_or_list&,
00088               sc_simcontext* );
00089     void wait( sc_event_and_list&,
00090               sc_simcontext* );
00091     void wait( const sc_time&,
00092               sc_simcontext* );
00093     void wait( const sc_time&, const sc_event&,
00094               sc_simcontext* );
00095     void wait( const sc_time&, sc_event_or_list&,
00096               sc_simcontext* );
00097     void wait( const sc_time&, sc_event_and_list&,
00098               sc_simcontext* );
00099 
00100 //==============================================================================
00101 
00102 void sc_set_stack_size( sc_thread_handle thread_h, std::size_t size );
00103 
00104 //==============================================================================
00105 // sc_thread_process -
00106 //
00107 //==============================================================================
00108 class sc_thread_process : public sc_process_b {
00109     friend void sc_thread_cor_fn( void* );
00110     friend void sc_cthread_cor_fn( void* );
00111     friend void sc_set_stack_size( sc_thread_handle, std::size_t );
00112     friend class sc_event;
00113     friend class sc_join;
00114     friend class sc_module;
00115     friend class sc_process_handle;
00116     friend class sc_process_table;
00117     friend class sc_simcontext;
00118     friend class sc_runnable;
00119     friend sc_cor* get_cor_pointer( sc_process_b* process_p );
00120 
00121     friend void wait( sc_simcontext* );
00122     friend void wait( const sc_event&,
00123               sc_simcontext* );
00124     friend void wait( sc_event_or_list&,
00125               sc_simcontext* );
00126     friend void wait( sc_event_and_list&,
00127               sc_simcontext* );
00128     friend void wait( const sc_time&,
00129               sc_simcontext* );
00130     friend void wait( const sc_time&, const sc_event&,
00131               sc_simcontext* );
00132     friend void wait( const sc_time&, sc_event_or_list&,
00133               sc_simcontext* );
00134     friend void wait( const sc_time&, sc_event_and_list&,
00135               sc_simcontext* );
00136   public:
00137     sc_thread_process( const char* name_p, bool free_host,
00138         SC_ENTRY_FUNC method_p, sc_process_host* host_p,
00139         const sc_spawn_options* opt_p );
00140 
00141     virtual ~sc_thread_process();
00142 
00143     virtual const char* kind() const
00144         { return "sc_thread_process"; }
00145 
00146   protected:
00147     virtual void kill_process();
00148     sc_thread_handle next_exist();
00149     sc_thread_handle next_runnable();
00150     virtual void prepare_for_simulation();
00151     inline bool ready_to_run();
00152     void set_next_exist( sc_thread_handle next_p );
00153     void set_next_runnable( sc_thread_handle next_p );
00154 
00155     void set_stack_size( std::size_t size );
00156     inline void suspend_me();
00157 
00158     bool trigger_dynamic( sc_event* );
00159 
00160     void wait( const sc_event& );
00161     void wait( sc_event_or_list& );
00162     void wait( sc_event_and_list& );
00163     void wait( const sc_time& );
00164     void wait( const sc_time&, const sc_event& );
00165     void wait( const sc_time&, sc_event_or_list& );
00166     void wait( const sc_time&, sc_event_and_list& );
00167     void wait_cycles( int n=1 );
00168 
00169   protected:
00170     void add_monitor( sc_process_monitor* monitor_p );
00171     void remove_monitor( sc_process_monitor* monitor_p);
00172     void signal_monitors( int type = 0 );
00173 
00174   protected:
00175     sc_cor*                          m_cor_p;        // Thread's coroutine.
00176     static sc_cor*                   m_dead_cor_p;   // Coroutine to delete.
00177     std::vector<sc_process_monitor*> m_monitor_q;    // Thread monitors.
00178     std::size_t                      m_stack_size;   // Thread stack size.
00179     int                              m_wait_cycle_n; // # of waits to be done.
00180 
00181   private: // disabled
00182     sc_thread_process( const sc_thread_process& );
00183     const sc_thread_process& operator = ( const sc_thread_process& );
00184 
00185 };
00186 
00187 
00188 //------------------------------------------------------------------------------
00189 //"sc_thread_process::ready_to_run"
00190 //
00191 //------------------------------------------------------------------------------
00192 inline bool sc_thread_process::ready_to_run()
00193 {
00194     if ( (m_throw_type == THROW_NONE) && ( m_wait_cycle_n > 0 ) )
00195     {
00196         --m_wait_cycle_n;
00197         return false;
00198     }
00199     return true;
00200 }
00201 
00202 
00203 //------------------------------------------------------------------------------
00204 //"sc_thread_process::set_stack_size"
00205 //
00206 //------------------------------------------------------------------------------
00207 inline void sc_thread_process::set_stack_size( std::size_t size )
00208 {
00209     assert( size );
00210     m_stack_size = size;
00211 }
00212 
00213 //------------------------------------------------------------------------------
00214 //"sc_thread_process::suspend_me"
00215 //
00216 // This method suspends this object instance in favor of the next runnable
00217 // process. Upon awakening we check to see if an exception should be thrown.
00218 //------------------------------------------------------------------------------
00219 inline void sc_thread_process::suspend_me()
00220 {
00221     sc_simcontext* simc_p = simcontext();
00222     simc_p->cor_pkg()->yield( simc_p->next_cor() );
00223 
00224     switch ( m_throw_type )
00225     {
00226       case THROW_NONE:
00227         break;
00228       case THROW_RESET:
00229         throw sc_user();
00230       default:
00231         break;
00232     }
00233 }
00234 
00235 //------------------------------------------------------------------------------
00236 //"sc_thread_process::wait"
00237 //
00238 //------------------------------------------------------------------------------
00239 inline
00240 void
00241 sc_thread_process::wait( const sc_event& e )
00242 {
00243     e.add_dynamic( this );
00244     m_trigger_type = EVENT;
00245     suspend_me();
00246 }
00247 
00248 inline
00249 void
00250 sc_thread_process::wait( sc_event_or_list& el )
00251 {
00252     el.add_dynamic( this );
00253     m_event_list_p = &el;
00254     m_trigger_type = OR_LIST;
00255     suspend_me();
00256 }
00257 
00258 inline
00259 void
00260 sc_thread_process::wait( sc_event_and_list& el )
00261 {
00262     el.add_dynamic( this );
00263     m_event_list_p = &el;
00264     m_event_count = el.size();
00265     m_trigger_type = AND_LIST;
00266     suspend_me();
00267 }
00268 
00269 inline
00270 void
00271 sc_thread_process::wait( const sc_time& t )
00272 {
00273     m_timeout_event_p->notify_internal( t );
00274     m_timeout_event_p->add_dynamic( this );
00275     m_trigger_type = TIMEOUT;
00276     suspend_me();
00277 }
00278 
00279 inline
00280 void
00281 sc_thread_process::wait( const sc_time& t, const sc_event& e )
00282 {
00283     m_timeout_event_p->notify_internal( t );
00284     m_timeout_event_p->add_dynamic( this );
00285     e.add_dynamic( this );
00286     m_event_p = &e;
00287     m_trigger_type = EVENT_TIMEOUT;
00288     suspend_me();
00289 }
00290 
00291 inline
00292 void
00293 sc_thread_process::wait( const sc_time& t, sc_event_or_list& el )
00294 {
00295     m_timeout_event_p->notify_internal( t );
00296     m_timeout_event_p->add_dynamic( this );
00297     el.add_dynamic( this );
00298     m_event_list_p = &el;
00299     m_trigger_type = OR_LIST_TIMEOUT;
00300     suspend_me();
00301 }
00302 
00303 inline
00304 void
00305 sc_thread_process::wait( const sc_time& t, sc_event_and_list& el )
00306 {
00307     m_timeout_event_p->notify_internal( t );
00308     m_timeout_event_p->add_dynamic( this );
00309     el.add_dynamic( this );
00310     m_event_list_p = &el;
00311     m_event_count = el.size();
00312     m_trigger_type = AND_LIST_TIMEOUT;
00313     suspend_me();
00314 }
00315 
00316 //------------------------------------------------------------------------------
00317 //"sc_thread_process::wait_cycles"
00318 //
00319 // This method suspends this object instance for the specified number of cycles.
00320 // A cycle is defined as the event the thread is set up to staticly wait on.
00321 // The field m_wait_cycle_n is set to one less than the number of cycles to
00322 // be waited for, since the value is tested before being decremented in
00323 // the simulation kernel.
00324 //------------------------------------------------------------------------------
00325 inline
00326 void
00327 sc_thread_process::wait_cycles( int n )
00328 {
00329     m_wait_cycle_n = n-1;
00330     suspend_me();
00331 }
00332 
00333 //------------------------------------------------------------------------------
00334 //"sc_thread_process::miscellaneous support"
00335 //
00336 //------------------------------------------------------------------------------
00337 inline
00338 void sc_thread_process::add_monitor(sc_process_monitor* monitor_p)
00339 {
00340     m_monitor_q.push_back(monitor_p);
00341 }
00342 
00343 
00344 inline
00345 void sc_thread_process::remove_monitor(sc_process_monitor* monitor_p)
00346 {
00347     int mon_n = m_monitor_q.size();
00348 
00349     for ( int mon_i = 0; mon_i < mon_n; mon_i++ )
00350     {
00351     if  ( m_monitor_q[mon_i] == monitor_p )
00352         {
00353             m_monitor_q[mon_i] = m_monitor_q[mon_n-1];
00354             m_monitor_q.resize(mon_n-1);
00355         }
00356     }
00357 }
00358 
00359 inline
00360 void sc_thread_process::set_next_exist(sc_thread_handle next_p)
00361 {
00362     m_exist_p = next_p;
00363 }
00364 
00365 inline
00366 sc_thread_handle sc_thread_process::next_exist()
00367 {
00368     return (sc_thread_handle)m_exist_p;
00369 }
00370 
00371 inline
00372 void sc_thread_process::set_next_runnable(sc_thread_handle next_p)
00373 {
00374     m_runnable_p = next_p;
00375 }
00376 
00377 inline
00378 sc_thread_handle sc_thread_process::next_runnable()
00379 {
00380     return (sc_thread_handle)m_runnable_p;
00381 }
00382 
00383 inline sc_cor* get_cor_pointer( sc_process_b* process_p )
00384 {
00385     sc_thread_handle thread_p = DCAST<sc_thread_handle>(process_p);
00386     return thread_p->m_cor_p;
00387 }
00388 
00389 } // namespace sc_core
00390 
00391 #endif // !defined(sc_thread_process_h_INCLUDED)

Generated on Wed Jan 21 15:32:09 2009 for SystemC by  doxygen 1.5.5