00001 /***************************************************************************** 00002 00003 The following code is derived, directly or indirectly, from the SystemC 00004 source code Copyright (c) 1996-2014 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 (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.accellera.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 CHANGE LOG AT THE END OF THE FILE 00026 *****************************************************************************/ 00027 00028 00029 #if !defined(sc_thread_process_h_INCLUDED) 00030 #define sc_thread_process_h_INCLUDED 00031 00032 #include "sysc/kernel/sc_spawn_options.h" 00033 #include "sysc/kernel/sc_process.h" 00034 #include "sysc/kernel/sc_cor.h" 00035 #include "sysc/kernel/sc_event.h" 00036 #include "sysc/kernel/sc_except.h" 00037 #include "sysc/kernel/sc_reset.h" 00038 00039 // DEBUGGING MACROS: 00040 // 00041 // DEBUG_MSG(NAME,P,MSG) 00042 // MSG = message to print 00043 // NAME = name that must match the process for the message to print, or 00044 // null if the message should be printed unconditionally. 00045 // P = pointer to process message is for, or NULL in which case the 00046 // message will not print. 00047 #if 0 00048 # define DEBUG_NAME "" 00049 # define DEBUG_MSG(NAME,P,MSG) \ 00050 { \ 00051 if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ 00052 std::cout << "**** " << sc_time_stamp() << " (" \ 00053 << sc_get_current_process_name() << "): " << MSG \ 00054 << " - " << P->name() << std::endl; \ 00055 } 00056 #else 00057 # define DEBUG_MSG(NAME,P,MSG) 00058 #endif 00059 00060 00061 namespace sc_core { 00062 00063 // forward references: 00064 class sc_event_and_list; 00065 class sc_event_or_list; 00066 class sc_reset; 00067 void sc_thread_cor_fn( void* ); 00068 void sc_set_stack_size( sc_thread_handle, std::size_t ); 00069 class sc_event; 00070 class sc_join; 00071 class sc_module; 00072 class sc_process_handle; 00073 class sc_process_table; 00074 class sc_simcontext; 00075 class sc_runnable; 00076 00077 sc_cor* get_cor_pointer( sc_process_b* process_p ); 00078 void sc_set_stack_size( sc_thread_handle thread_h, std::size_t size ); 00079 void wait( int, sc_simcontext* ); 00080 void wait( const sc_event&, int, sc_simcontext* ); 00081 void wait( const sc_event_or_list&, int, sc_simcontext* ); 00082 void wait( const sc_event_and_list&, int, sc_simcontext* ); 00083 void wait( const sc_time&, int, sc_simcontext* ); 00084 void wait( const sc_time&, const sc_event&, int, sc_simcontext* ); 00085 void wait( const sc_time&, const sc_event_or_list&, int, sc_simcontext* ); 00086 void wait( const sc_time&, const sc_event_and_list&, int, sc_simcontext* ); 00087 00088 /**************************************************************************/ 00093 class sc_thread_process : public sc_process_b { 00094 friend void sc_thread_cor_fn( void* ); 00095 friend void sc_set_stack_size( sc_thread_handle, std::size_t ); 00096 friend class sc_event; 00097 friend class sc_join; 00098 friend class sc_module; 00099 00100 // 04/07/2015 GL: a new sc_channel class is derived from sc_module 00101 friend class sc_channel; 00102 00103 friend class sc_process_b; 00104 friend class sc_process_handle; 00105 friend class sc_process_table; 00106 friend class sc_simcontext; 00107 friend class sc_runnable; 00108 friend sc_cor* get_cor_pointer( sc_process_b* process_p ); 00109 00110 // 06/12/2015 GL: modified for the OoO simulation 00111 friend void wait( int, sc_simcontext* ); 00112 friend void wait( const sc_event&, int, sc_simcontext* ); 00113 friend void wait( const sc_event_or_list&, int, sc_simcontext* ); 00114 friend void wait( const sc_event_and_list&, int, sc_simcontext* ); 00115 friend void wait( const sc_time&, int, sc_simcontext* ); 00116 friend void wait( const sc_time&, const sc_event&, int, sc_simcontext* ); 00117 friend void wait( const sc_time&, const sc_event_or_list&, int, 00118 sc_simcontext* ); 00119 friend void wait( const sc_time&, const sc_event_and_list&, int, 00120 sc_simcontext*); 00121 00122 public: 00123 sc_thread_process( const char* name_p, bool free_host, 00124 SC_ENTRY_FUNC method_p, sc_process_host* host_p, 00125 const sc_spawn_options* opt_p ); 00126 00127 virtual const char* kind() const 00128 { return "sc_thread_process"; } 00129 00130 protected: 00131 // may not be deleted manually (called from sc_process_b) 00132 virtual ~sc_thread_process(); 00133 00134 virtual void disable_process( 00135 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 00136 virtual void enable_process( 00137 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 00138 virtual void kill_process( 00139 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 00140 sc_thread_handle next_exist(); 00141 sc_thread_handle next_runnable(); 00142 virtual void prepare_for_simulation(); 00143 virtual void resume_process( 00144 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 00145 void set_next_exist( sc_thread_handle next_p ); 00146 void set_next_runnable( sc_thread_handle next_p ); 00147 00148 void set_stack_size( std::size_t size ); 00149 inline void suspend_me(); 00150 virtual void suspend_process( 00151 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 00152 virtual void throw_reset( bool async ); 00153 virtual void throw_user( const sc_throw_it_helper& helper, 00154 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 00155 00156 bool trigger_dynamic( sc_event* ); 00157 00162 // 08/14/2015 GL: add a new parameter to update the local time stamp 00163 //inline void trigger_static(); 00164 inline void trigger_static( sc_event* ); 00165 00170 // 06/12/2015 GL: modified for the OoO simulation 00171 void wait( const sc_event&, int ); 00172 00177 // 06/12/2015 GL: modified for the OoO simulation 00178 void wait( const sc_event_or_list&, int ); 00179 00184 // 06/12/2015 GL: modified for the OoO simulation 00185 void wait( const sc_event_and_list&, int ); 00186 00191 // 06/12/2015 GL: modified for the OoO simulation 00192 void wait( const sc_time&, int ); 00193 00198 // 06/12/2015 GL: modified for the OoO simulation 00199 void wait( const sc_time&, const sc_event&, int ); 00200 00205 // 06/12/2015 GL: modified for the OoO simulation 00206 void wait( const sc_time&, const sc_event_or_list&, int ); 00207 00212 // 06/12/2015 GL: modified for the OoO simulation 00213 void wait( const sc_time&, const sc_event_and_list&, int ); 00214 00219 // 06/12/2015 GL: modified for the OoO simulation 00220 void wait_cycles( int, int n=1 ); 00221 00222 protected: 00223 void add_monitor( sc_process_monitor* monitor_p ); 00224 void remove_monitor( sc_process_monitor* monitor_p); 00225 void signal_monitors( int type = 0 ); 00226 00227 protected: 00228 sc_cor* m_cor_p; // Thread's coroutine. 00229 std::vector<sc_process_monitor*> m_monitor_q; // Thread monitors. 00230 std::size_t m_stack_size; // Thread stack size. 00231 int m_wait_cycle_n; // # of waits to be done. 00232 00233 private: // disabled 00234 sc_thread_process( const sc_thread_process& ); 00235 const sc_thread_process& operator = ( const sc_thread_process& ); 00236 00237 }; 00238 00239 //------------------------------------------------------------------------------ 00240 //"sc_thread_process::set_stack_size" 00241 // 00242 //------------------------------------------------------------------------------ 00243 inline void sc_thread_process::set_stack_size( std::size_t size ) 00244 { 00245 assert( size ); 00246 m_stack_size = size; 00247 } 00248 00249 //------------------------------------------------------------------------------ 00250 //"sc_thread_process::suspend_me" 00251 // 00252 // This method suspends this object instance in favor of the next runnable 00253 // process. Upon awakening we check to see if an exception should be thrown. 00254 // There are two types of exceptions that can be thrown, synchronous reset 00255 // and asynchronous reset. At a future time there may be more asynchronous 00256 // exceptions. If an asynchronous reset is seen and there is not static reset 00257 // specified, or the static reset is not active then clear the throw 00258 // type for the next time this method is called. 00259 // 00260 // Notes: 00261 // (1) For an explanation of how the reset mechanism works see the top of 00262 // the file sc_reset.cpp. 00263 // (2) The m_sticky_reset field is used to handle synchronous resets that 00264 // are enabled via the sc_process_handle::sync_reset_on() method. These 00265 // resets are not generated by a signal, but rather are modal by 00266 // method call: sync_reset_on() - sync_reset_off(). 00267 //------------------------------------------------------------------------------ 00268 inline void sc_thread_process::suspend_me() 00269 { 00270 // 11/21/2014 GL: assume we have acquired the kernel lock upon here 00271 #ifdef SC_LOCK_CHECK 00272 assert( sc_get_curr_simcontext()->is_locked_and_owner() ); 00273 #endif /* SC_LOCK_CHECK */ 00274 00275 // remember, if we're currently unwinding 00276 00277 bool unwinding_preempted = m_unwinding; 00278 00279 sc_simcontext* simc_p = simcontext(); 00280 //sc_cor* cor_p = simc_p->next_cor(); 00281 simc_p->remove_running_process( (sc_process_b*)this ); 00282 // simc_p->schedule( m_cor_p ); 00283 simc_p->oooschedule( m_cor_p ); // 08/19/2015 GL: OoO scheduling 00284 00285 // do not switch, if we're about to execute next (e.g. suicide) 00286 00287 //if( m_cor_p != cor_p ) 00288 //{ 00289 // DEBUG_MSG( DEBUG_NAME , this, "suspending thread"); 00290 // simc_p->cor_pkg()->yield( cor_p ); 00291 // DEBUG_MSG( DEBUG_NAME , this, "resuming thread"); 00292 //} 00293 00294 // if I am not scheduled to execute again 00295 if ( !simc_p->is_running_process( (sc_process_b*)this ) ) 00296 { 00297 DEBUG_MSG( DEBUG_NAME , this, "suspending thread"); 00298 simc_p->suspend_cor( m_cor_p ); 00299 DEBUG_MSG( DEBUG_NAME , this, "resuming thread"); 00300 } 00301 00302 // IF THERE IS A THROW TO BE DONE FOR THIS PROCESS DO IT NOW: 00303 // 00304 // (1) Optimize THROW_NONE for speed as it is the normal case. 00305 // (2) If this thread is already unwinding then suspend_me() was 00306 // called from the catch clause to throw an exception on another 00307 // process, so just go back to the catch clause. 00308 00309 if ( m_throw_status == THROW_NONE ) return; 00310 00311 if ( m_unwinding ) return; 00312 00313 switch( m_throw_status ) 00314 { 00315 case THROW_ASYNC_RESET: 00316 case THROW_SYNC_RESET: 00317 DEBUG_MSG( DEBUG_NAME , this, "throwing reset for"); 00318 if ( m_reset_event_p ) m_reset_event_p->notify(); 00319 throw sc_unwind_exception( this, true ); 00320 00321 case THROW_USER: 00322 DEBUG_MSG( DEBUG_NAME, this, "invoking throw_it for"); 00323 m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET : 00324 (m_active_reset_n ? THROW_SYNC_RESET : 00325 THROW_NONE); 00326 m_throw_helper_p->throw_it(); 00327 break; 00328 00329 case THROW_KILL: 00330 DEBUG_MSG( DEBUG_NAME, this, "throwing kill for"); 00331 throw sc_unwind_exception( this, false ); 00332 00333 default: // THROWING_NOW 00334 sc_assert( unwinding_preempted ); 00335 DEBUG_MSG( DEBUG_NAME, this, "restarting thread"); 00336 break; 00337 } 00338 } 00339 00340 00341 //------------------------------------------------------------------------------ 00342 //"sc_thread_process::wait" 00343 // 00344 // Notes: 00345 // (1) The correct order to lock and unlock channel locks (to avoid deadlocks 00346 // and races) for SystemC functions with context switch: 00347 // 00348 // outer_channel.lock_and_push 00349 // [outer channel work] 00350 // inner_channel.lock_and_push 00351 // [inner channel work] 00352 // +----------------------------------WAIT----------------------------------+ 00353 // | +------------------------Simulation Kernel------------------------+ | 00354 // | | acquire kernel lock | | 00355 // | | +------unlock_all_channels-----+ | | 00356 // | | | inner_channel.unlock | | | 00357 // | | | outer_channel.unlock | | | 00358 // | | +------------------------------+ | | 00359 // | | [kernel work] | | 00360 // | | pthread_cond_wait: release kernel lock | | 00361 // | | [sleep] | | 00362 // | | pthread_cond_wait (upon wakeup): acquire kernel lock | | 00363 // | | [kernel work] | | 00364 // | | release kernel lock | | 00365 // | +-----------------------------------------------------------------+ | 00366 // | [no lock/no work] | 00367 // | +------lock_all_channels-------+ | 00368 // | | outer_channel.lock | | 00369 // | | inner_channel.lock | | 00370 // | +------------------------------+ | 00371 // +------------------------------------------------------------------------+ 00372 // [inner channel work] 00373 // inner_channel.pop_and_unlock 00374 // [outer channel work] 00375 // outer_channel.pop_and_unlock 00376 // 00377 // (2) If we did not consider immediate notification, a more cleaner locking 00378 // order should be: 00379 // 00380 // outer_channel.lock_and_push 00381 // [outer channel work] 00382 // inner_channel.lock_and_push 00383 // [inner channel work] 00384 // +----------------------------------WAIT----------------------------------+ 00385 // | +----unlock_all_channels----+ | 00386 // | | inner_channel.unlock | | 00387 // | | outer_channel.unlock | | 00388 // | +---------------------------+ | 00389 // | [no lock/no work] | 00390 // | +-------------------------Simulation Kernel-------------------------+ | 00391 // | | acquire kernel lock | | 00392 // | | [kernel work] | | 00393 // | | pthread_cond_wait: release kernel lock | | 00394 // | | [sleep] | | 00395 // | | pthread_cond_wait (upon wakeup): acquire kernel lock | | 00396 // | | [kernel work] | | 00397 // | | release kernel lock | | 00398 // | +-------------------------------------------------------------------+ | 00399 // | [no lock/no work] | 00400 // | +-----lock_all_channels-----+ | 00401 // | | outer_channel.lock | | 00402 // | | inner_channel.lock | | 00403 // | +---------------------------+ | 00404 // +------------------------------------------------------------------------+ 00405 // [inner channel work] 00406 // inner_channel.pop_and_unlock 00407 // [outer channel work] 00408 // outer_channel.pop_and_unlock 00409 // 00410 // (3) When acquiring the channel locks, we may encounter the same lock for 00411 // several times (a channel method calls another one in the same channel). 00412 // But we should encounter them one right after another, so the same lock 00413 // is at the end of the lock queue. If we encounter a lock that is in the 00414 // middle of the queue, then it is a bad coding style and simulation may 00415 // break (meaning an inner channel method calls an outer channel method). 00416 // 00417 // (4) For more information, please refer to the following files: 00418 // sc_method_process.h: 184 (sc_method_process::next_trigger) 00419 // sc_event.cpp: 79 (sc_event::notify) 00420 // 00421 // (02/19/2015 GL) 00422 //------------------------------------------------------------------------------ 00423 inline 00424 void 00425 sc_thread_process::wait( const sc_event& e, int seg_id ) 00426 { 00427 if( m_unwinding ) 00428 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 00429 00430 { 00431 // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock 00432 sc_kernel_lock lock; 00433 00434 #ifdef SC_LOCK_CHECK 00435 assert( sc_get_curr_simcontext()->is_locked_and_owner() ); 00436 #endif /* SC_LOCK_CHECK */ 00437 00438 // 08/14/2015 GL: set the new segment ID of this thread 00439 set_segment_id( seg_id ); 00440 00441 unlock_all_channels(); // 02/16/2015 GL: release all the channel locks 00442 m_event_p = &e; // for cleanup. 00443 e.add_dynamic( this ); 00444 m_trigger_type = EVENT; 00445 suspend_me(); 00446 // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock 00447 } 00448 #ifdef SC_LOCK_CHECK 00449 assert( sc_get_curr_simcontext()->is_not_owner() ); 00450 #endif /* SC_LOCK_CHECK */ 00451 lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks 00452 } 00453 00454 inline 00455 void 00456 sc_thread_process::wait( const sc_event_or_list& el, int seg_id ) 00457 { 00458 if( m_unwinding ) 00459 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 00460 00461 { 00462 // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock 00463 sc_kernel_lock lock; 00464 00465 #ifdef SC_LOCK_CHECK 00466 assert( sc_get_curr_simcontext()->is_locked_and_owner() ); 00467 #endif /* SC_LOCK_CHECK */ 00468 00469 // 08/14/2015 GL: set the new segment ID of this thread 00470 set_segment_id( seg_id ); 00471 00472 unlock_all_channels(); // 02/16/2015 GL: release all the channel locks 00473 el.add_dynamic( this ); 00474 m_event_list_p = ⪙ 00475 m_trigger_type = OR_LIST; 00476 suspend_me(); 00477 // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock 00478 } 00479 #ifdef SC_LOCK_CHECK 00480 assert( sc_get_curr_simcontext()->is_not_owner() ); 00481 #endif /* SC_LOCK_CHECK */ 00482 lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks 00483 } 00484 00485 inline 00486 void 00487 sc_thread_process::wait( const sc_event_and_list& el, int seg_id ) 00488 { 00489 if( m_unwinding ) 00490 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 00491 00492 { 00493 // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock 00494 sc_kernel_lock lock; 00495 00496 #ifdef SC_LOCK_CHECK 00497 assert( sc_get_curr_simcontext()->is_locked_and_owner() ); 00498 #endif /* SC_LOCK_CHECK */ 00499 00500 // 08/14/2015 GL: set the new segment ID of this thread 00501 set_segment_id( seg_id ); 00502 00503 unlock_all_channels(); // 02/16/2015 GL: release all the channel locks 00504 el.add_dynamic( this ); 00505 m_event_list_p = ⪙ 00506 m_event_count = el.size(); 00507 m_trigger_type = AND_LIST; 00508 suspend_me(); 00509 // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock 00510 } 00511 #ifdef SC_LOCK_CHECK 00512 assert( sc_get_curr_simcontext()->is_not_owner() ); 00513 #endif /* SC_LOCK_CHECK */ 00514 lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks 00515 } 00516 00517 inline 00518 void 00519 sc_thread_process::wait( const sc_time& t, int seg_id ) 00520 { 00521 if( m_unwinding ) 00522 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 00523 00524 { 00525 // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock 00526 sc_kernel_lock lock; 00527 00528 #ifdef SC_LOCK_CHECK 00529 assert( sc_get_curr_simcontext()->is_locked_and_owner() ); 00530 #endif /* SC_LOCK_CHECK */ 00531 00532 // 08/14/2015 GL: set the new segment ID of this thread 00533 set_segment_id( seg_id ); 00534 00535 unlock_all_channels(); // 02/16/2015 GL: release all the channel locks 00536 m_timeout_event_p->notify_internal( t ); 00537 m_timeout_event_p->add_dynamic( this ); 00538 m_trigger_type = TIMEOUT; 00539 suspend_me(); 00540 // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock 00541 } 00542 #ifdef SC_LOCK_CHECK 00543 assert( sc_get_curr_simcontext()->is_not_owner() ); 00544 #endif /* SC_LOCK_CHECK */ 00545 lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks 00546 } 00547 00548 inline 00549 void 00550 sc_thread_process::wait( const sc_time& t, const sc_event& e, int seg_id ) 00551 { 00552 if( m_unwinding ) 00553 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 00554 00555 { 00556 // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock 00557 sc_kernel_lock lock; 00558 00559 #ifdef SC_LOCK_CHECK 00560 assert( sc_get_curr_simcontext()->is_locked_and_owner() ); 00561 #endif /* SC_LOCK_CHECK */ 00562 00563 // 08/14/2015 GL: set the new segment ID of this thread 00564 set_segment_id( seg_id ); 00565 00566 unlock_all_channels(); // 02/16/2015 GL: release all the channel locks 00567 m_timeout_event_p->notify_internal( t ); 00568 m_timeout_event_p->add_dynamic( this ); 00569 e.add_dynamic( this ); 00570 m_event_p = &e; 00571 m_trigger_type = EVENT_TIMEOUT; 00572 suspend_me(); 00573 // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock 00574 } 00575 #ifdef SC_LOCK_CHECK 00576 assert( sc_get_curr_simcontext()->is_not_owner() ); 00577 #endif /* SC_LOCK_CHECK */ 00578 lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks 00579 } 00580 00581 inline 00582 void 00583 sc_thread_process::wait( const sc_time& t, const sc_event_or_list& el, int seg_id ) 00584 { 00585 if( m_unwinding ) 00586 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 00587 00588 { 00589 // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock 00590 sc_kernel_lock lock; 00591 00592 #ifdef SC_LOCK_CHECK 00593 assert( sc_get_curr_simcontext()->is_locked_and_owner() ); 00594 #endif /* SC_LOCK_CHECK */ 00595 00596 // 08/14/2015 GL: set the new segment ID of this thread 00597 set_segment_id( seg_id ); 00598 00599 unlock_all_channels(); // 02/16/2015 GL: release all the channel locks 00600 m_timeout_event_p->notify_internal( t ); 00601 m_timeout_event_p->add_dynamic( this ); 00602 el.add_dynamic( this ); 00603 m_event_list_p = ⪙ 00604 m_trigger_type = OR_LIST_TIMEOUT; 00605 suspend_me(); 00606 // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock 00607 } 00608 #ifdef SC_LOCK_CHECK 00609 assert( sc_get_curr_simcontext()->is_not_owner() ); 00610 #endif /* SC_LOCK_CHECK */ 00611 lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks 00612 } 00613 00614 inline 00615 void 00616 sc_thread_process::wait( const sc_time& t, const sc_event_and_list& el, int seg_id ) 00617 { 00618 if( m_unwinding ) 00619 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 00620 00621 { 00622 // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock 00623 sc_kernel_lock lock; 00624 00625 #ifdef SC_LOCK_CHECK 00626 assert( sc_get_curr_simcontext()->is_locked_and_owner() ); 00627 #endif /* SC_LOCK_CHECK */ 00628 00629 // 08/14/2015 GL: set the new segment ID of this thread 00630 set_segment_id( seg_id ); 00631 00632 unlock_all_channels(); // 02/16/2015 GL: release all the channel locks 00633 m_timeout_event_p->notify_internal( t ); 00634 m_timeout_event_p->add_dynamic( this ); 00635 el.add_dynamic( this ); 00636 m_event_list_p = ⪙ 00637 m_event_count = el.size(); 00638 m_trigger_type = AND_LIST_TIMEOUT; 00639 suspend_me(); 00640 // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock 00641 } 00642 #ifdef SC_LOCK_CHECK 00643 assert( sc_get_curr_simcontext()->is_not_owner() ); 00644 #endif /* SC_LOCK_CHECK */ 00645 lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks 00646 } 00647 00648 //------------------------------------------------------------------------------ 00649 //"sc_thread_process::wait_cycles" 00650 // 00651 // This method suspends this object instance for the specified number of cycles. 00652 // A cycle is defined as the event the thread is set up to staticly wait on. 00653 // The field m_wait_cycle_n is set to one less than the number of cycles to 00654 // be waited for, since the value is tested before being decremented in 00655 // the simulation kernel. 00656 //------------------------------------------------------------------------------ 00657 inline 00658 void 00659 sc_thread_process::wait_cycles( int seg_id, int n ) 00660 { 00661 if( m_unwinding ) 00662 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 00663 00664 { 00665 // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock 00666 sc_kernel_lock lock; 00667 00668 #ifdef SC_LOCK_CHECK 00669 assert( sc_get_curr_simcontext()->is_locked_and_owner() ); 00670 #endif /* SC_LOCK_CHECK */ 00671 00672 // 08/14/2015 GL: set the new segment ID of this thread 00673 set_segment_id( seg_id ); 00674 00675 unlock_all_channels(); // 02/16/2015 GL: release all the channel locks 00676 m_wait_cycle_n = n-1; 00677 suspend_me(); 00678 // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock 00679 } 00680 #ifdef SC_LOCK_CHECK 00681 assert( sc_get_curr_simcontext()->is_not_owner() ); 00682 #endif /* SC_LOCK_CHECK */ 00683 lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks 00684 } 00685 00686 //------------------------------------------------------------------------------ 00687 //"sc_thread_process::miscellaneous support" 00688 // 00689 //------------------------------------------------------------------------------ 00690 inline 00691 void sc_thread_process::add_monitor(sc_process_monitor* monitor_p) 00692 { 00693 m_monitor_q.push_back(monitor_p); 00694 } 00695 00696 00697 inline 00698 void sc_thread_process::remove_monitor(sc_process_monitor* monitor_p) 00699 { 00700 int mon_n = m_monitor_q.size(); 00701 00702 for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) 00703 { 00704 if ( m_monitor_q[mon_i] == monitor_p ) 00705 { 00706 m_monitor_q[mon_i] = m_monitor_q[mon_n-1]; 00707 m_monitor_q.resize(mon_n-1); 00708 } 00709 } 00710 } 00711 00712 inline 00713 void sc_thread_process::set_next_exist(sc_thread_handle next_p) 00714 { 00715 m_exist_p = next_p; 00716 } 00717 00718 inline 00719 sc_thread_handle sc_thread_process::next_exist() 00720 { 00721 return (sc_thread_handle)m_exist_p; 00722 } 00723 00724 inline 00725 void sc_thread_process::set_next_runnable(sc_thread_handle next_p) 00726 { 00727 m_runnable_p = next_p; 00728 } 00729 00730 inline 00731 sc_thread_handle sc_thread_process::next_runnable() 00732 { 00733 return (sc_thread_handle)m_runnable_p; 00734 } 00735 00736 //------------------------------------------------------------------------------ 00737 //"sc_thread_process::trigger_static" 00738 // 00739 // This inline method adds the current thread to the queue of runnable 00740 // processes, if required. This is the case if the following criteria 00741 // are met: 00742 // (1) The process is in a runnable state. 00743 // (2) The process is not already on the run queue. 00744 // (3) The process is expecting a static trigger, 00745 // dynamic event waits take priority. 00746 // (4) The process' static wait count is zero. 00747 // 00748 // If the triggering process is the same process, the trigger is 00749 // ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS 00750 // is defined. 00751 //------------------------------------------------------------------------------ 00752 inline 00753 void 00754 // 08/14/2015 GL: add a new parameter to update the local time stamp 00755 //sc_thread_process::trigger_static() 00756 sc_thread_process::trigger_static( sc_event* e ) 00757 { 00758 // 05/05/2015 GL: we may or may not have acquired the kernel lock upon here 00759 // 1) this function is invoked in sc_simcontext::prepare_to_simulate(), 00760 // where the kernel lock is not acquired as it is in the initialization 00761 // phase 00762 // 2) this function is also invoked in sc_event::notify(), where the kernel 00763 // lock is acquired 00764 00765 // No need to try queueing this thread if one of the following is true: 00766 // (a) its disabled 00767 // (b) its already queued for execution 00768 // (c) its waiting on a dynamic event 00769 // (d) its wait count is not satisfied 00770 00771 if ( (m_state & ps_bit_disabled) || is_runnable() || 00772 m_trigger_type != STATIC ) 00773 return; 00774 00775 #if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) 00776 if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) 00777 { 00778 report_immediate_self_notification(); 00779 return; 00780 } 00781 #endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS 00782 00783 if ( m_wait_cycle_n > 0 ) 00784 { 00785 --m_wait_cycle_n; 00786 return; 00787 } 00788 00789 // If we get here then the thread is has satisfied its wait criteria, if 00790 // its suspended mark its state as ready to run. If its not suspended then 00791 // push it onto the runnable queue. 00792 00793 if ( m_state & ps_bit_suspended ) 00794 { 00795 m_state = m_state | ps_bit_ready_to_run; 00796 } 00797 else 00798 { 00799 // 08/14/2015 GL: update the local time stamp of this thread process 00800 sc_timestamp ts = e->get_notify_timestamp(); 00801 switch( e->m_notify_type ) 00802 { 00803 case sc_event::DELTA: // delta notification 00804 set_timestamp( sc_timestamp( ts.get_time_count(), 00805 ts.get_delta_count() + 1 ) ); 00806 break; 00807 case sc_event::TIMED: // timed notification 00808 set_timestamp( ts ); 00809 break; 00810 case sc_event::NONE: 00811 assert( 0 ); // wrong type 00812 } 00813 00814 simcontext()->push_runnable_thread(this); 00815 } 00816 } 00817 00818 #undef DEBUG_MSG 00819 #undef DEBUG_NAME 00820 00821 } // namespace sc_core 00822 00823 // $Log: sc_thread_process.h,v $ 00824 // Revision 1.30 2011/08/26 20:46:11 acg 00825 // Andy Goodrich: moved the modification log to the end of the file to 00826 // eliminate source line number skew when check-ins are done. 00827 // 00828 // Revision 1.29 2011/08/24 23:36:12 acg 00829 // Andy Goodrich: removed break statements that can never be reached and 00830 // which causes warnings in the Greenhills C++ compiler. 00831 // 00832 // Revision 1.28 2011/04/14 22:34:27 acg 00833 // Andy Goodrich: removed dead code. 00834 // 00835 // Revision 1.27 2011/04/13 05:02:18 acg 00836 // Andy Goodrich: added missing check to the wake up code in suspend_me() 00837 // so that we just return if the call to suspend_me() was issued from a 00838 // stack unwinding. 00839 // 00840 // Revision 1.26 2011/04/13 02:44:26 acg 00841 // Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the 00842 // throw status will be set back to THROW_*_RESET if reset is active and 00843 // the check for an unwind being complete was expecting THROW_NONE as the 00844 // clearing of THROW_NOW. 00845 // 00846 // Revision 1.25 2011/04/11 22:05:14 acg 00847 // Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations. 00848 // 00849 // Revision 1.24 2011/04/10 22:12:32 acg 00850 // Andy Goodrich: adding debugging macros. 00851 // 00852 // Revision 1.23 2011/04/08 22:41:28 acg 00853 // Andy Goodrich: added comment pointing to the description of the reset 00854 // mechanism in sc_reset.cpp. 00855 // 00856 // Revision 1.22 2011/04/08 18:27:33 acg 00857 // Andy Goodrich: added check to make sure we don't schedule a running process 00858 // because of it issues a notify() it is sensitive to. 00859 // 00860 // Revision 1.21 2011/04/05 06:22:38 acg 00861 // Andy Goodrich: expanded comment for trigger_static() initial vetting. 00862 // 00863 // Revision 1.20 2011/04/01 21:24:57 acg 00864 // Andy Goodrich: removed unused code. 00865 // 00866 // Revision 1.19 2011/02/19 08:30:53 acg 00867 // Andy Goodrich: Moved process queueing into trigger_static from 00868 // sc_event::notify. 00869 // 00870 // Revision 1.18 2011/02/18 20:27:14 acg 00871 // Andy Goodrich: Updated Copyrights. 00872 // 00873 // Revision 1.17 2011/02/17 19:55:58 acg 00874 // Andy Goodrich: 00875 // (1) Changed signature of trigger_dynamic() back to a bool. 00876 // (2) Simplified process control usage. 00877 // (3) Changed trigger_static() to recognize process controls and to 00878 // do the down-count on wait(N), allowing the elimination of 00879 // ready_to_run(). 00880 // 00881 // Revision 1.16 2011/02/16 22:37:31 acg 00882 // Andy Goodrich: clean up to remove need for ps_disable_pending. 00883 // 00884 // Revision 1.15 2011/02/13 21:47:38 acg 00885 // Andy Goodrich: update copyright notice. 00886 // 00887 // Revision 1.14 2011/02/13 21:35:54 acg 00888 // Andy Goodrich: added error for performing a wait() during unwinding. 00889 // 00890 // Revision 1.13 2011/02/11 13:25:24 acg 00891 // Andy Goodrich: Philipp A. Hartmann's changes: 00892 // (1) Removal of SC_CTHREAD method overloads. 00893 // (2) New exception processing code. 00894 // 00895 // Revision 1.12 2011/02/01 23:01:53 acg 00896 // Andy Goodrich: removed dead code. 00897 // 00898 // Revision 1.11 2011/02/01 21:18:01 acg 00899 // Andy Goodrich: 00900 // (1) Changes in throw processing for new process control rules. 00901 // (2) Support of new process_state enum values. 00902 // 00903 // Revision 1.10 2011/01/25 20:50:37 acg 00904 // Andy Goodrich: changes for IEEE 1666 2011. 00905 // 00906 // Revision 1.9 2011/01/19 23:21:50 acg 00907 // Andy Goodrich: changes for IEEE 1666 2011 00908 // 00909 // Revision 1.8 2011/01/18 20:10:45 acg 00910 // Andy Goodrich: changes for IEEE1666_2011 semantics. 00911 // 00912 // Revision 1.7 2011/01/06 17:59:58 acg 00913 // Andy Goodrich: removed debugging output. 00914 // 00915 // Revision 1.6 2010/07/22 20:02:33 acg 00916 // Andy Goodrich: bug fixes. 00917 // 00918 // Revision 1.5 2009/07/28 01:10:53 acg 00919 // Andy Goodrich: updates for 2.3 release candidate. 00920 // 00921 // Revision 1.4 2009/05/22 16:06:29 acg 00922 // Andy Goodrich: process control updates. 00923 // 00924 // Revision 1.3 2009/03/12 22:59:58 acg 00925 // Andy Goodrich: updates for 2.4 stuff. 00926 // 00927 // Revision 1.2 2008/05/22 17:06:06 acg 00928 // Andy Goodrich: formatting and comments. 00929 // 00930 // Revision 1.1.1.1 2006/12/15 20:20:05 acg 00931 // SystemC 2.3 00932 // 00933 // Revision 1.7 2006/05/08 17:57:13 acg 00934 // Andy Goodrich: Added David Long's forward declarations for friend functions 00935 // to keep the Microsoft C++ compiler happy. 00936 // 00937 // Revision 1.6 2006/04/20 17:08:17 acg 00938 // Andy Goodrich: 3.0 style process changes. 00939 // 00940 // Revision 1.5 2006/04/11 23:13:21 acg 00941 // Andy Goodrich: Changes for reduced reset support that only includes 00942 // sc_cthread, but has preliminary hooks for expanding to method and thread 00943 // processes also. 00944 // 00945 // Revision 1.4 2006/01/24 20:49:05 acg 00946 // Andy Goodrich: changes to remove the use of deprecated features within the 00947 // simulator, and to issue warning messages when deprecated features are used. 00948 // 00949 // Revision 1.3 2006/01/13 18:44:30 acg 00950 // Added $Log to record CVS changes into the source. 00951 00952 #endif // !defined(sc_thread_process_h_INCLUDED)