1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 sc_thread_process.h -- Thread process declarations 23 24 Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 25 26 27 CHANGE LOG AT THE END OF THE FILE 28 *****************************************************************************/ 29 30 31#if !defined(sc_thread_process_h_INCLUDED) 32#define sc_thread_process_h_INCLUDED 33 34#include "sysc/kernel/sc_spawn_options.h" 35#include "sysc/kernel/sc_process.h" 36#include "sysc/kernel/sc_cor.h" 37#include "sysc/kernel/sc_event.h" 38#include "sysc/kernel/sc_except.h" 39#include "sysc/kernel/sc_reset.h" 40 41// DEBUGGING MACROS: 42// 43// DEBUG_MSG(NAME,P,MSG) 44// MSG = message to print 45// NAME = name that must match the process for the message to print, or 46// null if the message should be printed unconditionally. 47// P = pointer to process message is for, or NULL in which case the 48// message will not print. 49#if 0 50# define DEBUG_NAME "" 51# define DEBUG_MSG(NAME,P,MSG) \ 52 { \ 53 if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ 54 std::cout << "**** " << sc_time_stamp() << " (" \ 55 << sc_get_current_process_name() << "): " << MSG \ 56 << " - " << P->name() << std::endl; \ 57 } 58#else 59# define DEBUG_MSG(NAME,P,MSG) 60#endif 61 62 63namespace sc_core { 64 65// forward references: 66class sc_event_and_list; 67class sc_event_or_list; 68class sc_reset; 69void sc_thread_cor_fn( void* ); 70void sc_set_stack_size( sc_thread_handle, std::size_t ); 71class sc_event; 72class sc_join; 73class sc_module; 74class sc_process_handle; 75class sc_process_table; 76class sc_simcontext; 77class sc_runnable; 78 79sc_cor* get_cor_pointer( sc_process_b* process_p ); 80void sc_set_stack_size( sc_thread_handle thread_h, std::size_t size ); 81void wait( sc_simcontext* ); 82void wait( const sc_event&, sc_simcontext* ); 83void wait( const sc_event_or_list&, sc_simcontext* ); 84void wait( const sc_event_and_list&, sc_simcontext* ); 85void wait( const sc_time&, sc_simcontext* ); 86void wait( const sc_time&, const sc_event&, sc_simcontext* ); 87void wait( const sc_time&, const sc_event_or_list&, sc_simcontext* ); 88void wait( const sc_time&, const sc_event_and_list&, sc_simcontext* ); 89 90//============================================================================== 91// sc_thread_process - 92// 93//============================================================================== 94class sc_thread_process : public sc_process_b { 95 friend void sc_thread_cor_fn( void* ); 96 friend void sc_set_stack_size( sc_thread_handle, std::size_t ); 97 friend class sc_event; 98 friend class sc_join; 99 friend class sc_module; 100 friend class sc_process_b; 101 friend class sc_process_handle; 102 friend class sc_process_table; 103 friend class sc_simcontext; 104 friend class sc_runnable; 105 friend sc_cor* get_cor_pointer( sc_process_b* process_p ); 106 107 friend void wait( sc_simcontext* ); 108 friend void wait( const sc_event&, sc_simcontext* ); 109 friend void wait( const sc_event_or_list&, sc_simcontext* ); 110 friend void wait( const sc_event_and_list&, sc_simcontext* ); 111 friend void wait( const sc_time&, sc_simcontext* ); 112 friend void wait( const sc_time&, const sc_event&, sc_simcontext* ); 113 friend void wait( const sc_time&, const sc_event_or_list&, sc_simcontext* ); 114 friend void wait( const sc_time&, const sc_event_and_list&, sc_simcontext*); 115 public: 116 sc_thread_process( const char* name_p, bool free_host, 117 SC_ENTRY_FUNC method_p, sc_process_host* host_p, 118 const sc_spawn_options* opt_p ); 119 120 virtual const char* kind() const 121 { return "sc_thread_process"; } 122 123 protected: 124 // may not be deleted manually (called from sc_process_b) 125 virtual ~sc_thread_process(); 126 127 virtual void disable_process( 128 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 129 virtual void enable_process( 130 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 131 virtual void kill_process( 132 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 133 sc_thread_handle next_exist(); 134 sc_thread_handle next_runnable(); 135 virtual void prepare_for_simulation(); 136 virtual void resume_process( 137 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 138 void set_next_exist( sc_thread_handle next_p ); 139 void set_next_runnable( sc_thread_handle next_p ); 140 141 void set_stack_size( std::size_t size ); 142 inline void suspend_me(); 143 virtual void suspend_process( 144 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 145 virtual void throw_reset( bool async ); 146 virtual void throw_user( const sc_throw_it_helper& helper, 147 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); 148 149 bool trigger_dynamic( sc_event* ); 150 inline void trigger_static(); 151 152 void wait( const sc_event& ); 153 void wait( const sc_event_or_list& ); 154 void wait( const sc_event_and_list& ); 155 void wait( const sc_time& ); 156 void wait( const sc_time&, const sc_event& ); 157 void wait( const sc_time&, const sc_event_or_list& ); 158 void wait( const sc_time&, const sc_event_and_list& ); 159 void wait_cycles( int n=1 ); 160 161 protected: 162 void add_monitor( sc_process_monitor* monitor_p ); 163 void remove_monitor( sc_process_monitor* monitor_p); 164 void signal_monitors( int type = 0 ); 165 166 protected: 167 sc_cor* m_cor_p; // Thread's coroutine. 168 std::vector<sc_process_monitor*> m_monitor_q; // Thread monitors. 169 std::size_t m_stack_size; // Thread stack size. 170 int m_wait_cycle_n; // # of waits to be done. 171 172 private: // disabled 173 sc_thread_process( const sc_thread_process& ); 174 const sc_thread_process& operator = ( const sc_thread_process& ); 175 176}; 177 178//------------------------------------------------------------------------------ 179//"sc_thread_process::set_stack_size" 180// 181//------------------------------------------------------------------------------ 182inline void sc_thread_process::set_stack_size( std::size_t size ) 183{ 184 assert( size ); 185 m_stack_size = size; 186} 187 188//------------------------------------------------------------------------------ 189//"sc_thread_process::suspend_me" 190// 191// This method suspends this object instance in favor of the next runnable 192// process. Upon awakening we check to see if an exception should be thrown. 193// There are two types of exceptions that can be thrown, synchronous reset 194// and asynchronous reset. At a future time there may be more asynchronous 195// exceptions. If an asynchronous reset is seen and there is not static reset 196// specified, or the static reset is not active then clear the throw 197// type for the next time this method is called. 198// 199// Notes: 200// (1) For an explanation of how the reset mechanism works see the top of 201// the file sc_reset.cpp. 202// (2) The m_sticky_reset field is used to handle synchronous resets that 203// are enabled via the sc_process_handle::sync_reset_on() method. These 204// resets are not generated by a signal, but rather are modal by 205// method call: sync_reset_on() - sync_reset_off(). 206//------------------------------------------------------------------------------ 207inline void sc_thread_process::suspend_me() 208{ 209 // remember, if we're currently unwinding 210 211 bool unwinding_preempted = m_unwinding; 212 213 sc_simcontext* simc_p = simcontext(); 214 sc_cor* cor_p = simc_p->next_cor(); 215 216 // do not switch, if we're about to execute next (e.g. suicide) 217 218 if( m_cor_p != cor_p ) 219 { 220 DEBUG_MSG( DEBUG_NAME , this, "suspending thread"); 221 simc_p->cor_pkg()->yield( cor_p ); 222 DEBUG_MSG( DEBUG_NAME , this, "resuming thread"); 223 } 224 225 // IF THERE IS A THROW TO BE DONE FOR THIS PROCESS DO IT NOW: 226 // 227 // (1) Optimize THROW_NONE for speed as it is the normal case. 228 // (2) If this thread is already unwinding then suspend_me() was 229 // called from the catch clause to throw an exception on another 230 // process, so just go back to the catch clause. 231 232 if ( m_throw_status == THROW_NONE ) return; 233 234 if ( m_unwinding ) return; 235 236 switch( m_throw_status ) 237 { 238 case THROW_ASYNC_RESET: 239 case THROW_SYNC_RESET: 240 DEBUG_MSG( DEBUG_NAME , this, "throwing reset for"); 241 if ( m_reset_event_p ) m_reset_event_p->notify(); 242 throw sc_unwind_exception( this, true ); 243 244 case THROW_USER: 245 DEBUG_MSG( DEBUG_NAME, this, "invoking throw_it for"); 246 m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET : 247 (m_active_reset_n ? THROW_SYNC_RESET : 248 THROW_NONE); 249 m_throw_helper_p->throw_it(); 250 break; 251 252 case THROW_KILL: 253 DEBUG_MSG( DEBUG_NAME, this, "throwing kill for"); 254 throw sc_unwind_exception( this, false ); 255 256 default: // THROWING_NOW 257 sc_assert( unwinding_preempted ); 258 DEBUG_MSG( DEBUG_NAME, this, "restarting thread"); 259 break; 260 } 261} 262 263 264//------------------------------------------------------------------------------ 265//"sc_thread_process::wait" 266// 267//------------------------------------------------------------------------------ 268inline 269void 270sc_thread_process::wait( const sc_event& e ) 271{ 272 if( m_unwinding ) 273 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 274 275 m_event_p = &e; // for cleanup. 276 e.add_dynamic( this ); 277 m_trigger_type = EVENT; 278 suspend_me(); 279} 280 281inline 282void 283sc_thread_process::wait( const sc_event_or_list& el ) 284{ 285 if( m_unwinding ) 286 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 287 288 el.add_dynamic( this ); 289 m_event_list_p = ⪙ 290 m_trigger_type = OR_LIST; 291 suspend_me(); 292} 293 294inline 295void 296sc_thread_process::wait( const sc_event_and_list& el ) 297{ 298 if( m_unwinding ) 299 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 300 301 el.add_dynamic( this ); 302 m_event_list_p = ⪙ 303 m_event_count = el.size(); 304 m_trigger_type = AND_LIST; 305 suspend_me(); 306} 307 308inline 309void 310sc_thread_process::wait( const sc_time& t ) 311{ 312 if( m_unwinding ) 313 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 314 315 m_timeout_event_p->notify_internal( t ); 316 m_timeout_event_p->add_dynamic( this ); 317 m_trigger_type = TIMEOUT; 318 suspend_me(); 319} 320 321inline 322void 323sc_thread_process::wait( const sc_time& t, const sc_event& e ) 324{ 325 if( m_unwinding ) 326 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 327 328 m_timeout_event_p->notify_internal( t ); 329 m_timeout_event_p->add_dynamic( this ); 330 e.add_dynamic( this ); 331 m_event_p = &e; 332 m_trigger_type = EVENT_TIMEOUT; 333 suspend_me(); 334} 335 336inline 337void 338sc_thread_process::wait( const sc_time& t, const sc_event_or_list& el ) 339{ 340 if( m_unwinding ) 341 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 342 343 m_timeout_event_p->notify_internal( t ); 344 m_timeout_event_p->add_dynamic( this ); 345 el.add_dynamic( this ); 346 m_event_list_p = ⪙ 347 m_trigger_type = OR_LIST_TIMEOUT; 348 suspend_me(); 349} 350 351inline 352void 353sc_thread_process::wait( const sc_time& t, const sc_event_and_list& el ) 354{ 355 if( m_unwinding ) 356 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 357 358 m_timeout_event_p->notify_internal( t ); 359 m_timeout_event_p->add_dynamic( this ); 360 el.add_dynamic( this ); 361 m_event_list_p = ⪙ 362 m_event_count = el.size(); 363 m_trigger_type = AND_LIST_TIMEOUT; 364 suspend_me(); 365} 366 367//------------------------------------------------------------------------------ 368//"sc_thread_process::wait_cycles" 369// 370// This method suspends this object instance for the specified number of cycles. 371// A cycle is defined as the event the thread is set up to staticly wait on. 372// The field m_wait_cycle_n is set to one less than the number of cycles to 373// be waited for, since the value is tested before being decremented in 374// the simulation kernel. 375//------------------------------------------------------------------------------ 376inline 377void 378sc_thread_process::wait_cycles( int n ) 379{ 380 if( m_unwinding ) 381 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); 382 383 m_wait_cycle_n = n-1; 384 suspend_me(); 385} 386 387//------------------------------------------------------------------------------ 388//"sc_thread_process::miscellaneous support" 389// 390//------------------------------------------------------------------------------ 391inline 392void sc_thread_process::add_monitor(sc_process_monitor* monitor_p) 393{ 394 m_monitor_q.push_back(monitor_p); 395} 396 397 398inline 399void sc_thread_process::remove_monitor(sc_process_monitor* monitor_p) 400{ 401 int mon_n = m_monitor_q.size(); 402 403 for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) 404 { 405 if ( m_monitor_q[mon_i] == monitor_p ) 406 { 407 m_monitor_q[mon_i] = m_monitor_q[mon_n-1]; 408 m_monitor_q.resize(mon_n-1); 409 } 410 } 411} 412 413inline 414void sc_thread_process::set_next_exist(sc_thread_handle next_p) 415{ 416 m_exist_p = next_p; 417} 418 419inline 420sc_thread_handle sc_thread_process::next_exist() 421{ 422 return (sc_thread_handle)m_exist_p; 423} 424 425inline 426void sc_thread_process::set_next_runnable(sc_thread_handle next_p) 427{ 428 m_runnable_p = next_p; 429} 430 431inline 432sc_thread_handle sc_thread_process::next_runnable() 433{ 434 return (sc_thread_handle)m_runnable_p; 435} 436 437inline sc_cor* get_cor_pointer( sc_process_b* process_p ) 438{ 439 sc_thread_handle thread_p = DCAST<sc_thread_handle>(process_p); 440 return thread_p->m_cor_p; 441} 442 443//------------------------------------------------------------------------------ 444//"sc_thread_process::trigger_static" 445// 446// This inline method adds the current thread to the queue of runnable 447// processes, if required. This is the case if the following criteria 448// are met: 449// (1) The process is in a runnable state. 450// (2) The process is not already on the run queue. 451// (3) The process is expecting a static trigger, 452// dynamic event waits take priority. 453// (4) The process' static wait count is zero. 454// 455// If the triggering process is the same process, the trigger is 456// ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS 457// is defined. 458//------------------------------------------------------------------------------ 459inline 460void 461sc_thread_process::trigger_static() 462{ 463 // No need to try queueing this thread if one of the following is true: 464 // (a) its disabled 465 // (b) its already queued for execution 466 // (c) its waiting on a dynamic event 467 // (d) its wait count is not satisfied 468 469 if ( (m_state & ps_bit_disabled) || is_runnable() || 470 m_trigger_type != STATIC ) 471 return; 472 473#if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) 474 if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) 475 { 476 report_immediate_self_notification(); 477 return; 478 } 479#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS 480 481 if ( m_wait_cycle_n > 0 ) 482 { 483 --m_wait_cycle_n; 484 return; 485 } 486 487 // If we get here then the thread is has satisfied its wait criteria, if 488 // its suspended mark its state as ready to run. If its not suspended then 489 // push it onto the runnable queue. 490 491 if ( m_state & ps_bit_suspended ) 492 { 493 m_state = m_state | ps_bit_ready_to_run; 494 } 495 else 496 { 497 simcontext()->push_runnable_thread(this); 498 } 499} 500 501#undef DEBUG_MSG 502#undef DEBUG_NAME 503 504} // namespace sc_core 505 506// $Log: sc_thread_process.h,v $ 507// Revision 1.30 2011/08/26 20:46:11 acg 508// Andy Goodrich: moved the modification log to the end of the file to 509// eliminate source line number skew when check-ins are done. 510// 511// Revision 1.29 2011/08/24 23:36:12 acg 512// Andy Goodrich: removed break statements that can never be reached and 513// which causes warnings in the Greenhills C++ compiler. 514// 515// Revision 1.28 2011/04/14 22:34:27 acg 516// Andy Goodrich: removed dead code. 517// 518// Revision 1.27 2011/04/13 05:02:18 acg 519// Andy Goodrich: added missing check to the wake up code in suspend_me() 520// so that we just return if the call to suspend_me() was issued from a 521// stack unwinding. 522// 523// Revision 1.26 2011/04/13 02:44:26 acg 524// Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the 525// throw status will be set back to THROW_*_RESET if reset is active and 526// the check for an unwind being complete was expecting THROW_NONE as the 527// clearing of THROW_NOW. 528// 529// Revision 1.25 2011/04/11 22:05:14 acg 530// Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations. 531// 532// Revision 1.24 2011/04/10 22:12:32 acg 533// Andy Goodrich: adding debugging macros. 534// 535// Revision 1.23 2011/04/08 22:41:28 acg 536// Andy Goodrich: added comment pointing to the description of the reset 537// mechanism in sc_reset.cpp. 538// 539// Revision 1.22 2011/04/08 18:27:33 acg 540// Andy Goodrich: added check to make sure we don't schedule a running process 541// because of it issues a notify() it is sensitive to. 542// 543// Revision 1.21 2011/04/05 06:22:38 acg 544// Andy Goodrich: expanded comment for trigger_static() initial vetting. 545// 546// Revision 1.20 2011/04/01 21:24:57 acg 547// Andy Goodrich: removed unused code. 548// 549// Revision 1.19 2011/02/19 08:30:53 acg 550// Andy Goodrich: Moved process queueing into trigger_static from 551// sc_event::notify. 552// 553// Revision 1.18 2011/02/18 20:27:14 acg 554// Andy Goodrich: Updated Copyrights. 555// 556// Revision 1.17 2011/02/17 19:55:58 acg 557// Andy Goodrich: 558// (1) Changed signature of trigger_dynamic() back to a bool. 559// (2) Simplified process control usage. 560// (3) Changed trigger_static() to recognize process controls and to 561// do the down-count on wait(N), allowing the elimination of 562// ready_to_run(). 563// 564// Revision 1.16 2011/02/16 22:37:31 acg 565// Andy Goodrich: clean up to remove need for ps_disable_pending. 566// 567// Revision 1.15 2011/02/13 21:47:38 acg 568// Andy Goodrich: update copyright notice. 569// 570// Revision 1.14 2011/02/13 21:35:54 acg 571// Andy Goodrich: added error for performing a wait() during unwinding. 572// 573// Revision 1.13 2011/02/11 13:25:24 acg 574// Andy Goodrich: Philipp A. Hartmann's changes: 575// (1) Removal of SC_CTHREAD method overloads. 576// (2) New exception processing code. 577// 578// Revision 1.12 2011/02/01 23:01:53 acg 579// Andy Goodrich: removed dead code. 580// 581// Revision 1.11 2011/02/01 21:18:01 acg 582// Andy Goodrich: 583// (1) Changes in throw processing for new process control rules. 584// (2) Support of new process_state enum values. 585// 586// Revision 1.10 2011/01/25 20:50:37 acg 587// Andy Goodrich: changes for IEEE 1666 2011. 588// 589// Revision 1.9 2011/01/19 23:21:50 acg 590// Andy Goodrich: changes for IEEE 1666 2011 591// 592// Revision 1.8 2011/01/18 20:10:45 acg 593// Andy Goodrich: changes for IEEE1666_2011 semantics. 594// 595// Revision 1.7 2011/01/06 17:59:58 acg 596// Andy Goodrich: removed debugging output. 597// 598// Revision 1.6 2010/07/22 20:02:33 acg 599// Andy Goodrich: bug fixes. 600// 601// Revision 1.5 2009/07/28 01:10:53 acg 602// Andy Goodrich: updates for 2.3 release candidate. 603// 604// Revision 1.4 2009/05/22 16:06:29 acg 605// Andy Goodrich: process control updates. 606// 607// Revision 1.3 2009/03/12 22:59:58 acg 608// Andy Goodrich: updates for 2.4 stuff. 609// 610// Revision 1.2 2008/05/22 17:06:06 acg 611// Andy Goodrich: formatting and comments. 612// 613// Revision 1.1.1.1 2006/12/15 20:20:05 acg 614// SystemC 2.3 615// 616// Revision 1.7 2006/05/08 17:57:13 acg 617// Andy Goodrich: Added David Long's forward declarations for friend functions 618// to keep the Microsoft C++ compiler happy. 619// 620// Revision 1.6 2006/04/20 17:08:17 acg 621// Andy Goodrich: 3.0 style process changes. 622// 623// Revision 1.5 2006/04/11 23:13:21 acg 624// Andy Goodrich: Changes for reduced reset support that only includes 625// sc_cthread, but has preliminary hooks for expanding to method and thread 626// processes also. 627// 628// Revision 1.4 2006/01/24 20:49:05 acg 629// Andy Goodrich: changes to remove the use of deprecated features within the 630// simulator, and to issue warning messages when deprecated features are used. 631// 632// Revision 1.3 2006/01/13 18:44:30 acg 633// Added $Log to record CVS changes into the source. 634 635#endif // !defined(sc_thread_process_h_INCLUDED) 636