sc_method_process.cpp revision 12027
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