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