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