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_method_process.cpp -- Method process implementation
23 
24   Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005
25 
26   CHANGE LOG AT THE END OF THE FILE
27  *****************************************************************************/
28 
29 #include "sysc/kernel/sc_method_process.h"
30 #include "sysc/kernel/sc_simcontext_int.h"
31 #include "sysc/kernel/sc_module.h"
32 #include "sysc/kernel/sc_spawn_options.h"
33 
34 // DEBUGGING MACROS:
35 //
36 // DEBUG_MSG(NAME,P,MSG)
37 //     MSG  = message to print
38 //     NAME = name that must match the process for the message to print, or
39 //            null if the message should be printed unconditionally.
40 //     P    = pointer to process message is for, or NULL in which case the
41 //            message will not print.
42 #if 0
43 #   include <cstring>
44 #   define DEBUG_NAME ""
45 #   define DEBUG_MSG(NAME,P,MSG) \
46     { \
47         if ( P && ( (std::strlen(NAME)==0) || !std::strcmp(NAME,P->name())) ) \
48           std::cout << "**** " << sc_time_stamp() << " ("  \
49 	            << sc_get_current_process_name("** NONE **") << "): " << MSG \
50 		    << " - " << P->name() << std::endl; \
51     }
52 #else
53 #   define DEBUG_MSG(NAME,P,MSG)
54 #endif
55 
56 namespace sc_core {
57 
58 // +----------------------------------------------------------------------------
59 // |"sc_method_process::check_for_throws"
60 // |
61 // | This method checks to see if this method process should throw an exception
62 // | or not. It is called from sc_simcontext::preempt_with() to see if the
63 // | thread that was executed during the preemption did a kill or other
64 // | manipulation on this object instance that requires it to throw an
65 // | exception.
66 // +----------------------------------------------------------------------------
check_for_throws()67 void sc_method_process::check_for_throws()
68 {
69     if ( !m_unwinding )
70     {
71 	switch( m_throw_status )
72 	{
73 	  case THROW_ASYNC_RESET:
74 	    simcontext()->preempt_with(this);
75 	    break;
76           case THROW_KILL:
77 	    throw sc_unwind_exception( this, false );
78 	  default:
79 	    break;
80 	}
81     }
82 }
83 
84 //------------------------------------------------------------------------------
85 //"sc_method_process::clear_trigger"
86 //
87 // This method clears any pending trigger for this object instance.
88 //------------------------------------------------------------------------------
clear_trigger()89 void sc_method_process::clear_trigger()
90 {
91     switch( m_trigger_type ) {
92       case STATIC:
93         return;
94       case EVENT:
95         m_event_p->remove_dynamic( this );
96         m_event_p = 0;
97         break;
98       case OR_LIST:
99         m_event_list_p->remove_dynamic( this, 0 );
100         m_event_list_p->auto_delete();
101         m_event_list_p = 0;
102         break;
103       case AND_LIST:
104         m_event_list_p->remove_dynamic( this, 0 );
105         m_event_list_p->auto_delete();
106         m_event_list_p = 0;
107         m_event_count = 0;
108         break;
109       case TIMEOUT:
110         m_timeout_event_p->cancel();
111         m_timeout_event_p->reset();
112         break;
113       case EVENT_TIMEOUT:
114         m_timeout_event_p->cancel();
115         m_timeout_event_p->reset();
116         m_event_p->remove_dynamic( this );
117         m_event_p = 0;
118         break;
119       case OR_LIST_TIMEOUT:
120         m_timeout_event_p->cancel();
121         m_timeout_event_p->reset();
122         m_event_list_p->remove_dynamic( this, 0 );
123         m_event_list_p->auto_delete();
124         m_event_list_p = 0;
125       break;
126       case AND_LIST_TIMEOUT:
127         m_timeout_event_p->cancel();
128         m_timeout_event_p->reset();
129         m_event_list_p->remove_dynamic( this, 0 );
130         m_event_list_p->auto_delete();
131         m_event_list_p = 0;
132         m_event_count = 0;
133         break;
134     }
135     m_trigger_type = STATIC;
136 }
137 
138 //------------------------------------------------------------------------------
139 //"sc_method_process::disable_process"
140 //
141 // This virtual method disables this process and its children if requested to.
142 //     descendants = indicator of whether this process' children should also
143 //                   be suspended
144 //------------------------------------------------------------------------------
disable_process(sc_descendant_inclusion_info descendants)145 void sc_method_process::disable_process(
146     sc_descendant_inclusion_info descendants )
147 {
148 
149     // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS:
150 
151     if ( descendants == SC_INCLUDE_DESCENDANTS )
152     {
153         const std::vector<sc_object*>& children = get_child_objects();
154         int                            child_n  = children.size();
155 
156         for ( int child_i = 0; child_i < child_n; child_i++ )
157         {
158             sc_process_b* child_p = dynamic_cast<sc_process_b*>(children[child_i]);
159             if ( child_p ) child_p->disable_process(descendants);
160         }
161     }
162 
163     // DON'T ALLOW CORNER CASE BY DEFAULT:
164 
165     if ( !sc_allow_process_control_corners )
166     {
167         switch( m_trigger_type )
168         {
169           case AND_LIST_TIMEOUT:
170           case EVENT_TIMEOUT:
171           case OR_LIST_TIMEOUT:
172           case TIMEOUT:
173             report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_,
174                           "attempt to disable a method with timeout wait" );
175             // may continue, if suppressed
176             break;
177           default:
178             break;
179         }
180     }
181 
182     // DISABLE OUR OBJECT INSTANCE:
183 
184     m_state = m_state | ps_bit_disabled;
185 
186     // IF THIS CALL IS BEFORE THE SIMULATION DON'T RUN THE METHOD:
187 
188     if ( !sc_is_running() )
189     {
190         sc_get_curr_simcontext()->remove_runnable_method(this);
191     }
192 }
193 
194 
195 //------------------------------------------------------------------------------
196 //"sc_method_process::enable_process"
197 //
198 // This method enables the execution of this process, and if requested, its
199 // descendants. If the process was suspended and has a resumption pending it
200 // will be dispatched in the next delta cycle. Otherwise the state will be
201 // adjusted to indicate it is no longer suspended, but no immediate execution
202 // will occur.
203 //------------------------------------------------------------------------------
enable_process(sc_descendant_inclusion_info descendants)204 void sc_method_process::enable_process(
205     sc_descendant_inclusion_info descendants )
206 {
207 
208     // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS:
209 
210     if ( descendants == SC_INCLUDE_DESCENDANTS )
211     {
212         const std::vector<sc_object*>& children = get_child_objects();
213         int                            child_n  = children.size();
214 
215         for ( int child_i = 0; child_i < child_n; child_i++ )
216         {
217             sc_process_b* child_p = dynamic_cast<sc_process_b*>(children[child_i]);
218             if ( child_p ) child_p->enable_process(descendants);
219         }
220     }
221 
222     // ENABLE THIS OBJECT INSTANCE:
223     //
224     // If it was disabled and ready to run then put it on the run queue.
225 
226     m_state = m_state & ~ps_bit_disabled;
227     if ( m_state == ps_bit_ready_to_run )
228     {
229         m_state = ps_normal;
230 	if ( next_runnable() == 0 )
231 	    simcontext()->push_runnable_method(this);
232     }
233 }
234 
235 
236 //------------------------------------------------------------------------------
237 //"sc_method_process::kill_process"
238 //
239 // This method removes throws a kill for this object instance. It calls the
240 // sc_process_b::kill_process() method to perform low level clean up.
241 //------------------------------------------------------------------------------
kill_process(sc_descendant_inclusion_info descendants)242 void sc_method_process::kill_process(sc_descendant_inclusion_info descendants)
243 {
244 
245     // IF THE SIMULATION HAS NOT BEEN INITIALIZED YET THAT IS AN ERROR:
246 
247     if ( !sc_is_running() )
248     {
249         report_error( SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ );
250         return;
251     }
252 
253     // IF NEEDED, PROPOGATE THE KILL REQUEST THROUGH OUR DESCENDANTS:
254 
255     if ( descendants == SC_INCLUDE_DESCENDANTS )
256     {
257         const std::vector<sc_object*> children = get_child_objects();
258         int                           child_n  = children.size();
259 
260         for ( int child_i = 0; child_i < child_n; child_i++ )
261         {
262             sc_process_b* child_p = dynamic_cast<sc_process_b*>(children[child_i]);
263             if ( child_p ) child_p->kill_process(descendants);
264         }
265     }
266 
267     // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE
268     // IGNORE THE KILL:
269 
270     if ( m_unwinding )
271     {
272         SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() );
273         return;
274     }
275 
276     if ( m_state & ps_bit_zombie )
277         return;
278 
279 
280     // REMOVE OUR PROCESS FROM EVENTS, ETC., AND IF ITS THE ACTIVE PROCESS
281     // THROW ITS KILL.
282     //
283     // Note we set the throw status to kill regardless if we throw or not.
284     // That lets check_for_throws stumble across it if we were in the call
285     // chain when the kill call occurred.
286 
287     if ( next_runnable() != 0 )
288         simcontext()->remove_runnable_method( this );
289     disconnect_process();
290 
291     m_throw_status = THROW_KILL;
292     if ( sc_get_current_process_b() == this )
293     {
294         throw sc_unwind_exception( this, false );
295     }
296 }
297 
298 //------------------------------------------------------------------------------
299 //"sc_method_process::sc_method_process"
300 //
301 // This is the object instance constructor for this class.
302 //------------------------------------------------------------------------------
sc_method_process(const char * name_p,bool free_host,SC_ENTRY_FUNC method_p,sc_process_host * host_p,const sc_spawn_options * opt_p)303 sc_method_process::sc_method_process( const char* name_p,
304     bool free_host, SC_ENTRY_FUNC method_p,
305     sc_process_host* host_p, const sc_spawn_options* opt_p
306 ):
307     sc_process_b(
308         name_p ? name_p : sc_gen_unique_name("method_p"),
309         false, free_host, method_p, host_p, opt_p),
310 	m_cor(0), m_stack_size(0), m_monitor_q()
311 {
312 
313     // CHECK IF THIS IS AN sc_module-BASED PROCESS AND SIMUALTION HAS STARTED:
314 
315     if ( dynamic_cast<sc_module*>(host_p) != 0 && sc_is_running() )
316     {
317         report_error( SC_ID_MODULE_METHOD_AFTER_START_, "" );
318         sc_abort(); // can't recover from here
319     }
320 
321     // INITIALIZE VALUES:
322     //
323     // If there are spawn options use them.
324 
325     m_process_kind = SC_METHOD_PROC_;
326     if (opt_p) {
327         m_dont_init = opt_p->m_dont_initialize;
328 
329         // traverse event sensitivity list
330         for (unsigned int i = 0; i < opt_p->m_sensitive_events.size(); i++) {
331             sc_sensitive::make_static_sensitivity(
332                 this, *opt_p->m_sensitive_events[i]);
333         }
334 
335         // traverse port base sensitivity list
336         for ( unsigned int i = 0; i < opt_p->m_sensitive_port_bases.size(); i++)
337         {
338             sc_sensitive::make_static_sensitivity(
339                 this, *opt_p->m_sensitive_port_bases[i]);
340         }
341 
342         // traverse interface sensitivity list
343         for ( unsigned int i = 0; i < opt_p->m_sensitive_interfaces.size(); i++)
344         {
345             sc_sensitive::make_static_sensitivity(
346                 this, *opt_p->m_sensitive_interfaces[i]);
347         }
348 
349         // traverse event finder sensitivity list
350         for ( unsigned int i = 0; i < opt_p->m_sensitive_event_finders.size();
351             i++)
352         {
353             sc_sensitive::make_static_sensitivity(
354                 this, *opt_p->m_sensitive_event_finders[i]);
355         }
356 
357 	// process any reset signal specification:
358 
359 	opt_p->specify_resets();
360     }
361 
362     else
363     {
364         m_dont_init = false;
365     }
366 }
367 
368 //------------------------------------------------------------------------------
369 //"sc_method_process::sc_method_process"
370 //
371 // This is the object instance destructor for this class.
372 //------------------------------------------------------------------------------
~sc_method_process()373 sc_method_process::~sc_method_process()
374 {
375     // Remove from simcontext, if not spawned during simulation
376     if( m_dynamic_proc != SPAWN_SIM ) {
377         simcontext()->remove_process(this);
378     }
379 }
380 
381 
382 //------------------------------------------------------------------------------
383 //"sc_method_process::suspend_process"
384 //
385 // This virtual method suspends this process and its children if requested to.
386 //     descendants = indicator of whether this process' children should also
387 //                   be suspended
388 //------------------------------------------------------------------------------
suspend_process(sc_descendant_inclusion_info descendants)389 void sc_method_process::suspend_process(
390     sc_descendant_inclusion_info descendants )
391 {
392 
393     // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS:
394 
395     if ( descendants == SC_INCLUDE_DESCENDANTS )
396     {
397         const std::vector<sc_object*>& children = get_child_objects();
398         int                            child_n  = children.size();
399 
400         for ( int child_i = 0; child_i < child_n; child_i++ )
401         {
402             sc_process_b* child_p = dynamic_cast<sc_process_b*>(children[child_i]);
403             if ( child_p ) child_p->suspend_process(descendants);
404         }
405     }
406 
407     // CORNER CASE CHECKS, THE FOLLOWING ARE ERRORS:
408     //   (a) if this method has a reset_signal_is specification
409     //   (b) if this method is in synchronous reset
410 
411     if ( !sc_allow_process_control_corners && m_has_reset_signal )
412     {
413         report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_,
414                      "attempt to suspend a method that has a reset signal");
415         // may continue, if suppressed
416     }
417     else if ( !sc_allow_process_control_corners && m_sticky_reset )
418     {
419         report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_,
420                      "attempt to suspend a method in synchronous reset");
421         // may continue, if suppressed
422     }
423 
424     // SUSPEND OUR OBJECT INSTANCE:
425     //
426     // (1) If we are on the runnable queue then set suspended and ready_to_run,
427     //     and remove ourselves from the run queue.
428     // (2) If this is a self-suspension then a resume should cause immediate
429     //     scheduling of the process.
430 
431     m_state = m_state | ps_bit_suspended;
432     if ( next_runnable() != 0 )
433     {
434 	m_state = m_state | ps_bit_ready_to_run;
435 	simcontext()->remove_runnable_method( this );
436     }
437     if ( sc_get_current_process_b() == dynamic_cast<sc_process_b*>(this)  )
438     {
439 	m_state = m_state | ps_bit_ready_to_run;
440     }
441 }
442 
443 //------------------------------------------------------------------------------
444 //"sc_method_process::resume_process"
445 //
446 // This method resumes the execution of this process, and if requested, its
447 // descendants. If the process was suspended and has a resumption pending it
448 // will be dispatched in the next delta cycle. Otherwise the state will be
449 // adjusted to indicate it is no longer suspended, but no immediate execution
450 // will occur.
451 //------------------------------------------------------------------------------
resume_process(sc_descendant_inclusion_info descendants)452 void sc_method_process::resume_process(
453     sc_descendant_inclusion_info descendants )
454 {
455 
456     // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS:
457 
458     if ( descendants == SC_INCLUDE_DESCENDANTS )
459     {
460         const std::vector<sc_object*>& children = get_child_objects();
461         int                            child_n  = children.size();
462 
463         for ( int child_i = 0; child_i < child_n; child_i++ )
464         {
465             sc_process_b* child_p = dynamic_cast<sc_process_b*>(children[child_i]);
466             if ( child_p ) child_p->resume_process(descendants);
467         }
468     }
469 
470 
471     // BY DEFAULT THE CORNER CASE IS AN ERROR:
472 
473     if ( !sc_allow_process_control_corners && (m_state & ps_bit_disabled) &&
474          (m_state & ps_bit_suspended) )
475     {
476         m_state = m_state & ~ps_bit_suspended;
477         report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_,
478                       "call to resume() on a disabled suspended method" );
479         // may continue, if suppressed
480     }
481 
482     // CLEAR THE SUSPENDED BIT:
483 
484     m_state = m_state & ~ps_bit_suspended;
485 
486     // RESUME OBJECT INSTANCE:
487     //
488     // If this is not a self-resume and the method is ready to run then
489     // put it on the runnable queue.
490 
491     if ( m_state & ps_bit_ready_to_run )
492     {
493 	m_state = m_state & ~ps_bit_ready_to_run;
494 	if ( next_runnable() == 0 &&
495 	   ( sc_get_current_process_b() != dynamic_cast<sc_process_b*>(this) ) )
496         {
497 	    simcontext()->push_runnable_method(this);
498 	    remove_dynamic_events();
499 	}
500     }
501 }
502 
503 //------------------------------------------------------------------------------
504 //"sc_method_process::throw_reset"
505 //
506 // This virtual method is invoked to "throw" a reset.
507 //
508 // If the reset is synchronous this is a no-op, except for triggering the
509 // reset event if it is present.
510 //
511 // If the reset is asynchronous we:
512 //   (a) cancel any dynamic waits
513 //   (b) if it is the active process actually throw a reset exception.
514 //   (c) if it was not the active process and does not have a static
515 //       sensitivity emit an error if corner cases are to be considered
516 //       errors.
517 //
518 // Notes:
519 //   (1) If the process had a reset event it will have been triggered in
520 //       sc_process_b::semantics()
521 //
522 // Arguments:
523 //   async = true if this is an asynchronous reset.
524 //------------------------------------------------------------------------------
throw_reset(bool async)525 void sc_method_process::throw_reset( bool async )
526 {
527     // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE
528     // IGNORE THE RESET:
529 
530     if ( m_unwinding )
531     {
532         SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() );
533         return;
534     }
535 
536     if ( m_state & ps_bit_zombie )
537         return;
538 
539     // Set the throw status and if its an asynchronous reset throw an
540     // exception:
541 
542     m_throw_status = async ? THROW_ASYNC_RESET : THROW_SYNC_RESET;
543     if ( async )
544     {
545         remove_dynamic_events();
546 	if ( sc_get_current_process_b() == this )
547 	{
548 	    DEBUG_MSG(DEBUG_NAME,this,"throw_reset: throwing exception");
549 	    m_throw_status = THROW_ASYNC_RESET;
550 	    throw sc_unwind_exception( this, true );
551 	}
552 	else
553 	{
554 	    DEBUG_MSG(DEBUG_NAME,this,
555 	              "throw_reset: queueing this method for execution");
556 	    simcontext()->preempt_with(this);
557 	}
558     }
559 }
560 
561 
562 //------------------------------------------------------------------------------
563 //"sc_method_process::throw_user"
564 //
565 // This virtual method is invoked when a user exception is to be thrown.
566 // If requested it will also throw the exception to the children of this
567 // object instance. Since this is a method no throw will occur for this
568 // object instance. The children will be awakened from youngest child to
569 // eldest.
570 //     helper_p    -> object to use to throw the exception.
571 //     descendants =  indicator of whether this process' children should also
572 //                    be suspended
573 //------------------------------------------------------------------------------
throw_user(const sc_throw_it_helper & helper,sc_descendant_inclusion_info descendants)574 void sc_method_process::throw_user( const sc_throw_it_helper& helper,
575     sc_descendant_inclusion_info descendants )
576 {
577 
578     // IF THE SIMULATION IS NOT ACTUALLY RUNNING THIS IS AN ERROR:
579 
580     if (  sc_get_status() != SC_RUNNING )
581     {
582         report_error( SC_ID_THROW_IT_WHILE_NOT_RUNNING_ );
583         return;
584     }
585 
586     // IF NEEDED PROPOGATE THE THROW REQUEST THROUGH OUR DESCENDANTS:
587 
588     if ( descendants == SC_INCLUDE_DESCENDANTS )
589     {
590         const std::vector<sc_object*> children = get_child_objects();
591         int                           child_n  = children.size();
592 
593         for ( int child_i = 0; child_i < child_n; child_i++ )
594         {
595             sc_process_b* child_p = dynamic_cast<sc_process_b*>(children[child_i]);
596             if ( child_p )
597 	    {
598 	        DEBUG_MSG(DEBUG_NAME,child_p,"about to throw user on");
599 	        child_p->throw_user(helper, descendants);
600 	    }
601         }
602     }
603 
604 #if 0 // shouldn't we throw, if we're currently running?
605 
606     if ( sc_get_current_process_b() == (sc_process_b*)this )
607     {
608         remove_dynamic_events();
609         m_throw_status = THROW_USER;
610         if ( m_throw_helper_p != 0 ) delete m_throw_helper_p;
611         m_throw_helper_p = helper.clone();
612         m_throw_helper_p->throw_it();
613     }
614 
615     // throw_it HAS NO EFFECT ON A METHOD, ISSUE A WARNING:
616 
617     else
618 
619 #endif
620    {
621         SC_REPORT_WARNING( SC_ID_THROW_IT_IGNORED_, name() );
622    }
623 
624 
625 }
626 
627 //------------------------------------------------------------------------------
628 //"sc_method_process::trigger_dynamic"
629 //
630 // This method sets up a dynamic trigger on an event.
631 //
632 // Notes:
633 //   (1) This method is identical to sc_thread_process::trigger_dynamic(),
634 //       but they cannot be combined as sc_process_b::trigger_dynamic()
635 //       because the signatures things like sc_event::remove_dynamic()
636 //       have different overloads for sc_method_process* and sc_thread_process*.
637 //       So if you change code here you'll also need to change it in
638 //       sc_thread_process.cpp.
639 //
640 // Result is true if this process should be removed from the event's list,
641 // false if not.
642 //
643 // If the triggering process is the same process, the trigger is
644 // ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS
645 // is defined.
646 //------------------------------------------------------------------------------
trigger_dynamic(sc_event * e)647 bool sc_method_process::trigger_dynamic( sc_event* e )
648 {
649     // No time outs yet, and keep gcc happy.
650 
651     m_timed_out = false;
652 
653     // Escape cases:
654     //   (a) If this method issued the notify() don't schedule it for
655     //       execution, but leave the sensitivity in place.
656     //   (b) If this method is already runnable can't trigger an event.
657 
658 #if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS )
659     if( SC_UNLIKELY_( sc_get_current_process_b() == this ) )
660     {
661         report_immediate_self_notification();
662         return false;
663     }
664 #endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS
665 
666     if( is_runnable() )
667         return true;
668 
669     // If a process is disabled then we ignore any events, leaving them enabled:
670     //
671     // But if this is a time out event we need to remove both it and the
672     // event that was being waited for.
673 
674     if ( m_state & ps_bit_disabled )
675     {
676         if ( e == m_timeout_event_p )
677 	{
678 	    remove_dynamic_events( true );
679 	    return true;
680 	}
681 	else
682 	{
683 	    return false;
684 	}
685     }
686 
687 
688     // Process based on the event type and current process state:
689     //
690     // Every case needs to set 'rc' and continue on to the end of
691     // this method to allow suspend processing to work correctly.
692 
693     switch( m_trigger_type )
694     {
695       case EVENT:
696 	m_event_p = 0;
697 	m_trigger_type = STATIC;
698 	break;
699 
700       case AND_LIST:
701         -- m_event_count;
702 	if ( m_event_count == 0 )
703 	{
704 	    m_event_list_p->auto_delete();
705 	    m_event_list_p = 0;
706 	    m_trigger_type = STATIC;
707 	}
708 	else
709 	{
710 	    return true;
711 	}
712 	break;
713 
714       case OR_LIST:
715 	m_event_list_p->remove_dynamic( this, e );
716 	m_event_list_p->auto_delete();
717 	m_event_list_p = 0;
718 	m_trigger_type = STATIC;
719 	break;
720 
721       case TIMEOUT:
722 	m_trigger_type = STATIC;
723 	break;
724 
725       case EVENT_TIMEOUT:
726         if ( e == m_timeout_event_p )
727 	{
728 	    m_timed_out = true;
729 	    m_event_p->remove_dynamic( this );
730 	    m_event_p = 0;
731 	    m_trigger_type = STATIC;
732 	}
733 	else
734 	{
735 	    m_timeout_event_p->cancel();
736 	    m_timeout_event_p->reset();
737 	    m_event_p = 0;
738 	    m_trigger_type = STATIC;
739 	}
740 	break;
741 
742       case OR_LIST_TIMEOUT:
743         if ( e == m_timeout_event_p )
744 	{
745             m_timed_out = true;
746             m_event_list_p->remove_dynamic( this, e );
747             m_event_list_p->auto_delete();
748             m_event_list_p = 0;
749             m_trigger_type = STATIC;
750 	}
751 
752 	else
753 	{
754             m_timeout_event_p->cancel();
755             m_timeout_event_p->reset();
756 	    m_event_list_p->remove_dynamic( this, e );
757 	    m_event_list_p->auto_delete();
758 	    m_event_list_p = 0;
759 	    m_trigger_type = STATIC;
760 	}
761 	break;
762 
763       case AND_LIST_TIMEOUT:
764         if ( e == m_timeout_event_p )
765 	{
766             m_timed_out = true;
767             m_event_list_p->remove_dynamic( this, e );
768             m_event_list_p->auto_delete();
769             m_event_list_p = 0;
770             m_trigger_type = STATIC;
771 	}
772 
773 	else
774 	{
775 	    -- m_event_count;
776 	    if ( m_event_count == 0 )
777 	    {
778 		m_timeout_event_p->cancel();
779 		m_timeout_event_p->reset();
780 		// no need to remove_dynamic
781 		m_event_list_p->auto_delete();
782 		m_event_list_p = 0;
783 		m_trigger_type = STATIC;
784 	    }
785 	    else
786 	    {
787 	        return true;
788 	    }
789 	}
790 	break;
791 
792       case STATIC: {
793         // we should never get here, but throw_it() can make it happen.
794 	SC_REPORT_WARNING(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_, name());
795         return true;
796       }
797     }
798 
799     // If we get here then the method has satisfied its next_trigger, if its
800     // suspended mark its state as ready to run. If its not suspended then push
801     // it onto the runnable queue.
802 
803     if ( (m_state & ps_bit_suspended) )
804     {
805 	m_state = m_state | ps_bit_ready_to_run;
806     }
807     else
808     {
809         simcontext()->push_runnable_method(this);
810     }
811 
812     return true;
813 }
814 
815 } // namespace sc_core
816 
817 
818 /*****************************************************************************
819 
820   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
821   changes you are making here.
822 
823       Name, Affiliation, Date:
824   Description of Modification:
825 
826  *****************************************************************************/
827 
828 // $Log: sc_method_process.cpp,v $
829 // Revision 1.49  2011/08/29 18:24:47  acg
830 //  Andy Goodrich: remove temporary comment flagging new preempt_with() call.
831 //
832 // Revision 1.48  2011/08/29 18:04:32  acg
833 //  Philipp A. Hartmann: miscellaneous clean ups.
834 //
835 // Revision 1.47  2011/08/24 22:05:50  acg
836 //  Torsten Maehne: initialization changes to remove warnings.
837 //
838 // Revision 1.46  2011/08/07 19:08:04  acg
839 //  Andy Goodrich: moved logs to end of file so line number synching works
840 //  better between versions.
841 //
842 // Revision 1.45  2011/07/29 22:42:45  acg
843 //  Andy Goodrich: added check_for_throws() to fix case where a method is
844 //  deleted by a process it resets or kills so that it can throw itself.
845 //  Philipp A. Hartmann: changes to handle case where a process control
846 //  invocation on a child process causes the list of child processes to change.
847 //
848 // Revision 1.44  2011/07/24 11:27:04  acg
849 //  Andy Goodrich: moved the check for unwinding processes until after the
850 //  descendants have been processed in throw_user and kill.
851 //
852 // Revision 1.43  2011/07/24 11:20:03  acg
853 //  Philipp A. Hartmann: process control error message improvements:
854 //  (1) Downgrade error to warning for re-kills of processes.
855 //  (2) Add process name to process messages.
856 //  (3) drop some superfluous colons in messages.
857 //
858 // Revision 1.42  2011/05/05 17:45:27  acg
859 //  Philip A. Hartmann: changes in WIN64 support.
860 //  Andy Goodrich: additional DEBUG_MSG instances to trace process handling.
861 //
862 // Revision 1.41  2011/04/19 19:15:41  acg
863 //  Andy Goodrich: fix so warning message is always issued for a throw_it()
864 //  on a method process.
865 //
866 // Revision 1.40  2011/04/19 15:04:27  acg
867 //  Philipp A. Hartmann: clean up SC_ID messages.
868 //
869 // Revision 1.39  2011/04/19 02:39:09  acg
870 //  Philipp A. Hartmann: added checks for additional throws during stack unwinds.
871 //
872 // Revision 1.38  2011/04/13 02:41:34  acg
873 //  Andy Goodrich: eliminate warning messages generated when the DEBUG_MSG
874 //  macro is used.
875 //
876 // Revision 1.37  2011/04/11 22:10:46  acg
877 //  Andy Goodrich:
878 //    (1) Add DEBUG_MSG macro and use it to generate a journal of method
879 //        throws if it is enabled.
880 //    (2) Trim down to the expected behavior of scheduling a method that
881 //        is asynchronously reset in anticipation of IEEE 1666 being revised.
882 //
883 // Revision 1.36  2011/04/10 22:15:29  acg
884 //  Andy Goodrich: change to call methods on asynchronous reset.
885 //
886 // Revision 1.35  2011/04/08 22:31:40  acg
887 //  Andy Goodrich: removed unused code.
888 //
889 // Revision 1.34  2011/04/08 18:24:07  acg
890 //  Andy Goodrich: fix asynchronous reset dispatch and when the reset_event()
891 //  is fired.
892 //
893 // Revision 1.33  2011/04/05 20:50:56  acg
894 //  Andy Goodrich:
895 //    (1) changes to make sure that event(), posedge() and negedge() only
896 //        return true if the clock has not moved.
897 //    (2) fixes for method self-resumes.
898 //    (3) added SC_PRERELEASE_VERSION
899 //    (4) removed kernel events from the object hierarchy, added
900 //        sc_hierarchy_name_exists().
901 //
902 // Revision 1.32  2011/04/01 22:30:39  acg
903 //  Andy Goodrich: change hard assertion to warning for trigger_dynamic()
904 //  getting called when there is only STATIC sensitivity. This can result
905 //  because of sc_process_handle::throw_it().
906 //
907 // Revision 1.31  2011/03/28 13:02:51  acg
908 //  Andy Goodrich: Changes for disable() interactions.
909 //
910 // Revision 1.30  2011/03/23 16:17:52  acg
911 //  Andy Goodrich: don't emit an error message for a resume on a disabled
912 //  process that is not suspended.
913 //
914 // Revision 1.29  2011/03/20 13:43:23  acg
915 //  Andy Goodrich: added async_signal_is() plus suspend() as a corner case.
916 //
917 // Revision 1.28  2011/03/08 20:49:30  acg
918 //  Andy Goodrich: implement coarse checking for synchronous reset - suspend
919 //  interaction.
920 //
921 // Revision 1.27  2011/03/08 20:32:28  acg
922 //  Andy Goodrich: implemented "coarse" checking for undefined process
923 //  control interactions.
924 //
925 // Revision 1.26  2011/03/07 18:25:19  acg
926 //  Andy Goodrich: tightening of check for resume on a disabled process to
927 //  only produce an error if it is ready to run.
928 //
929 // Revision 1.25  2011/03/07 17:38:43  acg
930 //  Andy Goodrich: tightening up of checks for undefined interaction between
931 //  synchronous reset and suspend.
932 //
933 // Revision 1.24  2011/03/06 23:30:13  acg
934 //  Andy Goodrich: refining suspend - sync reset corner case checking so that
935 //  the following are error situations:
936 //    (1) Calling suspend on a process with a reset_signal_is() specification
937 //        or sync_reset_on() is active.
938 //    (2) Calling sync_reset_on() on a suspended process.
939 //
940 // Revision 1.23  2011/03/06 19:57:11  acg
941 //  Andy Goodrich: refinements for the illegal suspend - synchronous reset
942 //  interaction.
943 //
944 // Revision 1.22  2011/03/06 16:47:09  acg
945 //  Andy Goodrich: changes for testing sync_reset - suspend corner cases.
946 //
947 // Revision 1.21  2011/03/06 15:57:08  acg
948 //  Andy Goodrich: added process control corner case checks.
949 //
950 // Revision 1.20  2011/03/05 19:44:20  acg
951 //  Andy Goodrich: changes for object and event naming and structures.
952 //
953 // Revision 1.19  2011/02/18 20:27:14  acg
954 //  Andy Goodrich: Updated Copyrights.
955 //
956 // Revision 1.18  2011/02/17 19:50:43  acg
957 //  Andy Goodrich:
958 //    (1) Changed signature of trigger_dynamic back to a bool.
959 //    (2) Added run queue processing into trigger dynamic.
960 //    (3) Simplified process control support.
961 //
962 // Revision 1.17  2011/02/16 22:37:30  acg
963 //  Andy Goodrich: clean up to remove need for ps_disable_pending.
964 //
965 // Revision 1.16  2011/02/13 23:09:58  acg
966 //  Andy Goodrich: only remove dynamic events for asynchronous resets.
967 //
968 // Revision 1.15  2011/02/13 21:47:37  acg
969 //  Andy Goodrich: update copyright notice.
970 //
971 // Revision 1.14  2011/02/13 21:31:02  acg
972 //  Andy Goodrich: added error messages for throws when simulator has not
973 //  been initialized. Added missing remove_dynamic_events() call to the
974 //  reset code.
975 //
976 // Revision 1.13  2011/02/11 13:25:24  acg
977 //  Andy Goodrich: Philipp A. Hartmann's changes:
978 //    (1) Removal of SC_CTHREAD method overloads.
979 //    (2) New exception processing code.
980 //
981 // Revision 1.12  2011/02/07 19:17:20  acg
982 //  Andy Goodrich: changes for IEEE 1666 compatibility.
983 //
984 // Revision 1.11  2011/02/04 15:27:36  acg
985 //  Andy Goodrich: changes for suspend-resume semantics.
986 //
987 // Revision 1.10  2011/02/01 23:01:53  acg
988 //  Andy Goodrich: removed dead code.
989 //
990 // Revision 1.9  2011/02/01 21:05:05  acg
991 //  Andy Goodrich: Changes in trigger_dynamic methods to handle new
992 //  process control rules about event sensitivity.
993 //
994 // Revision 1.8  2011/01/25 20:50:37  acg
995 //  Andy Goodrich: changes for IEEE 1666 2011.
996 //
997 // Revision 1.7  2011/01/18 20:10:44  acg
998 //  Andy Goodrich: changes for IEEE1666_2011 semantics.
999 //
1000 // Revision 1.6  2011/01/06 18:02:43  acg
1001 //  Andy Goodrich: added check for ps_disabled to method_dynamic().
1002 //
1003 // Revision 1.5  2010/11/20 17:10:56  acg
1004 //  Andy Goodrich: reset processing changes for new IEEE 1666 standard.
1005 //
1006 // Revision 1.4  2010/07/22 20:02:33  acg
1007 //  Andy Goodrich: bug fixes.
1008 //
1009 // Revision 1.3  2009/05/22 16:06:29  acg
1010 //  Andy Goodrich: process control updates.
1011 //
1012 // Revision 1.2  2008/05/22 17:06:25  acg
1013 //  Andy Goodrich: updated copyright notice to include 2008.
1014 //
1015 // Revision 1.1.1.1  2006/12/15 20:20:05  acg
1016 // SystemC 2.3
1017 //
1018 // Revision 1.7  2006/04/20 17:08:16  acg
1019 //  Andy Goodrich: 3.0 style process changes.
1020 //
1021 // Revision 1.6  2006/04/11 23:13:20  acg
1022 //   Andy Goodrich: Changes for reduced reset support that only includes
1023 //   sc_cthread, but has preliminary hooks for expanding to method and thread
1024 //   processes also.
1025 //
1026 // Revision 1.5  2006/01/26 21:04:54  acg
1027 //  Andy Goodrich: deprecation message changes and additional messages.
1028 //
1029 // Revision 1.4  2006/01/24 20:49:05  acg
1030 // Andy Goodrich: changes to remove the use of deprecated features within the
1031 // simulator, and to issue warning messages when deprecated features are used.
1032 //
1033 // Revision 1.3  2006/01/13 18:44:29  acg
1034 // Added $Log to record CVS changes into the source.
1035 //
1036