SystemC  Recoding Infrastructure for SystemC v0.6.0 derived from Accellera SystemC 2.3.1
Accellera SystemC proof-of-concept library
sc_thread_process.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  The following code is derived, directly or indirectly, from the SystemC
4  source code Copyright (c) 1996-2014 by all Contributors.
5  All Rights reserved.
6 
7  The contents of this file are subject to the restrictions and limitations
8  set forth in the SystemC Open Source License (the "License");
9  You may not use this file except in compliance with such restrictions and
10  limitations. You may obtain instructions on how to receive a copy of the
11  License at http://www.accellera.org/. Software distributed by Contributors
12  under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
13  ANY KIND, either express or implied. See the License for the specific
14  language governing rights and limitations under the License.
15 
16  *****************************************************************************/
17 
18 /*****************************************************************************
19 
20  sc_thread_process.h -- Thread process declarations
21 
22  Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005
23 
24 
25  CHANGE LOG AT THE END OF THE FILE
26  *****************************************************************************/
27 
28 
29 #if !defined(sc_thread_process_h_INCLUDED)
30 #define sc_thread_process_h_INCLUDED
31 
33 #include "sysc/kernel/sc_process.h"
34 #include "sysc/kernel/sc_cor.h"
35 #include "sysc/kernel/sc_event.h"
36 #include "sysc/kernel/sc_except.h"
37 #include "sysc/kernel/sc_reset.h"
38 
39 // DEBUGGING MACROS:
40 //
41 // DEBUG_MSG(NAME,P,MSG)
42 // MSG = message to print
43 // NAME = name that must match the process for the message to print, or
44 // null if the message should be printed unconditionally.
45 // P = pointer to process message is for, or NULL in which case the
46 // message will not print.
47 #if 0
48 # define DEBUG_NAME ""
49 # define DEBUG_MSG(NAME,P,MSG) \
50  { \
51  if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \
52  std::cout << "**** " << sc_time_stamp() << " (" \
53  << sc_get_current_process_name() << "): " << MSG \
54  << " - " << P->name() << std::endl; \
55  }
56 #else
57 # define DEBUG_MSG(NAME,P,MSG)
58 #endif
59 
60 // 02/22/2016 ZC: to enable verbose display or not
61 #ifndef _SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR
62 #define _SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR "SYSC_PRINT_VERBOSE_MESSAGE"
63 #endif
64 namespace sc_core {
65 
66 // forward references:
67 class sc_event_and_list;
68 class sc_event_or_list;
69 class sc_reset;
70 void sc_thread_cor_fn( void* );
71 void sc_set_stack_size( sc_thread_handle, std::size_t );
72 class sc_event;
73 class sc_join;
74 class sc_module;
75 class sc_process_handle;
76 class sc_process_table;
77 class sc_simcontext;
78 class sc_runnable;
79 
80 class Invoker; //DM 05/16/2019
81 
82 sc_cor* get_cor_pointer( sc_process_b* process_p );
83 void sc_set_stack_size( sc_thread_handle thread_h, std::size_t size );
84 void wait( int , sc_simcontext* );
85 void wait( const sc_event&, int , sc_simcontext* );
86 void wait( const sc_event_or_list&, int , sc_simcontext* );
87 void wait( const sc_event_and_list&, int , sc_simcontext* );
88 void wait( const sc_time&, int , sc_simcontext* );
89 void wait( const sc_time&, const sc_event&, int , sc_simcontext* );
90 void wait( const sc_time&, const sc_event_or_list&, int , sc_simcontext* );
91 void wait( const sc_time&, const sc_event_and_list&, int , sc_simcontext* );
92 
93 /**************************************************************************/
99  friend void sc_thread_cor_fn( void* );
100  friend void sc_set_stack_size( sc_thread_handle, std::size_t );
101  friend class sc_event;
102  friend class sc_join;
103  friend class sc_module;
104 
105  // 04/07/2015 GL: a new sc_channel class is derived from sc_module
106  friend class sc_channel;
107 
108  friend class sc_process_b;
109  friend class sc_process_handle;
110  friend class sc_process_table;
111  friend class sc_simcontext;
112  friend class sc_runnable;
113  friend sc_cor* get_cor_pointer( sc_process_b* process_p );
114 
115  friend class Invoker; //DM 05/16/2019
116 
117  // 06/12/2015 GL: modified for the OoO simulation
118  friend void wait( int , sc_simcontext* );
119  friend void wait( const sc_event&, int , sc_simcontext* );
120  friend void wait( const sc_event_or_list&, int , sc_simcontext* );
121  friend void wait( const sc_event_and_list&, int , sc_simcontext* );
122  friend void wait( const sc_time&, int , sc_simcontext* );
123  friend void wait( const sc_time&, const sc_event&, int , sc_simcontext* );
124  friend void wait( const sc_time&, const sc_event_or_list&, int ,
125  sc_simcontext* );
126  friend void wait( const sc_time&, const sc_event_and_list&, int ,
127  sc_simcontext*);
128 
129  public:
130 
133  sc_thread_process( const char* name_p, bool free_host,
134  SC_ENTRY_FUNC method_p, sc_process_host* host_p,
135  const sc_spawn_options* opt_p );
136 
137  virtual const char* kind() const
138  { return "sc_thread_process"; }
139 
140  void aux_boundary();
141  protected:
142  // may not be deleted manually (called from sc_process_b)
143  virtual ~sc_thread_process();
144 
145  virtual void disable_process(
147  virtual void enable_process(
149  virtual void kill_process(
153  virtual void prepare_for_simulation();
154  virtual void resume_process(
156  void set_next_exist( sc_thread_handle next_p );
157  void set_next_runnable( sc_thread_handle next_p );
158 
159  void set_stack_size( std::size_t size );
160  inline void suspend_me();
161  virtual void suspend_process(
163  virtual void throw_reset( bool async );
164  virtual void throw_user( const sc_throw_it_helper& helper,
166 
167  bool trigger_dynamic( sc_event*, bool& );
168  bool deliver_event_at_time( sc_event* e, sc_timestamp e_delivery_time );
169 
174  // 08/14/2015 GL: add a new parameter to update the local time stamp
175  //inline void trigger_static();
176  inline void trigger_static( sc_event* );
177 
178 
179 
184  // 06/12/2015 GL: modified for the OoO simulation
185  void wait( const sc_event&, int = -1 );
186 
191  // 06/12/2015 GL: modified for the OoO simulation
192  void wait( const sc_event_or_list&, int = -1 );
193 
198  // 06/12/2015 GL: modified for the OoO simulation
199  void wait( const sc_event_and_list&, int = -1 );
200 
205  // 06/12/2015 GL: modified for the OoO simulation
206  void wait( const sc_time&, int = -1 );
207 
212  // 06/12/2015 GL: modified for the OoO simulation
213  void wait( const sc_time&, const sc_event&, int = -1 );
214 
219  // 06/12/2015 GL: modified for the OoO simulation
220  void wait( const sc_time&, const sc_event_or_list&, int = -1 );
221 
226  // 06/12/2015 GL: modified for the OoO simulation
227  void wait( const sc_time&, const sc_event_and_list&, int = -1 );
228 
233  // 06/12/2015 GL: modified for the OoO simulation
234  void wait_cycles( int, int n=1 );
235 
236  protected:
237  void add_monitor( sc_process_monitor* monitor_p );
238  void remove_monitor( sc_process_monitor* monitor_p);
239  void signal_monitors( int type = 0 );
240 
241  protected:
242  sc_cor* m_cor_p; // Thread's coroutine.
243  std::vector<sc_process_monitor*> m_monitor_q; // Thread monitors.
244  std::size_t m_stack_size; // Thread stack size.
245  int m_wait_cycle_n; // # of waits to be done.
246 
247  private: // disabled
249  const sc_thread_process& operator = ( const sc_thread_process& );
250 
251 };
252 
253 //------------------------------------------------------------------------------
254 //"sc_thread_process::set_stack_size"
255 //
256 //------------------------------------------------------------------------------
257 inline void sc_thread_process::set_stack_size( std::size_t size )
258 {
259  assert( size );
260  m_stack_size = size;
261 }
262 
263 //------------------------------------------------------------------------------
264 //"sc_thread_process::suspend_me"
265 //
266 // This method suspends this object instance in favor of the next runnable
267 // process. Upon awakening we check to see if an exception should be thrown.
268 // There are two types of exceptions that can be thrown, synchronous reset
269 // and asynchronous reset. At a future time there may be more asynchronous
270 // exceptions. If an asynchronous reset is seen and there is not static reset
271 // specified, or the static reset is not active then clear the throw
272 // type for the next time this method is called.
273 //
274 // Notes:
275 // (1) For an explanation of how the reset mechanism works see the top of
276 // the file sc_reset.cpp.
277 // (2) The m_sticky_reset field is used to handle synchronous resets that
278 // are enabled via the sc_process_handle::sync_reset_on() method. These
279 // resets are not generated by a signal, but rather are modal by
280 // method call: sync_reset_on() - sync_reset_off().
281 //------------------------------------------------------------------------------
283 {
284  // 11/21/2014 GL: assume we have acquired the kernel lock upon here
285 #ifdef SC_LOCK_CHECK
286  assert( sc_get_curr_simcontext()->is_locked_and_owner() );
287 #endif /* SC_LOCK_CHECK */
288 
289  // remember, if we're currently unwinding
290 
291  bool unwinding_preempted = m_unwinding;
292 
293  sc_simcontext* simc_p = simcontext();
294  //sc_cor* cor_p = simc_p->next_cor();
295 
296  simc_p->remove_running_process( (sc_process_b*)this );
297 
298  //the following code should not be here, because suspend_me only removes
299  //a process from running queue
300  //put it into waiting queue and set its state 10:23 2017/3/10 ZC
301  //simc_p->add_to_wait_queue( (sc_process_b*)this );
302  //this->m_process_state=12;
303 
304  //printf("calling oooschedule() from process %s",this->process_name);
305  // simc_p->schedule( m_cor_p );
306  // if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
307  // printf("%s is calling suspend_me()\n",this->name());
308  simc_p->oooschedule( m_cor_p ); // 08/19/2015 GL: OoO scheduling
309 
310  // do not switch, if we're about to execute next (e.g. suicide)
311 
312  //if( m_cor_p != cor_p )
313  //{
314  // DEBUG_MSG( DEBUG_NAME , this, "suspending thread");
315  // simc_p->cor_pkg()->yield( cor_p );
316  // DEBUG_MSG( DEBUG_NAME , this, "resuming thread");
317  //}
318 
319  // if I am not scheduled to execute again
320  if ( !simc_p->is_running_process( (sc_process_b*)this ) )
321  {
322  DEBUG_MSG( DEBUG_NAME , this, "suspending thread");
323  simc_p->suspend_cor( m_cor_p );
324  DEBUG_MSG( DEBUG_NAME , this, "resuming thread");
325  }
326 
327  // IF THERE IS A THROW TO BE DONE FOR THIS PROCESS DO IT NOW:
328  //
329  // (1) Optimize THROW_NONE for speed as it is the normal case.
330  // (2) If this thread is already unwinding then suspend_me() was
331  // called from the catch clause to throw an exception on another
332  // process, so just go back to the catch clause.
333 
334  if ( m_throw_status == THROW_NONE ) return;
335 
336  if ( m_unwinding ) return;
337 
338  switch( m_throw_status )
339  {
340  case THROW_ASYNC_RESET:
341  case THROW_SYNC_RESET:
342  DEBUG_MSG( DEBUG_NAME , this, "throwing reset for");
344  throw sc_unwind_exception( this, true );
345 
346  case THROW_USER:
347  DEBUG_MSG( DEBUG_NAME, this, "invoking throw_it for");
350  THROW_NONE);
352  break;
353 
354  case THROW_KILL:
355  DEBUG_MSG( DEBUG_NAME, this, "throwing kill for");
356  throw sc_unwind_exception( this, false );
357 
358  default: // THROWING_NOW
359  sc_assert( unwinding_preempted );
360  DEBUG_MSG( DEBUG_NAME, this, "restarting thread");
361  break;
362  }
363 }
364 
365 
366 //------------------------------------------------------------------------------
367 //"sc_thread_process::wait"
368 //
369 // Notes:
370 // (1) The correct order to lock and unlock channel locks (to avoid deadlocks
371 // and races) for SystemC functions with context switch:
372 //
373 // outer_channel.lock_and_push
374 // [outer channel work]
375 // inner_channel.lock_and_push
376 // [inner channel work]
377 // +----------------------------------WAIT----------------------------------+
378 // | +------------------------Simulation Kernel------------------------+ |
379 // | | acquire kernel lock | |
380 // | | +------unlock_all_channels-----+ | |
381 // | | | inner_channel.unlock | | |
382 // | | | outer_channel.unlock | | |
383 // | | +------------------------------+ | |
384 // | | [kernel work] | |
385 // | | pthread_cond_wait: release kernel lock | |
386 // | | [sleep] | |
387 // | | pthread_cond_wait (upon wakeup): acquire kernel lock | |
388 // | | [kernel work] | |
389 // | | release kernel lock | |
390 // | +-----------------------------------------------------------------+ |
391 // | [no lock/no work] |
392 // | +------lock_all_channels-------+ |
393 // | | outer_channel.lock | |
394 // | | inner_channel.lock | |
395 // | +------------------------------+ |
396 // +------------------------------------------------------------------------+
397 // [inner channel work]
398 // inner_channel.pop_and_unlock
399 // [outer channel work]
400 // outer_channel.pop_and_unlock
401 //
402 // (2) If we did not consider immediate notification, a more cleaner locking
403 // order should be:
404 //
405 // outer_channel.lock_and_push
406 // [outer channel work]
407 // inner_channel.lock_and_push
408 // [inner channel work]
409 // +----------------------------------WAIT----------------------------------+
410 // | +----unlock_all_channels----+ |
411 // | | inner_channel.unlock | |
412 // | | outer_channel.unlock | |
413 // | +---------------------------+ |
414 // | [no lock/no work] |
415 // | +-------------------------Simulation Kernel-------------------------+ |
416 // | | acquire kernel lock | |
417 // | | [kernel work] | |
418 // | | pthread_cond_wait: release kernel lock | |
419 // | | [sleep] | |
420 // | | pthread_cond_wait (upon wakeup): acquire kernel lock | |
421 // | | [kernel work] | |
422 // | | release kernel lock | |
423 // | +-------------------------------------------------------------------+ |
424 // | [no lock/no work] |
425 // | +-----lock_all_channels-----+ |
426 // | | outer_channel.lock | |
427 // | | inner_channel.lock | |
428 // | +---------------------------+ |
429 // +------------------------------------------------------------------------+
430 // [inner channel work]
431 // inner_channel.pop_and_unlock
432 // [outer channel work]
433 // outer_channel.pop_and_unlock
434 //
435 // (3) When acquiring the channel locks, we may encounter the same lock for
436 // several times (a channel method calls another one in the same channel).
437 // But we should encounter them one right after another, so the same lock
438 // is at the end of the lock queue. If we encounter a lock that is in the
439 // middle of the queue, then it is a bad coding style and simulation may
440 // break (meaning an inner channel method calls an outer channel method).
441 //
442 // (4) For more information, please refer to the following files:
443 // sc_method_process.h: 184 (sc_method_process::next_trigger)
444 // sc_event.cpp: 79 (sc_event::notify)
445 //
446 // (02/19/2015 GL)
447 //------------------------------------------------------------------------------
448 inline
449 void
451 {
452 
453 
454 
455 
456  if( m_unwinding )
457  SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
458 
459  {
460  // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock
461  sc_kernel_lock lock;
462 
463 #ifdef SC_LOCK_CHECK
464  assert( sc_get_curr_simcontext()->is_locked_and_owner() );
465 #endif /* SC_LOCK_CHECK */
466 
467  // 08/14/2015 GL: set the new segment ID of this thread
468  set_segment_id( -2 );
469 
470  unlock_all_channels(); // 02/16/2015 GL: release all the channel locks
471 
472 
473  //ZC 9:06 2017/3/14
474  // if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
475  // printf("\n%s is calling wait for nothing\n",this->name());
476 
477 
479  // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock
480  }
481 #ifdef SC_LOCK_CHECK
482  assert( sc_get_curr_simcontext()->is_not_owner() );
483 #endif /* SC_LOCK_CHECK */
484  lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks
485 
486 
487 
488 }
489 
490 inline
491 void
492 sc_thread_process::wait( const sc_event& e, int seg_id )
493 {
494 
495 
496  if( m_unwinding )
497  SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
498 
499  {
500  // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock
501  sc_kernel_lock lock;
502 
503 #ifdef SC_LOCK_CHECK
504  assert( sc_get_curr_simcontext()->is_locked_and_owner() );
505 #endif /* SC_LOCK_CHECK */
506 
507  // 08/14/2015 GL: set the new segment ID of this thread
508  set_segment_id( seg_id );
509 
510  unlock_all_channels(); // 02/16/2015 GL: release all the channel locks
511  m_event_p = &e; // for cleanup.
512  e.add_dynamic( this );
513 
514 
516 
517  //ZC 9:06 2017/3/14
518  // if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
519  // printf("\n%s is calling wait for event %s\n",this->name(),e.name());
520  this->m_process_state=2;
521  sc_get_curr_simcontext()->add_to_wait_queue( (sc_process_b*)this ) ;
522 
523 
524 
525  suspend_me();
526  // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock
527  }
528 #ifdef SC_LOCK_CHECK
529  assert( sc_get_curr_simcontext()->is_not_owner() );
530 #endif /* SC_LOCK_CHECK */
531  lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks
532 }
533 
534 inline
535 void
537 {
538 
539  if( m_unwinding )
540  SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
541 
542  {
543  // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock
544  sc_kernel_lock lock;
545 
546 #ifdef SC_LOCK_CHECK
547  assert( sc_get_curr_simcontext()->is_locked_and_owner() );
548 #endif /* SC_LOCK_CHECK */
549 
550  // 08/14/2015 GL: set the new segment ID of this thread
551  set_segment_id( seg_id );
552 
553  unlock_all_channels(); // 02/16/2015 GL: release all the channel locks
554  el.add_dynamic( this );
555  m_event_list_p = &el;
556  m_event_count = el.size(); //ZC 2018/7/9
557  //std::cout << "wait for or_list m_event_count = " << m_event_count << std::endl;
559 
560  //ZC 19:59 2018/7/9 copied for the andlist downward
561  //I dont know why I didnt do this before
562  // if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
563  // printf("\n%s is calling wait for event list\n",this->name());
564  this->m_process_state=2;
565  sc_get_curr_simcontext()->add_to_wait_queue( (sc_process_b*)this ) ;
566 
567 
568  suspend_me();
569  // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock
570  }
571 #ifdef SC_LOCK_CHECK
572  assert( sc_get_curr_simcontext()->is_not_owner() );
573 #endif /* SC_LOCK_CHECK */
574  lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks
575 }
576 
577 inline
578 void
580 {
581  if( m_unwinding )
582  SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
583 
584  {
585  // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock
586  sc_kernel_lock lock;
587 
588 #ifdef SC_LOCK_CHECK
589  assert( sc_get_curr_simcontext()->is_locked_and_owner() );
590 #endif /* SC_LOCK_CHECK */
591 
592  // 08/14/2015 GL: set the new segment ID of this thread
593  set_segment_id( seg_id );
594 
595  unlock_all_channels(); // 02/16/2015 GL: release all the channel locks
596  el.add_dynamic( this );
597  m_event_list_p = &el;
598  m_event_count = el.size();
599  //this->m_process_state=7;
600  //std::cout << "wait for and_list m_event_count = " << m_event_count << std::endl;
602 
603  //ZC 9:06 2017/3/14
604  // if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
605  // printf("\n%s is calling wait for event list\n",this->name());
606  this->m_process_state=2;
607  sc_get_curr_simcontext()->add_to_wait_queue( (sc_process_b*)this ) ;
608 
609 
610  suspend_me();
611  // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock
612  }
613 #ifdef SC_LOCK_CHECK
614  assert( sc_get_curr_simcontext()->is_not_owner() );
615 #endif /* SC_LOCK_CHECK */
616  lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks
617 }
618 
619 inline
620 void
621 sc_thread_process::wait( const sc_time& t, int seg_id )
622 {
623  if( m_unwinding )
624  SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
625 
626  {
627  // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock
628  sc_kernel_lock lock;
629 
630 #ifdef SC_LOCK_CHECK
631  assert( sc_get_curr_simcontext()->is_locked_and_owner() );
632 #endif /* SC_LOCK_CHECK */
633 
634  // 08/14/2015 GL: set the new segment ID of this thread
635  set_segment_id( seg_id );
636 
637  unlock_all_channels(); // 02/16/2015 GL: release all the channel locks
638  m_timeout_event_p->notify_internal( t );
639  m_timeout_event_p->add_dynamic( this );
640 
641  if(t==SC_ZERO_TIME){
642  this->m_process_state=3;
643  //sc_get_curr_simcontext()->add_to_wait_queue( (sc_process_b*)this ) ;
644  // if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
645  // printf("\n%s is calling wait for delta time\n",this->name());
646  }
647  else {
648  this->m_process_state=3; //ZC
649  // if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
650  // printf("\n%s is calling wait for time\n",this->name());
651  }
653 
654  suspend_me();
655  // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock
656  }
657 #ifdef SC_LOCK_CHECK
658  assert( sc_get_curr_simcontext()->is_not_owner() );
659 #endif /* SC_LOCK_CHECK */
660  lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks
661 }
662 
663 inline
664 void
665 sc_thread_process::wait( const sc_time& t, const sc_event& e, int seg_id )
666 {
667  if( m_unwinding )
668  SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
669 
670  {
671  // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock
672  sc_kernel_lock lock;
673 
674 #ifdef SC_LOCK_CHECK
675  assert( sc_get_curr_simcontext()->is_locked_and_owner() );
676 #endif /* SC_LOCK_CHECK */
677 
678  // 08/14/2015 GL: set the new segment ID of this thread
679  set_segment_id( seg_id );
680 
681  unlock_all_channels(); // 02/16/2015 GL: release all the channel locks
682  m_timeout_event_p->notify_internal( t );
683  m_timeout_event_p->add_dynamic( this );
684  e.add_dynamic( this );
685  m_event_p = &e;
687  suspend_me();
688  // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock
689  }
690 #ifdef SC_LOCK_CHECK
691  assert( sc_get_curr_simcontext()->is_not_owner() );
692 #endif /* SC_LOCK_CHECK */
693  lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks
694 }
695 
696 inline
697 void
698 sc_thread_process::wait( const sc_time& t, const sc_event_or_list& el, int seg_id )
699 {
700  if( m_unwinding )
701  SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
702 
703  {
704  // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock
705  sc_kernel_lock lock;
706 
707 #ifdef SC_LOCK_CHECK
708  assert( sc_get_curr_simcontext()->is_locked_and_owner() );
709 #endif /* SC_LOCK_CHECK */
710 
711  // 08/14/2015 GL: set the new segment ID of this thread
712  set_segment_id( seg_id );
713 
714  unlock_all_channels(); // 02/16/2015 GL: release all the channel locks
715  m_timeout_event_p->notify_internal( t );
716  m_timeout_event_p->add_dynamic( this );
717  el.add_dynamic( this );
718  m_event_list_p = &el;
720  suspend_me();
721  // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock
722  }
723 #ifdef SC_LOCK_CHECK
724  assert( sc_get_curr_simcontext()->is_not_owner() );
725 #endif /* SC_LOCK_CHECK */
726  lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks
727 }
728 
729 inline
730 void
731 sc_thread_process::wait( const sc_time& t, const sc_event_and_list& el, int seg_id )
732 {
733  if( m_unwinding )
734  SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
735 
736  {
737  // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock
738  sc_kernel_lock lock;
739 
740 #ifdef SC_LOCK_CHECK
741  assert( sc_get_curr_simcontext()->is_locked_and_owner() );
742 #endif /* SC_LOCK_CHECK */
743 
744  // 08/14/2015 GL: set the new segment ID of this thread
745  set_segment_id( seg_id );
746 
747  unlock_all_channels(); // 02/16/2015 GL: release all the channel locks
748  m_timeout_event_p->notify_internal( t );
749  m_timeout_event_p->add_dynamic( this );
750  el.add_dynamic( this );
751  m_event_list_p = &el;
752  m_event_count = el.size();
754  suspend_me();
755  // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock
756  }
757 #ifdef SC_LOCK_CHECK
758  assert( sc_get_curr_simcontext()->is_not_owner() );
759 #endif /* SC_LOCK_CHECK */
760  lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks
761 }
762 
763 //------------------------------------------------------------------------------
764 //"sc_thread_process::wait_cycles"
765 //
766 // This method suspends this object instance for the specified number of cycles.
767 // A cycle is defined as the event the thread is set up to staticly wait on.
768 // The field m_wait_cycle_n is set to one less than the number of cycles to
769 // be waited for, since the value is tested before being decremented in
770 // the simulation kernel.
771 //------------------------------------------------------------------------------
772 inline
773 void
774 sc_thread_process::wait_cycles( int seg_id, int n )
775 {
776  if( m_unwinding )
777  SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
778 
779  {
780  // 05/25/2015 GL: sc_kernel_lock constructor acquires the kernel lock
781  sc_kernel_lock lock;
782 
783 #ifdef SC_LOCK_CHECK
784  assert( sc_get_curr_simcontext()->is_locked_and_owner() );
785 #endif /* SC_LOCK_CHECK */
786 
787  // 08/14/2015 GL: set the new segment ID of this thread
788  set_segment_id( seg_id );
789 
790  unlock_all_channels(); // 02/16/2015 GL: release all the channel locks
791  m_wait_cycle_n = n-1;
792  suspend_me();
793  // 05/25/2015 GL: sc_kernel_lock destructor releases the kernel lock
794  }
795 #ifdef SC_LOCK_CHECK
796  assert( sc_get_curr_simcontext()->is_not_owner() );
797 #endif /* SC_LOCK_CHECK */
798  lock_all_channels(); // 02/16/2015 GL: acquire all the channel locks
799 }
800 
801 //------------------------------------------------------------------------------
802 //"sc_thread_process::miscellaneous support"
803 //
804 //------------------------------------------------------------------------------
805 inline
807 {
808  m_monitor_q.push_back(monitor_p);
809 }
810 
811 
812 inline
814 {
815  int mon_n = m_monitor_q.size();
816 
817  for ( int mon_i = 0; mon_i < mon_n; mon_i++ )
818  {
819  if ( m_monitor_q[mon_i] == monitor_p )
820  {
821  m_monitor_q[mon_i] = m_monitor_q[mon_n-1];
822  m_monitor_q.resize(mon_n-1);
823  }
824  }
825 }
826 
827 inline
829 {
830  m_exist_p = next_p;
831 }
832 
833 inline
835 {
836  return (sc_thread_handle)m_exist_p;
837 }
838 
839 inline
841 {
842  m_runnable_p = next_p;
843 }
844 
845 inline
847 {
849 }
850 
851 //------------------------------------------------------------------------------
852 //"sc_thread_process::trigger_static"
853 //
854 // This inline method adds the current thread to the queue of runnable
855 // processes, if required. This is the case if the following criteria
856 // are met:
857 // (1) The process is in a runnable state.
858 // (2) The process is not already on the run queue.
859 // (3) The process is expecting a static trigger,
860 // dynamic event waits take priority.
861 // (4) The process' static wait count is zero.
862 //
863 // If the triggering process is the same process, the trigger is
864 // ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS
865 // is defined.
866 //------------------------------------------------------------------------------
867 inline
868 void
869 // 08/14/2015 GL: add a new parameter to update the local time stamp
870 //sc_thread_process::trigger_static()
872 {
873  // 05/05/2015 GL: we may or may not have acquired the kernel lock upon here
874  // 1) this function is invoked in sc_simcontext::prepare_to_simulate(),
875  // where the kernel lock is not acquired as it is in the initialization
876  // phase
877  // 2) this function is also invoked in sc_event::notify(), where the kernel
878  // lock is acquired
879 
880  // No need to try queueing this thread if one of the following is true:
881  // (a) its disabled
882  // (b) its already queued for execution
883  // (c) its waiting on a dynamic event
884  // (d) its wait count is not satisfied
885 
886  if ( (m_state & ps_bit_disabled) || is_runnable() ||
888  return;
889 
890 #if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS )
891  if( SC_UNLIKELY_( sc_get_current_process_b() == this ) )
892  {
894  return;
895  }
896 #endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS
897 
898  if ( m_wait_cycle_n > 0 )
899  {
900  --m_wait_cycle_n;
901  return;
902  }
903 
904  // If we get here then the thread is has satisfied its wait criteria, if
905  // its suspended mark its state as ready to run. If its not suspended then
906  // push it onto the runnable queue.
907 
908  if ( m_state & ps_bit_suspended )
909  {
911  }
912  else
913  {
914  // 12/22/2016 GL: store the current time before updating
915  sc_time curr_time = m_timestamp.get_time_count();
916 
917  // 08/14/2015 GL: update the local time stamp of this thread process
919  switch( e->m_notify_type )
920  {
921  case sc_event::DELTA: // delta notification
922  if ( ts > m_timestamp ) {
924  ts.get_delta_count() + 1 ) );
925  } else {
928  + 1 ) );
929  }
930  break;
931  case sc_event::TIMED: // timed notification
932  set_timestamp( ts );
933  break;
934  case sc_event::NONE:
935  assert( 0 ); // wrong type
936  }
937 
938  simcontext()->push_runnable_thread(this);
939 
940  // 12/22/2016 GL: update m_oldest_time in sc_simcontext if necessary
941  simcontext()->update_oldest_time( curr_time );
942  }
943 }
944 
945 #undef DEBUG_MSG
946 #undef DEBUG_NAME
947 
948 } // namespace sc_core
949 
950 // $Log: sc_thread_process.h,v $
951 // Revision 1.30 2011/08/26 20:46:11 acg
952 // Andy Goodrich: moved the modification log to the end of the file to
953 // eliminate source line number skew when check-ins are done.
954 //
955 // Revision 1.29 2011/08/24 23:36:12 acg
956 // Andy Goodrich: removed break statements that can never be reached and
957 // which causes warnings in the Greenhills C++ compiler.
958 //
959 // Revision 1.28 2011/04/14 22:34:27 acg
960 // Andy Goodrich: removed dead code.
961 //
962 // Revision 1.27 2011/04/13 05:02:18 acg
963 // Andy Goodrich: added missing check to the wake up code in suspend_me()
964 // so that we just return if the call to suspend_me() was issued from a
965 // stack unwinding.
966 //
967 // Revision 1.26 2011/04/13 02:44:26 acg
968 // Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the
969 // throw status will be set back to THROW_*_RESET if reset is active and
970 // the check for an unwind being complete was expecting THROW_NONE as the
971 // clearing of THROW_NOW.
972 //
973 // Revision 1.25 2011/04/11 22:05:14 acg
974 // Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations.
975 //
976 // Revision 1.24 2011/04/10 22:12:32 acg
977 // Andy Goodrich: adding debugging macros.
978 //
979 // Revision 1.23 2011/04/08 22:41:28 acg
980 // Andy Goodrich: added comment pointing to the description of the reset
981 // mechanism in sc_reset.cpp.
982 //
983 // Revision 1.22 2011/04/08 18:27:33 acg
984 // Andy Goodrich: added check to make sure we don't schedule a running process
985 // because of it issues a notify() it is sensitive to.
986 //
987 // Revision 1.21 2011/04/05 06:22:38 acg
988 // Andy Goodrich: expanded comment for trigger_static() initial vetting.
989 //
990 // Revision 1.20 2011/04/01 21:24:57 acg
991 // Andy Goodrich: removed unused code.
992 //
993 // Revision 1.19 2011/02/19 08:30:53 acg
994 // Andy Goodrich: Moved process queueing into trigger_static from
995 // sc_event::notify.
996 //
997 // Revision 1.18 2011/02/18 20:27:14 acg
998 // Andy Goodrich: Updated Copyrights.
999 //
1000 // Revision 1.17 2011/02/17 19:55:58 acg
1001 // Andy Goodrich:
1002 // (1) Changed signature of trigger_dynamic() back to a bool.
1003 // (2) Simplified process control usage.
1004 // (3) Changed trigger_static() to recognize process controls and to
1005 // do the down-count on wait(N), allowing the elimination of
1006 // ready_to_run().
1007 //
1008 // Revision 1.16 2011/02/16 22:37:31 acg
1009 // Andy Goodrich: clean up to remove need for ps_disable_pending.
1010 //
1011 // Revision 1.15 2011/02/13 21:47:38 acg
1012 // Andy Goodrich: update copyright notice.
1013 //
1014 // Revision 1.14 2011/02/13 21:35:54 acg
1015 // Andy Goodrich: added error for performing a wait() during unwinding.
1016 //
1017 // Revision 1.13 2011/02/11 13:25:24 acg
1018 // Andy Goodrich: Philipp A. Hartmann's changes:
1019 // (1) Removal of SC_CTHREAD method overloads.
1020 // (2) New exception processing code.
1021 //
1022 // Revision 1.12 2011/02/01 23:01:53 acg
1023 // Andy Goodrich: removed dead code.
1024 //
1025 // Revision 1.11 2011/02/01 21:18:01 acg
1026 // Andy Goodrich:
1027 // (1) Changes in throw processing for new process control rules.
1028 // (2) Support of new process_state enum values.
1029 //
1030 // Revision 1.10 2011/01/25 20:50:37 acg
1031 // Andy Goodrich: changes for IEEE 1666 2011.
1032 //
1033 // Revision 1.9 2011/01/19 23:21:50 acg
1034 // Andy Goodrich: changes for IEEE 1666 2011
1035 //
1036 // Revision 1.8 2011/01/18 20:10:45 acg
1037 // Andy Goodrich: changes for IEEE1666_2011 semantics.
1038 //
1039 // Revision 1.7 2011/01/06 17:59:58 acg
1040 // Andy Goodrich: removed debugging output.
1041 //
1042 // Revision 1.6 2010/07/22 20:02:33 acg
1043 // Andy Goodrich: bug fixes.
1044 //
1045 // Revision 1.5 2009/07/28 01:10:53 acg
1046 // Andy Goodrich: updates for 2.3 release candidate.
1047 //
1048 // Revision 1.4 2009/05/22 16:06:29 acg
1049 // Andy Goodrich: process control updates.
1050 //
1051 // Revision 1.3 2009/03/12 22:59:58 acg
1052 // Andy Goodrich: updates for 2.4 stuff.
1053 //
1054 // Revision 1.2 2008/05/22 17:06:06 acg
1055 // Andy Goodrich: formatting and comments.
1056 //
1057 // Revision 1.1.1.1 2006/12/15 20:20:05 acg
1058 // SystemC 2.3
1059 //
1060 // Revision 1.7 2006/05/08 17:57:13 acg
1061 // Andy Goodrich: Added David Long's forward declarations for friend functions
1062 // to keep the Microsoft C++ compiler happy.
1063 //
1064 // Revision 1.6 2006/04/20 17:08:17 acg
1065 // Andy Goodrich: 3.0 style process changes.
1066 //
1067 // Revision 1.5 2006/04/11 23:13:21 acg
1068 // Andy Goodrich: Changes for reduced reset support that only includes
1069 // sc_cthread, but has preliminary hooks for expanding to method and thread
1070 // processes also.
1071 //
1072 // Revision 1.4 2006/01/24 20:49:05 acg
1073 // Andy Goodrich: changes to remove the use of deprecated features within the
1074 // simulator, and to issue warning messages when deprecated features are used.
1075 //
1076 // Revision 1.3 2006/01/13 18:44:30 acg
1077 // Added $Log to record CVS changes into the source.
1078 
1079 #endif // !defined(sc_thread_process_h_INCLUDED)
friend void sc_thread_cor_fn(void *)
void report_immediate_self_notification() const
#define sc_assert(expr)
Definition: sc_report.h:235
sc_throw_it_helper * m_throw_helper_p
Definition: sc_process.h:918
sc_event * m_reset_event_p
Definition: sc_process.h:909
sc_process_b * sc_get_current_process_b()
bool deliver_event_at_time(sc_event *e, sc_timestamp e_delivery_time)
virtual void resume_process(sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS)
void add_monitor(sc_process_monitor *monitor_p)
friend void wait(int, sc_simcontext *)
OR list of events.
Definition: sc_event.h:228
virtual void throw_reset(bool async)
void notify()
The immediate notification is not supported by the out-of-order simulation in the current release...
void set_next_runnable(sc_thread_handle next_p)
A scoped mutex for the kernel lock.
process_throw_type m_throw_status
Definition: sc_process.h:919
#define SC_REPORT_ERROR(msg_type, msg)
Definition: sc_report.h:213
sc_process_b sc_process_b
Definition: sc_process.h:964
A time stamp combining timed cycles and delta cycles.
Definition: sc_process.h:433
const sc_time & get_time_count() const
Get the value of timed cycles.
void oooschedule(sc_cor *cor)
Scheduling function in the OoO simulation.
virtual void prepare_for_simulation()
sc_descendant_inclusion_info
Definition: sc_process.h:135
This class provides access to an sc_process_b object instance in a manner which allows some persisten...
void(sc_process_host::* SC_ENTRY_FUNC)()
Definition: sc_process.h:211
sc_thread_process(const char *name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host *host_p, const sc_spawn_options *opt_p)
AND list of events.
Definition: sc_event.h:193
void signal_monitors(int type=0)
#define SC_UNLIKELY_(x)
Definition: sc_cmnhdr.h:85
sc_event * m_timeout_event_p
Definition: sc_process.h:921
void wait(int, sc_simcontext *)
sc_cor * get_cor_pointer(sc_process_b *process_p)
Coroutine abstract base class.
Definition: sc_cor.h:57
const char * name() const
Definition: sc_object.h:71
sc_simcontext * simcontext() const
Definition: sc_object.h:85
const sc_event * m_event_p
Definition: sc_process.h:895
void sc_thread_cor_fn(void *arg)
int size() const
Definition: sc_event.h:643
void add_dynamic(sc_method_handle) const
User initiated dynamic process support.
Definition: sc_process.h:555
virtual void suspend_process(sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS)
void trigger_static(sc_event *)
A new parameter is added to update the local time stamp in the thread process.
void set_stack_size(std::size_t size)
void set_next_exist(sc_thread_handle next_p)
Class that manages the ready-to-run queues.
Definition: sc_runnable.h:42
trigger_t m_trigger_type
Definition: sc_process.h:922
sc_thread_handle next_exist()
void lock_all_channels(void)
Acquire all the channel locks.
class sc_thread_process * sc_thread_handle
Definition: sc_process.h:120
sc_process_b * m_exist_p
Definition: sc_process.h:899
const sc_timestamp & get_notify_timestamp() const
GET the notification time stamp.
void wait_cycles(int, int n=1)
A new parameter segment ID is added for the out-of-order simulation.
void remove_running_process(sc_process_b *)
Remove a process from the running queue.
The event class.
Definition: sc_event.h:260
virtual void disable_process(sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS)
The simulation context.
#define DEBUG_MSG(NAME, P, MSG)
friend class sc_unwind_exception
Definition: sc_process.h:578
Base class for all structural entities.
Definition: sc_module.h:83
void unlock_all_channels(void)
Release all the channel locks.
bool is_running_process(sc_process_b *)
Check whether a process is in the running queue.
sc_timestamp m_timestamp
The local time stamp of this process.
Definition: sc_process.h:941
friend void sc_set_stack_size(sc_thread_handle, std::size_t)
virtual void throw_user(const sc_throw_it_helper &helper, sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS)
Base class for all hierarchical channels.
Definition: sc_module.h:712
virtual void throw_it()=0
sc_thread_handle next_runnable()
virtual void kill_process(sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS)
sc_simcontext * sc_get_curr_simcontext()
void set_timestamp(const sc_timestamp &ts)
Get the local time stamp of this process.
void sc_set_stack_size(sc_method_handle, std::size_t)
friend sc_cor * get_cor_pointer(sc_process_b *process_p)
const sc_time SC_ZERO_TIME
This is the base class for objects which may have processes defined for their methods (e...
Definition: sc_process.h:148
void remove_monitor(sc_process_monitor *monitor_p)
bool trigger_dynamic(sc_event *, bool &)
sc_process_b * m_runnable_p
Definition: sc_process.h:911
std::vector< sc_process_monitor * > m_monitor_q
virtual const char * kind() const
value_type get_delta_count() const
Get the value of delta cycles.
bool is_runnable() const
Definition: sc_process.h:1034
virtual void enable_process(sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS)
void suspend_cor(sc_cor *)
Suspend a coroutine.
void set_segment_id(int id)
Get the current segment ID of this process.
int m_process_state
The name of this process.
Definition: sc_process.h:887
const sc_event_list * m_event_list_p
Definition: sc_process.h:898