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