sc_thread_process.cpp

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.cpp -- Thread process implementation
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.cpp,v $
00038 // Revision 1.1.1.1  2006/12/15 20:31:37  acg
00039 // SystemC 2.2
00040 //
00041 // Revision 1.7  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.6  2006/03/21 00:00:34  acg
00047 //   Andy Goodrich: changed name of sc_get_current_process_base() to be
00048 //   sc_get_current_process_b() since its returning an sc_process_b instance.
00049 //
00050 // Revision 1.5  2006/01/26 21:04:55  acg
00051 //  Andy Goodrich: deprecation message changes and additional messages.
00052 //
00053 // Revision 1.4  2006/01/24 20:49:05  acg
00054 // Andy Goodrich: changes to remove the use of deprecated features within the
00055 // simulator, and to issue warning messages when deprecated features are used.
00056 //
00057 // Revision 1.3  2006/01/13 18:44:30  acg
00058 // Added $Log to record CVS changes into the source.
00059 //
00060 
00061 #include "sysc/kernel/sc_thread_process.h"
00062 #include "sysc/kernel/sc_process_handle.h"
00063 #include "sysc/kernel/sc_simcontext_int.h"
00064 #include "sysc/kernel/sc_module.h"
00065 
00066 namespace sc_core {
00067 
00068 //------------------------------------------------------------------------------
00069 //"sc_thread_cor_fn"
00070 // 
00071 // This function invokes the coroutine for the supplied object instance.
00072 //------------------------------------------------------------------------------
00073 void sc_thread_cor_fn( void* arg )
00074 {
00075     sc_thread_handle thread_h = RCAST<sc_thread_handle>( arg );
00076 
00077     // PROCESS THE THREAD AND PROCESS ANY EXCEPTIONS THAT ARE THROWN:
00078 
00079     while( true ) {
00080 
00081         try {
00082             thread_h->semantics();
00083         }
00084         catch( sc_user ) {
00085             continue;
00086         }
00087         catch( sc_halt ) {
00088             ::std::cout << "Terminating process "
00089                       << thread_h->name() << ::std::endl;
00090         }
00091         catch( const sc_report& ex ) {
00092             std::cout << "\n" << ex.what() << std::endl;
00093             thread_h->simcontext()->set_error();
00094         }
00095         break;
00096     }
00097 
00098     // SCHEDULE THREAD PACKAGE FOR DESTRUCTION:
00099     //
00100     // If control reaches this point the process semantics have returned
00101     // so the process should die.
00102 
00103     thread_h->kill_process();
00104 }
00105 
00106 
00107 //------------------------------------------------------------------------------
00108 //"sc_thread_process::kill_process"
00109 //
00110 // This method removes this object instance from use. It calls the
00111 // sc_process_b::kill_process() method to perform low level clean up. Then
00112 // it aborts this process if it is the active process.
00113 //------------------------------------------------------------------------------
00114 void sc_thread_process::kill_process()
00115 {
00116     // SIGNAL ANY MONITORS WAITING FOR THIS THREAD TO EXIT:
00117 
00118     int mon_n = m_monitor_q.size();
00119     if ( mon_n )
00120     {   
00121         for ( int mon_i = 0; mon_i < mon_n; mon_i++ )
00122             m_monitor_q[mon_i]->signal( this, sc_process_monitor::spm_exit);
00123     }
00124 
00125     // CLEAN UP THE LOW LEVEL STUFF ASSOCIATED WITH THIS DATA STRUCTURE:
00126 
00127     sc_process_b::kill_process();
00128 
00129 
00130     // IF THIS IS THE ACTIVE PROCESS THEN ABORT IT AND SWITCH TO A NEW ONE:
00131     //
00132     // Note we do not use an sc_process_handle, by making a call to
00133     // sc_get_current_process_handle(), since we don't want to increment the 
00134     // usage count in case it is already zero. (We are being deleted, and this
00135     // call to kill_process() may have been the result of the usage count going
00136     // to zero.) So we get a raw sc_process_b pointer instead.
00137  
00138     sc_process_b* active_p = sc_get_current_process_b();
00139     sc_simcontext*    simc_p = simcontext();
00140     if ( active_p == (sc_process_b*)this )
00141     {
00142         simc_p->cor_pkg()->abort( simc_p->next_cor() );
00143     }
00144 
00145     // IF THIS WAS NOT THE ACTIVE PROCESS REMOVE IT FROM ANY RUN QUEUES:
00146 
00147     else
00148     {
00149         simc_p->remove_runnable_thread( this );
00150     }
00151 }
00152 
00153 
00154 //------------------------------------------------------------------------------
00155 //"sc_thread_process::prepare_for_simulation"
00156 //
00157 // This method prepares this object instance for simulation. It calls the
00158 // coroutine package to create the actual thread.
00159 //------------------------------------------------------------------------------
00160 void sc_thread_process::prepare_for_simulation()
00161 {
00162     m_cor_p = simcontext()->cor_pkg()->create( m_stack_size,
00163                          sc_thread_cor_fn, this );
00164     m_cor_p->stack_protect( true );
00165 }
00166 
00167 
00168 //------------------------------------------------------------------------------
00169 //"sc_thread_process::sc_thread_process"
00170 //
00171 // This is the object instance constructor for this class.
00172 //------------------------------------------------------------------------------
00173 sc_thread_process::sc_thread_process( const char* name_p, bool free_host,
00174     SC_ENTRY_FUNC method_p, sc_process_host* host_p, 
00175     const sc_spawn_options* opt_p 
00176 ):
00177     sc_process_b(
00178         name_p && name_p[0] ? name_p : sc_gen_unique_name("thread_p"), 
00179         free_host, method_p, host_p, opt_p),
00180         m_cor_p(0), m_stack_size(SC_DEFAULT_STACK_SIZE), 
00181         m_wait_cycle_n(0)
00182 {
00183 
00184     // CHECK IF THIS IS AN sc_module-BASED PROCESS AND SIMUALTION HAS STARTED:
00185 
00186     if ( DCAST<sc_module*>(host_p) != 0 && sc_is_running() )
00187     {
00188         SC_REPORT_ERROR( SC_ID_MODULE_THREAD_AFTER_START_, "" );
00189     }
00190 
00191     // INITIALIZE VALUES:
00192     //
00193     // If there are spawn options use them.
00194 
00195     m_process_kind = SC_THREAD_PROC_;
00196 
00197     if (opt_p) {
00198         m_dont_init = opt_p->m_dont_initialize;
00199         if ( opt_p->m_stack_size ) m_stack_size = opt_p->m_stack_size;
00200 
00201         // traverse event sensitivity list
00202         for (unsigned int i = 0; i < opt_p->m_sensitive_events.size(); i++) {
00203             sc_sensitive::make_static_sensitivity(
00204                 this, *opt_p->m_sensitive_events[i]);
00205         }
00206 
00207         // traverse port base sensitivity list
00208         for ( unsigned int i = 0; i < opt_p->m_sensitive_port_bases.size(); i++)
00209         {
00210             sc_sensitive::make_static_sensitivity(
00211                 this, *opt_p->m_sensitive_port_bases[i]);
00212         }
00213 
00214         // traverse interface sensitivity list
00215         for ( unsigned int i = 0; i < opt_p->m_sensitive_interfaces.size(); i++)
00216         {
00217             sc_sensitive::make_static_sensitivity(
00218                 this, *opt_p->m_sensitive_interfaces[i]);
00219         }
00220 
00221         // traverse event finder sensitivity list
00222         for ( unsigned int i = 0; i < opt_p->m_sensitive_event_finders.size();
00223             i++)
00224         {
00225             sc_sensitive::make_static_sensitivity(
00226                 this, *opt_p->m_sensitive_event_finders[i]);
00227         }
00228     }
00229 
00230     else
00231     {
00232         m_dont_init = false;
00233     }
00234 
00235 }
00236 
00237 //------------------------------------------------------------------------------
00238 //"sc_thread_process::~sc_thread_process"
00239 //
00240 // This is the object instance constructor for this class.
00241 //------------------------------------------------------------------------------
00242 sc_thread_process::~sc_thread_process()
00243 {
00244 
00245     // DESTROY THE COROUTINE FOR THIS THREAD:
00246 
00247     if( m_cor_p != 0 ) {
00248         m_cor_p->stack_protect( false );
00249         delete m_cor_p;
00250         m_cor_p = 0;
00251     }
00252 }
00253 
00254 
00255 //------------------------------------------------------------------------------
00256 //"sc_thread_process::signal_monitors"
00257 //
00258 // This methods signals the list of monitors for this object instance.
00259 //------------------------------------------------------------------------------
00260 void sc_thread_process::signal_monitors(int type)
00261 {       
00262     int mon_n;  // # of monitors present.
00263         
00264     mon_n = m_monitor_q.size();
00265     for ( int mon_i = 0; mon_i < mon_n; mon_i++ )
00266         m_monitor_q[mon_i]->signal(this, type);
00267 }   
00268 
00269 
00270 //------------------------------------------------------------------------------
00271 //"sc_thread_process::trigger_dynamic"
00272 //
00273 //------------------------------------------------------------------------------
00274 bool sc_thread_process::trigger_dynamic( sc_event* e )
00275 {
00276     if( is_runnable() ) {
00277         return false;
00278     }
00279     m_timed_out = false;
00280     switch( m_trigger_type ) {
00281     case EVENT: {
00282         m_trigger_type = STATIC;
00283         return true;
00284     }
00285     case OR_LIST: {
00286         m_event_list_p->remove_dynamic( this, e );
00287         m_event_list_p->auto_delete();
00288         m_event_list_p = 0;
00289         m_trigger_type = STATIC;
00290         return true;
00291     }
00292     case AND_LIST: {
00293         if( -- m_event_count == 0 ) {
00294             // no need to remove_dynamic
00295             m_event_list_p->auto_delete();
00296             m_event_list_p = 0;
00297             m_trigger_type = STATIC;
00298             return true;
00299         }
00300         return false;
00301     }
00302     case TIMEOUT: {
00303         m_trigger_type = STATIC;
00304         return true;
00305     }
00306     case EVENT_TIMEOUT: {
00307         if( e == m_event_p ) {
00308             m_timeout_event_p->cancel();
00309             m_timeout_event_p->reset();
00310         } else {
00311             m_timed_out = true;
00312             m_event_p->remove_dynamic( this );
00313         }
00314         m_event_p = 0;
00315         m_trigger_type = STATIC;
00316         return true;
00317     }
00318     case OR_LIST_TIMEOUT: {
00319         if( e != m_timeout_event_p ) {
00320             m_timeout_event_p->cancel();
00321             m_timeout_event_p->reset();
00322         } else {
00323             m_timed_out = true;
00324         }
00325         m_event_list_p->remove_dynamic( this, e );
00326         m_event_list_p->auto_delete();
00327         m_event_list_p = 0;
00328         m_trigger_type = STATIC;
00329         return true;
00330     }
00331     case AND_LIST_TIMEOUT: {
00332         if( e == m_timeout_event_p ) {
00333             m_timed_out = true;
00334             m_event_list_p->remove_dynamic( this, e );
00335             m_event_list_p->auto_delete();
00336             m_event_list_p = 0;
00337             m_trigger_type = STATIC;
00338             return true;
00339         } else if( -- m_event_count == 0 ) {
00340             m_timeout_event_p->cancel();
00341             m_timeout_event_p->reset();
00342             // no need to remove_dynamic
00343             m_event_list_p->auto_delete();
00344             m_event_list_p = 0;
00345             m_trigger_type = STATIC;
00346             return true;
00347         }
00348         return false;
00349     }
00350     case STATIC: {
00351         // we should never get here
00352         assert( false );
00353     }
00354     }
00355     return false;
00356 }
00357 
00358 
00359 //------------------------------------------------------------------------------
00360 //"sc_set_stack_size"
00361 //
00362 //------------------------------------------------------------------------------
00363 void
00364 sc_set_stack_size( sc_thread_handle thread_h, std::size_t size )
00365 {
00366     thread_h->set_stack_size( size );
00367 }
00368 
00369 } // namespace sc_core 

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