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_simcontext.cpp -- Provides a simulation context for use with multiple 23 simulations. 24 25 Original Author: Stan Y. Liao, Synopsys, Inc. 26 Martin Janssen, Synopsys, Inc. 27 28 CHANGE LOG AT THE END OF THE FILE 29 *****************************************************************************/ 30 31#include <algorithm> 32 33#define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion 34 35#include "sysc/kernel/sc_cor_fiber.h" 36#include "sysc/kernel/sc_cor_pthread.h" 37#include "sysc/kernel/sc_cor_qt.h" 38#include "sysc/kernel/sc_event.h" 39#include "sysc/kernel/sc_kernel_ids.h" 40#include "sysc/kernel/sc_module.h" 41#include "sysc/kernel/sc_module_registry.h" 42#include "sysc/kernel/sc_name_gen.h" 43#include "sysc/kernel/sc_object_manager.h" 44#include "sysc/kernel/sc_cthread_process.h" 45#include "sysc/kernel/sc_method_process.h" 46#include "sysc/kernel/sc_thread_process.h" 47#include "sysc/kernel/sc_process_handle.h" 48#include "sysc/kernel/sc_simcontext.h" 49#include "sysc/kernel/sc_simcontext_int.h" 50#include "sysc/kernel/sc_reset.h" 51#include "sysc/kernel/sc_ver.h" 52#include "sysc/kernel/sc_boost.h" 53#include "sysc/kernel/sc_spawn.h" 54#include "sysc/kernel/sc_phase_callback_registry.h" 55#include "sysc/communication/sc_port.h" 56#include "sysc/communication/sc_export.h" 57#include "sysc/communication/sc_prim_channel.h" 58#include "sysc/tracing/sc_trace.h" 59#include "sysc/utils/sc_mempool.h" 60#include "sysc/utils/sc_list.h" 61#include "sysc/utils/sc_utils_ids.h" 62 63// DEBUGGING MACROS: 64// 65// DEBUG_MSG(NAME,P,MSG) 66// MSG = message to print 67// NAME = name that must match the process for the message to print, or 68// null if the message should be printed unconditionally. 69// P = pointer to process message is for, or NULL in which case the 70// message will not print. 71#if 0 72# define DEBUG_NAME "" 73# define DEBUG_MSG(NAME,P,MSG) \ 74 { \ 75 if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ 76 std::cout << "**** " << sc_time_stamp() << " (" \ 77 << sc_get_current_process_name() << "): " << MSG \ 78 << " - " << P->name() << std::endl; \ 79 } 80#else 81# define DEBUG_MSG(NAME,P,MSG) 82#endif 83 84#if SC_HAS_PHASE_CALLBACKS_ 85# define SC_DO_PHASE_CALLBACK_( Kind ) \ 86 m_phase_cb_registry->Kind() 87#else 88# define SC_DO_PHASE_CALLBACK_( Kind ) \ 89 ((void)0) /* do nothing */ 90#endif 91 92#if defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING ) 93// use callback based tracing 94# define SC_SIMCONTEXT_TRACING_ 0 95#else 96// enable tracing via explicit trace_cycle calls from simulator loop 97# define SC_SIMCONTEXT_TRACING_ 1 98#endif 99 100namespace sc_core { 101 102sc_stop_mode stop_mode = SC_STOP_FINISH_DELTA; 103 104// ---------------------------------------------------------------------------- 105// CLASS : sc_process_table 106// 107// Container class that keeps track of all method processes, 108// (c)thread processes. 109// ---------------------------------------------------------------------------- 110 111class sc_process_table 112{ 113 public: 114 115 sc_process_table(); 116 ~sc_process_table(); 117 void push_front( sc_method_handle ); 118 void push_front( sc_thread_handle ); 119 sc_method_handle method_q_head(); 120 sc_method_handle remove( sc_method_handle ); 121 sc_thread_handle thread_q_head(); 122 sc_thread_handle remove( sc_thread_handle ); 123 124 125 private: 126 127 sc_method_handle m_method_q; // Queue of existing method processes. 128 sc_thread_handle m_thread_q; // Queue of existing thread processes. 129}; 130 131 132// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 133 134sc_process_table::sc_process_table() : m_method_q(0), m_thread_q(0) 135{} 136 137sc_process_table::~sc_process_table() 138{ 139 140 sc_method_handle method_next_p; // Next method to delete. 141 sc_method_handle method_now_p; // Method now deleting. 142 143 for( method_now_p = m_method_q; method_now_p; method_now_p = method_next_p ) 144 { 145 method_next_p = method_now_p->next_exist(); 146 delete method_now_p; 147 } 148 149 if ( m_thread_q ) 150 { 151 ::std::cout << ::std::endl 152 << "WATCH OUT!! In sc_process_table destructor. " 153 << "Threads and cthreads are not actually getting deleted here. " 154 << "Some memory may leak. Look at the comments here in " 155 << "kernel/sc_simcontext.cpp for more details." 156 << ::std::endl; 157 } 158 159 // don't delete threads and cthreads. If a (c)thread 160 // has died, then it has already been deleted. Only (c)threads created 161 // before simulation-start are in this table. Due to performance 162 // reasons, we don't look up the dying thread in the process table 163 // and remove it from there. simcontext::reset and ~simcontext invoke this 164 // destructor. At present none of these routines are ever invoked. 165 // We can delete threads and cthreads here if a dying thread figured out 166 // it was created before simulation-start and took itself off the 167 // process_table. 168 169#if 0 170 sc_thread_handle thread_next_p; // Next thread to delete. 171 sc_thread_handle thread_now_p; // Thread now deleting. 172 173 for( thread_now_p=m_thread_q; thread_now_p; thread_now_p=thread_next_p ) 174 { 175 thread_next_p = thread_now_p->next_exist(); 176 delete thread_now_p; 177 } 178#endif // 0 179} 180 181inline 182sc_method_handle 183sc_process_table::method_q_head() 184{ 185 return m_method_q; 186} 187 188inline 189void 190sc_process_table::push_front( sc_method_handle handle_ ) 191{ 192 handle_->set_next_exist(m_method_q); 193 m_method_q = handle_; 194} 195 196inline 197void 198sc_process_table::push_front( sc_thread_handle handle_ ) 199{ 200 handle_->set_next_exist(m_thread_q); 201 m_thread_q = handle_; 202} 203 204sc_method_handle 205sc_process_table::remove( sc_method_handle handle_ ) 206{ 207 sc_method_handle now_p; // Entry now examining. 208 sc_method_handle prior_p; // Entry prior to one now examining. 209 210 prior_p = 0; 211 for ( now_p = m_method_q; now_p; now_p = now_p->next_exist() ) 212 { 213 if ( now_p == handle_ ) 214 { 215 if ( prior_p ) 216 prior_p->set_next_exist( now_p->next_exist() ); 217 else 218 m_method_q = now_p->next_exist(); 219 return handle_; 220 } 221 } 222 return 0; 223} 224 225sc_thread_handle 226sc_process_table::remove( sc_thread_handle handle_ ) 227{ 228 sc_thread_handle now_p; // Entry now examining. 229 sc_thread_handle prior_p; // Entry prior to one now examining. 230 231 prior_p = 0; 232 for ( now_p = m_thread_q; now_p; now_p = now_p->next_exist() ) 233 { 234 if ( now_p == handle_ ) 235 { 236 if ( prior_p ) 237 prior_p->set_next_exist( now_p->next_exist() ); 238 else 239 m_thread_q = now_p->next_exist(); 240 return handle_; 241 } 242 } 243 return 0; 244} 245 246inline 247sc_thread_handle 248sc_process_table::thread_q_head() 249{ 250 return m_thread_q; 251} 252 253int 254sc_notify_time_compare( const void* p1, const void* p2 ) 255{ 256 const sc_event_timed* et1 = static_cast<const sc_event_timed*>( p1 ); 257 const sc_event_timed* et2 = static_cast<const sc_event_timed*>( p2 ); 258 259 const sc_time& t1 = et1->notify_time(); 260 const sc_time& t2 = et2->notify_time(); 261 262 if( t1 < t2 ) { 263 return 1; 264 } else if( t1 > t2 ) { 265 return -1; 266 } else { 267 return 0; 268 } 269} 270 271 272// +============================================================================ 273// | CLASS sc_invoke_method - class to invoke sc_method's to support 274// | sc_simcontext::preempt_with(). 275// +============================================================================ 276SC_MODULE(sc_invoke_method) 277{ 278 SC_CTOR(sc_invoke_method) 279 { 280 // remove from object hierarchy 281 detach(); 282 } 283 284 virtual ~sc_invoke_method() 285 { 286 m_invokers.resize(0); 287 } 288 289 // Method to call to execute a method's semantics. 290 291 void invoke_method( sc_method_handle method_h ) 292 { 293 sc_process_handle invoker_h; // handle for invocation thread to use. 294 std::vector<sc_process_handle>::size_type invokers_n; // number of invocation threads available. 295 296 m_method = method_h; 297 298 // There is not an invocation thread to use, so allocate one. 299 300 invokers_n = m_invokers.size(); 301 if ( invokers_n == 0 ) 302 { 303 sc_spawn_options options; 304 options.dont_initialize(); 305 options.set_stack_size(0x100000); 306 options.set_sensitivity(&m_dummy); 307 invoker_h = sc_spawn(sc_bind(&sc_invoke_method::invoker,this), 308 sc_gen_unique_name("invoker"), &options); 309 ((sc_process_b*)invoker_h)->detach(); 310 } 311 312 // There is an invocation thread to use, use the last one on the list. 313 314 else 315 { 316 invoker_h = m_invokers[invokers_n-1]; 317 m_invokers.pop_back(); 318 } 319 320 // Fire off the invocation thread to invoke the method's semantics, 321 // When it blocks put it onto the list of invocation threads that 322 // are available. 323 324 sc_get_curr_simcontext()->preempt_with( (sc_thread_handle)invoker_h ); 325 DEBUG_MSG( DEBUG_NAME, m_method, "back from preemption" ); 326 m_invokers.push_back(invoker_h); 327 } 328 329 // Thread to call method from: 330 331 void invoker() 332 { 333 sc_simcontext* csc_p = sc_get_curr_simcontext(); 334 sc_process_b* me = sc_get_current_process_b(); 335 336 DEBUG_MSG( DEBUG_NAME, me, "invoker initialization" ); 337 for (;; ) 338 { 339 DEBUG_MSG( DEBUG_NAME, m_method, "invoker executing method" ); 340 csc_p->set_curr_proc( (sc_process_b*)m_method ); 341 csc_p->get_active_invokers().push_back((sc_thread_handle)me); 342 m_method->run_process(); 343 csc_p->set_curr_proc( me ); 344 csc_p->get_active_invokers().pop_back(); 345 DEBUG_MSG( DEBUG_NAME, m_method, "back from executing method" ); 346 wait(); 347 } 348 } 349 350 sc_event m_dummy; // dummy event to wait on. 351 sc_method_handle m_method; // method to be invoked. 352 std::vector<sc_process_handle> m_invokers; // list of invoking threads. 353}; 354 355// ---------------------------------------------------------------------------- 356// CLASS : sc_simcontext 357// 358// The simulation context. 359// ---------------------------------------------------------------------------- 360 361void 362sc_simcontext::init() 363{ 364 365 // ALLOCATE VARIOUS MANAGERS AND REGISTRIES: 366 367 m_object_manager = new sc_object_manager; 368 m_module_registry = new sc_module_registry( *this ); 369 m_port_registry = new sc_port_registry( *this ); 370 m_export_registry = new sc_export_registry( *this ); 371 m_prim_channel_registry = new sc_prim_channel_registry( *this ); 372 m_phase_cb_registry = new sc_phase_callback_registry( *this ); 373 m_name_gen = new sc_name_gen; 374 m_process_table = new sc_process_table; 375 m_current_writer = 0; 376 377 378 // CHECK FOR ENVIRONMENT VARIABLES THAT MODIFY SIMULATOR EXECUTION: 379 380 const char* write_check = std::getenv("SC_SIGNAL_WRITE_CHECK"); 381 m_write_check = ( (write_check==0) || strcmp(write_check,"DISABLE") ) ? 382 true : false; 383 384 385 // FINISH INITIALIZATIONS: 386 387 reset_curr_proc(); 388 m_next_proc_id = -1; 389 m_timed_events = new sc_ppq<sc_event_timed*>( 128, sc_notify_time_compare ); 390 m_something_to_trace = false; 391 m_runnable = new sc_runnable; 392 m_collectable = new sc_process_list; 393 m_time_params = new sc_time_params; 394 m_curr_time = SC_ZERO_TIME; 395 m_max_time = SC_ZERO_TIME; 396 m_change_stamp = 0; 397 m_delta_count = 0; 398 m_forced_stop = false; 399 m_paused = false; 400 m_ready_to_simulate = false; 401 m_elaboration_done = false; 402 m_execution_phase = phase_initialize; 403 m_error = NULL; 404 m_cor_pkg = 0; 405 m_method_invoker_p = NULL; 406 m_cor = 0; 407 m_in_simulator_control = false; 408 m_start_of_simulation_called = false; 409 m_end_of_simulation_called = false; 410 m_simulation_status = SC_ELABORATION; 411} 412 413void 414sc_simcontext::clean() 415{ 416 delete m_object_manager; 417 delete m_module_registry; 418 delete m_port_registry; 419 delete m_export_registry; 420 delete m_prim_channel_registry; 421 delete m_phase_cb_registry; 422 delete m_name_gen; 423 delete m_process_table; 424 m_child_objects.resize(0); 425 m_delta_events.resize(0); 426 delete m_timed_events; 427 for( int i = m_trace_files.size() - 1; i >= 0; -- i ) { 428 delete m_trace_files[i]; 429 } 430 m_trace_files.resize(0); 431 delete m_runnable; 432 delete m_collectable; 433 delete m_time_params; 434 delete m_cor_pkg; 435 delete m_error; 436} 437 438 439sc_simcontext::sc_simcontext() : 440 m_object_manager(0), m_module_registry(0), m_port_registry(0), 441 m_export_registry(0), m_prim_channel_registry(0), 442 m_phase_cb_registry(0), m_name_gen(0), 443 m_process_table(0), m_curr_proc_info(), m_current_writer(0), 444 m_write_check(false), m_next_proc_id(-1), m_child_events(), 445 m_child_objects(), m_delta_events(), m_timed_events(0), m_trace_files(), 446 m_something_to_trace(false), m_runnable(0), m_collectable(0), 447 m_time_params(), m_curr_time(SC_ZERO_TIME), m_max_time(SC_ZERO_TIME), 448 m_change_stamp(0), m_delta_count(0), m_forced_stop(false), m_paused(false), 449 m_ready_to_simulate(false), m_elaboration_done(false), 450 m_execution_phase(phase_initialize), m_error(0), 451 m_in_simulator_control(false), m_end_of_simulation_called(false), 452 m_simulation_status(SC_ELABORATION), m_start_of_simulation_called(false), 453 m_cor_pkg(0), m_cor(0) 454{ 455 init(); 456} 457 458sc_simcontext::~sc_simcontext() 459{ 460 clean(); 461} 462 463// +---------------------------------------------------------------------------- 464// |"sc_simcontext::active_object" 465// | 466// | This method returns the currently active object with respect to 467// | additions to the hierarchy. It will be the top of the object hierarchy 468// | stack if it is non-empty, or it will be the active process, or NULL 469// | if there is no active process. 470// +---------------------------------------------------------------------------- 471sc_object* 472sc_simcontext::active_object() 473{ 474 sc_object* result_p; // pointer to return. 475 476 result_p = m_object_manager->hierarchy_curr(); 477 if ( !result_p ) 478 result_p = (sc_object*)get_curr_proc_info()->process_handle; 479 return result_p; 480} 481 482// +---------------------------------------------------------------------------- 483// |"sc_simcontext::crunch" 484// | 485// | This method implements the simulator's execution of processes. It performs 486// | one or more "delta" cycles. Each delta cycle consists of an evaluation, 487// | an update phase, and a notification phase. During the evaluation phase any 488// | processes that are ready to run are executed. After all the processes have 489// | been executed the update phase is entered. During the update phase the 490// | values of any signals that have changed are updated. After the updates 491// | have been performed the notification phase is entered. During that phase 492// | any notifications that need to occur because of of signal values changes 493// | are performed. This will result in the queueing of processes for execution 494// | that are sensitive to those notifications. At that point a delta cycle 495// | is complete, and the process is started again unless 'once' is true. 496// | 497// | Arguments: 498// | once = true if only one delta cycle is to be performed. 499// +---------------------------------------------------------------------------- 500inline void 501sc_simcontext::crunch( bool once ) 502{ 503#ifdef DEBUG_SYSTEMC 504 int num_deltas = 0; // number of delta cycles 505#endif 506 507 while ( true ) 508 { 509 510 // EVALUATE PHASE 511 512 m_execution_phase = phase_evaluate; 513 bool empty_eval_phase = true; 514 while( true ) 515 { 516 517 // execute method processes 518 519 m_runnable->toggle_methods(); 520 sc_method_handle method_h = pop_runnable_method(); 521 while( method_h != 0 ) { 522 empty_eval_phase = false; 523 if ( !method_h->run_process() ) 524 { 525 goto out; 526 } 527 method_h = pop_runnable_method(); 528 } 529 530 // execute (c)thread processes 531 532 m_runnable->toggle_threads(); 533 sc_thread_handle thread_h = pop_runnable_thread(); 534 while( thread_h != 0 ) { 535 if ( thread_h->m_cor_p != NULL ) break; 536 thread_h = pop_runnable_thread(); 537 } 538 539 if( thread_h != 0 ) { 540 empty_eval_phase = false; 541 m_cor_pkg->yield( thread_h->m_cor_p ); 542 } 543 if( m_error ) { 544 goto out; 545 } 546 547 // check for call(s) to sc_stop 548 if( m_forced_stop ) { 549 if ( stop_mode == SC_STOP_IMMEDIATE ) goto out; 550 } 551 552 // no more runnable processes 553 554 if( m_runnable->is_empty() ) { 555 break; 556 } 557 } 558 559 // remove finally dead zombies: 560 561 while( ! m_collectable->empty() ) 562 { 563 sc_process_b* del_p = m_collectable->front(); 564 m_collectable->pop_front(); 565 del_p->reference_decrement(); 566 } 567 568 569 // UPDATE PHASE 570 // 571 // The change stamp must be updated first so that event_occurred() 572 // will work. 573 574 m_execution_phase = phase_update; 575 if ( !empty_eval_phase ) 576 { 577// SC_DO_PHASE_CALLBACK_(evaluation_done); 578 m_change_stamp++; 579 m_delta_count ++; 580 } 581 m_prim_channel_registry->perform_update(); 582 SC_DO_PHASE_CALLBACK_(update_done); 583 m_execution_phase = phase_notify; 584 585#if SC_SIMCONTEXT_TRACING_ 586 if( m_something_to_trace ) { 587 trace_cycle( /* delta cycle? */ true ); 588 } 589#endif 590 591 // check for call(s) to sc_stop 592 if( m_forced_stop ) { 593 break; 594 } 595 596#ifdef DEBUG_SYSTEMC 597 // check for possible infinite loops 598 if( ++ num_deltas > SC_MAX_NUM_DELTA_CYCLES ) { 599 ::std::cerr << "SystemC warning: " 600 << "the number of delta cycles exceeds the limit of " 601 << SC_MAX_NUM_DELTA_CYCLES 602 << ", defined in sc_constants.h.\n" 603 << "This is a possible sign of an infinite loop.\n" 604 << "Increase the limit if this warning is invalid.\n"; 605 break; 606 } 607#endif 608 609 // NOTIFICATION PHASE: 610 // 611 // Process delta notifications which will queue processes for 612 // subsequent execution. 613 614 int size = m_delta_events.size(); 615 if ( size != 0 ) 616 { 617 sc_event** l_events = &m_delta_events[0]; 618 int i = size - 1; 619 do { 620 l_events[i]->trigger(); 621 } while( -- i >= 0 ); 622 m_delta_events.resize(0); 623 } 624 625 if( m_runnable->is_empty() ) { 626 // no more runnable processes 627 break; 628 } 629 630 // if sc_pause() was called we are done. 631 632 if ( m_paused ) break; 633 634 // IF ONLY DOING ONE CYCLE, WE ARE DONE. OTHERWISE EXECUTE NEW CALLBACKS 635 636 if ( once ) break; 637 } 638 639 // When this point is reached the processing of delta cycles is complete, 640 // if the completion was because of an error throw the exception specified 641 // by '*m_error'. 642out: 643 this->reset_curr_proc(); 644 if( m_error ) throw *m_error; // re-throw propagated error 645} 646 647inline 648void 649sc_simcontext::cycle( const sc_time& t) 650{ 651 sc_time next_event_time; 652 653 m_in_simulator_control = true; 654 crunch(); 655 SC_DO_PHASE_CALLBACK_(before_timestep); 656#if SC_SIMCONTEXT_TRACING_ 657 if( m_something_to_trace ) { 658 trace_cycle( /* delta cycle? */ false ); 659 } 660#endif 661 m_curr_time += t; 662 if ( next_time(next_event_time) && next_event_time <= m_curr_time) { 663 SC_REPORT_WARNING(SC_ID_CYCLE_MISSES_EVENTS_, ""); 664 } 665 m_in_simulator_control = false; 666 SC_DO_PHASE_CALLBACK_(simulation_paused); 667} 668 669void 670sc_simcontext::elaborate() 671{ 672 if( m_elaboration_done || sim_status() != SC_SIM_OK ) { 673 return; 674 } 675 676 // Instantiate the method invocation module 677 // (not added to public object hierarchy) 678 679 m_method_invoker_p = 680 new sc_invoke_method("$$$$kernel_module$$$$_invoke_method" ); 681 682 m_simulation_status = SC_BEFORE_END_OF_ELABORATION; 683 for( int cd = 0; cd != 4; /* empty */ ) 684 { 685 cd = m_port_registry->construction_done(); 686 cd += m_export_registry->construction_done(); 687 cd += m_prim_channel_registry->construction_done(); 688 cd += m_module_registry->construction_done(); 689 690 // check for call(s) to sc_stop 691 if( m_forced_stop ) { 692 do_sc_stop_action(); 693 return; 694 } 695 696 } 697 SC_DO_PHASE_CALLBACK_(construction_done); 698 699 // SIGNAL THAT ELABORATION IS DONE 700 // 701 // We set the switch before the calls in case someone creates a process 702 // in an end_of_elaboration callback. We need the information to flag 703 // the process as being dynamic. 704 705 m_elaboration_done = true; 706 m_simulation_status = SC_END_OF_ELABORATION; 707 708 m_port_registry->elaboration_done(); 709 m_export_registry->elaboration_done(); 710 m_prim_channel_registry->elaboration_done(); 711 m_module_registry->elaboration_done(); 712 SC_DO_PHASE_CALLBACK_(elaboration_done); 713 sc_reset::reconcile_resets(); 714 715 // check for call(s) to sc_stop 716 if( m_forced_stop ) { 717 do_sc_stop_action(); 718 return; 719 } 720} 721 722void 723sc_simcontext::prepare_to_simulate() 724{ 725 sc_method_handle method_p; // Pointer to method process accessing. 726 sc_thread_handle thread_p; // Pointer to thread process accessing. 727 728 if( m_ready_to_simulate || sim_status() != SC_SIM_OK ) { 729 return; 730 } 731 732 // instantiate the coroutine package 733 m_cor_pkg = new sc_cor_pkg_t( this ); 734 m_cor = m_cor_pkg->get_main(); 735 736 // NOTIFY ALL OBJECTS THAT SIMULATION IS ABOUT TO START: 737 738 m_simulation_status = SC_START_OF_SIMULATION; 739 m_port_registry->start_simulation(); 740 m_export_registry->start_simulation(); 741 m_prim_channel_registry->start_simulation(); 742 m_module_registry->start_simulation(); 743 SC_DO_PHASE_CALLBACK_(start_simulation); 744 m_start_of_simulation_called = true; 745 746 // CHECK FOR CALL(S) TO sc_stop 747 748 if( m_forced_stop ) { 749 do_sc_stop_action(); 750 return; 751 } 752 753 // PREPARE ALL (C)THREAD PROCESSES FOR SIMULATION: 754 755 for ( thread_p = m_process_table->thread_q_head(); 756 thread_p; thread_p = thread_p->next_exist() ) 757 { 758 thread_p->prepare_for_simulation(); 759 } 760 761 m_simulation_status = SC_RUNNING; 762 m_ready_to_simulate = true; 763 m_runnable->init(); 764 765 // update phase 766 767 m_execution_phase = phase_update; 768 m_prim_channel_registry->perform_update(); 769 m_execution_phase = phase_notify; 770 771 int size; 772 773 // make all method processes runnable 774 775 for ( method_p = m_process_table->method_q_head(); 776 method_p; method_p = method_p->next_exist() ) 777 { 778 if ( ((method_p->m_state & sc_process_b::ps_bit_disabled) != 0) || 779 method_p->dont_initialize() ) 780 { 781 if ( method_p->m_static_events.size() == 0 ) 782 { 783 SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, 784 method_p->name() ); 785 } 786 } 787 else if ( (method_p->m_state & sc_process_b::ps_bit_suspended) == 0) 788 { 789 push_runnable_method_front( method_p ); 790 } 791 else 792 { 793 method_p->m_state |= sc_process_b::ps_bit_ready_to_run; 794 } 795 } 796 797 // make thread processes runnable 798 // (cthread processes always have the dont_initialize flag set) 799 800 for ( thread_p = m_process_table->thread_q_head(); 801 thread_p; thread_p = thread_p->next_exist() ) 802 { 803 if ( ((thread_p->m_state & sc_process_b::ps_bit_disabled) != 0) || 804 thread_p->dont_initialize() ) 805 { 806 if ( thread_p->m_static_events.size() == 0 ) 807 { 808 SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, 809 thread_p->name() ); 810 } 811 } 812 else if ( (thread_p->m_state & sc_process_b::ps_bit_suspended) == 0) 813 { 814 push_runnable_thread_front( thread_p ); 815 } 816 else 817 { 818 thread_p->m_state |= sc_process_b::ps_bit_ready_to_run; 819 } 820 } 821 822 823 // process delta notifications 824 825 if( ( size = m_delta_events.size() ) != 0 ) { 826 sc_event** l_delta_events = &m_delta_events[0]; 827 int i = size - 1; 828 do { 829 l_delta_events[i]->trigger(); 830 } while( -- i >= 0 ); 831 m_delta_events.resize(0); 832 } 833 834 SC_DO_PHASE_CALLBACK_(initialization_done); 835} 836 837void 838sc_simcontext::initial_crunch( bool no_crunch ) 839{ 840 if( no_crunch || m_runnable->is_empty() ) { 841 return; 842 } 843 844 // run the delta cycle loop 845 846 crunch(); 847 if( m_error ) { 848 return; 849 } 850 851#if SC_SIMCONTEXT_TRACING_ 852 if( m_something_to_trace ) { 853 trace_cycle( false ); 854 } 855#endif 856 857 // check for call(s) to sc_stop 858 if( m_forced_stop ) { 859 do_sc_stop_action(); 860 } 861} 862 863void 864sc_simcontext::initialize( bool no_crunch ) 865{ 866 m_in_simulator_control = true; 867 elaborate(); 868 869 prepare_to_simulate(); 870 initial_crunch(no_crunch); 871 m_in_simulator_control = false; 872} 873 874// +---------------------------------------------------------------------------- 875// |"sc_simcontext::simulate" 876// | 877// | This method runs the simulation for the specified amount of time. 878// | 879// | Notes: 880// | (1) This code always run with an SC_EXIT_ON_STARVATION starvation policy, 881// | so the simulation time on return will be the minimum of the 882// | simulation on entry plus the duration, and the maximum time of any 883// | event present in the simulation. If the simulation policy is 884// | SC_RUN_TO_TIME starvation it is implemented by the caller of this 885// | method, e.g., sc_start(), by artificially setting the simulation 886// | time forward after this method completes. 887// | 888// | Arguments: 889// | duration = amount of time to simulate. 890// +---------------------------------------------------------------------------- 891void 892sc_simcontext::simulate( const sc_time& duration ) 893{ 894 initialize( true ); 895 896 if (sim_status() != SC_SIM_OK) { 897 return; 898 } 899 900 sc_time non_overflow_time = sc_max_time() - m_curr_time; 901 if ( duration > non_overflow_time ) 902 { 903 SC_REPORT_ERROR(SC_ID_SIMULATION_TIME_OVERFLOW_, ""); 904 return; 905 } 906 else if ( duration < SC_ZERO_TIME ) 907 { 908 SC_REPORT_ERROR(SC_ID_NEGATIVE_SIMULATION_TIME_,""); 909 } 910 911 m_in_simulator_control = true; 912 m_paused = false; 913 914 sc_time until_t = m_curr_time + duration; 915 sc_time t; // current simulaton time. 916 917 // IF DURATION WAS ZERO WE ONLY CRUNCH ONCE: 918 // 919 // We duplicate the code so that we don't add the overhead of the 920 // check to each loop in the do below. 921 if ( duration == SC_ZERO_TIME ) 922 { 923 m_in_simulator_control = true; 924 crunch( true ); 925 if( m_error ) { 926 m_in_simulator_control = false; 927 return; 928 } 929#if SC_SIMCONTEXT_TRACING_ 930 if( m_something_to_trace ) 931 trace_cycle( /* delta cycle? */ false ); 932#endif 933 if( m_forced_stop ) { 934 do_sc_stop_action(); 935 return; 936 } 937 // return via implicit pause 938 goto exit_pause; 939 } 940 941 // NON-ZERO DURATION: EXECUTE UP TO THAT TIME, OR UNTIL EVENT STARVATION: 942 943 do { 944 945 crunch(); 946 if( m_error ) { 947 m_in_simulator_control = false; 948 return; 949 } 950#if SC_SIMCONTEXT_TRACING_ 951 if( m_something_to_trace ) { 952 trace_cycle( false ); 953 } 954#endif 955 // check for call(s) to sc_stop() or sc_pause(). 956 if( m_forced_stop ) { 957 do_sc_stop_action(); 958 return; 959 } 960 if( m_paused ) goto exit_pause; // return explicit pause 961 962 t = m_curr_time; 963 964 do { 965 // See note 1 above: 966 967 if ( !next_time(t) || (t > until_t ) ) goto exit_time; 968 if ( t > m_curr_time ) 969 { 970 SC_DO_PHASE_CALLBACK_(before_timestep); 971 m_curr_time = t; 972 m_change_stamp++; 973 } 974 975 // PROCESS TIMED NOTIFICATIONS AT THE CURRENT TIME 976 977 do { 978 sc_event_timed* et = m_timed_events->extract_top(); 979 sc_event* e = et->event(); 980 delete et; 981 if( e != 0 ) { 982 e->trigger(); 983 } 984 } while( m_timed_events->size() && 985 m_timed_events->top()->notify_time() == t ); 986 987 } while( m_runnable->is_empty() ); 988 } while ( t < until_t ); // hold off on the delta for the until_t time. 989 990exit_time: // final simulation time update, if needed 991 if ( t > m_curr_time && t <= until_t ) 992 { 993 SC_DO_PHASE_CALLBACK_(before_timestep); 994 m_curr_time = t; 995 m_change_stamp++; 996 } 997exit_pause: // call pause callback upon implicit or explicit pause 998 m_execution_phase = phase_evaluate; 999 m_in_simulator_control = false; 1000 SC_DO_PHASE_CALLBACK_(simulation_paused); 1001} 1002 1003void 1004sc_simcontext::do_sc_stop_action() 1005{ 1006 SC_REPORT_INFO("/OSCI/SystemC","Simulation stopped by user."); 1007 if (m_start_of_simulation_called) { 1008 end(); 1009 m_in_simulator_control = false; 1010 } 1011 m_simulation_status = SC_STOPPED; 1012 SC_DO_PHASE_CALLBACK_(simulation_stopped); 1013} 1014 1015void 1016sc_simcontext::mark_to_collect_process( sc_process_b* zombie ) 1017{ 1018 m_collectable->push_back( zombie ); 1019} 1020 1021 1022//------------------------------------------------------------------------------ 1023//"sc_simcontext::stop" 1024// 1025// This method stops the simulator after some amount of further processing. 1026// How much processing is done depends upon the value of the global variable 1027// stop_mode: 1028// SC_STOP_IMMEDIATE - aborts the execution phase of the current delta 1029// cycle and performs whatever updates are pending. 1030// SC_STOP_FINISH_DELTA - finishes the current delta cycle - both execution 1031// and updates. 1032// If sc_stop is called outside of the purview of the simulator kernel 1033// (e.g., directly from sc_main), the end of simulation notifications 1034// are performed. From within the purview of the simulator kernel, these 1035// will be performed at a later time. 1036//------------------------------------------------------------------------------ 1037 1038void 1039sc_simcontext::stop() 1040{ 1041 static bool stop_warning_issued = false; 1042 if (m_forced_stop) 1043 { 1044 if ( !stop_warning_issued ) 1045 { 1046 stop_warning_issued = true; // This must be before the WARNING!!! 1047 SC_REPORT_WARNING(SC_ID_SIMULATION_STOP_CALLED_TWICE_, ""); 1048 } 1049 return; 1050 } 1051 if ( stop_mode == SC_STOP_IMMEDIATE ) m_runnable->init(); 1052 m_forced_stop = true; 1053 if ( !m_in_simulator_control ) 1054 { 1055 do_sc_stop_action(); 1056 } 1057} 1058 1059void 1060sc_simcontext::reset() 1061{ 1062 clean(); 1063 init(); 1064} 1065 1066void 1067sc_simcontext::end() 1068{ 1069 m_simulation_status = SC_END_OF_SIMULATION; 1070 m_ready_to_simulate = false; 1071 m_port_registry->simulation_done(); 1072 m_export_registry->simulation_done(); 1073 m_prim_channel_registry->simulation_done(); 1074 m_module_registry->simulation_done(); 1075 SC_DO_PHASE_CALLBACK_(simulation_done); 1076 m_end_of_simulation_called = true; 1077} 1078 1079void 1080sc_simcontext::hierarchy_push( sc_module* mod ) 1081{ 1082 m_object_manager->hierarchy_push( mod ); 1083} 1084 1085sc_module* 1086sc_simcontext::hierarchy_pop() 1087{ 1088 return static_cast<sc_module*>( m_object_manager->hierarchy_pop() ); 1089} 1090 1091sc_module* 1092sc_simcontext::hierarchy_curr() const 1093{ 1094 return static_cast<sc_module*>( m_object_manager->hierarchy_curr() ); 1095} 1096 1097sc_object* 1098sc_simcontext::first_object() 1099{ 1100 return m_object_manager->first_object(); 1101} 1102 1103sc_object* 1104sc_simcontext::next_object() 1105{ 1106 return m_object_manager->next_object(); 1107} 1108 1109sc_object* 1110sc_simcontext::find_object( const char* name ) 1111{ 1112 static bool warn_find_object=true; 1113 if ( warn_find_object ) 1114 { 1115 warn_find_object = false; 1116 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 1117 "sc_simcontext::find_object() is deprecated,\n" \ 1118 " use sc_find_object()" ); 1119 } 1120 return m_object_manager->find_object( name ); 1121} 1122 1123// to generate unique names for objects in an MT-Safe way 1124 1125const char* 1126sc_simcontext::gen_unique_name( const char* basename_, bool preserve_first ) 1127{ 1128 return m_name_gen->gen_unique_name( basename_, preserve_first ); 1129} 1130 1131 1132sc_process_handle 1133sc_simcontext::create_cthread_process( 1134 const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, 1135 sc_process_host* host_p, const sc_spawn_options* opt_p ) 1136{ 1137 sc_thread_handle handle = 1138 new sc_cthread_process(name_p, free_host, method_p, host_p, opt_p); 1139 if ( m_ready_to_simulate ) 1140 { 1141 handle->prepare_for_simulation(); 1142 } else { 1143 m_process_table->push_front( handle ); 1144 } 1145 return sc_process_handle(handle); 1146} 1147 1148 1149sc_process_handle 1150sc_simcontext::create_method_process( 1151 const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, 1152 sc_process_host* host_p, const sc_spawn_options* opt_p ) 1153{ 1154 sc_method_handle handle = 1155 new sc_method_process(name_p, free_host, method_p, host_p, opt_p); 1156 if ( m_ready_to_simulate ) { // dynamic process 1157 if ( !handle->dont_initialize() ) 1158 { 1159#ifdef SC_HAS_PHASE_CALLBACKS_ 1160 if( SC_UNLIKELY_( m_simulation_status 1161 & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) 1162 { 1163 std::stringstream msg; 1164 msg << m_simulation_status 1165 << ":\n\t immediate method spawning of " 1166 "`" << handle->name() << "' ignored"; 1167 SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ 1168 , msg.str().c_str() ); 1169 } 1170 else 1171#endif // SC_HAS_PHASE_CALLBACKS_ 1172 { 1173 push_runnable_method( handle ); 1174 } 1175 } 1176 else if ( handle->m_static_events.size() == 0 ) 1177 { 1178 SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, 1179 handle->name() ); 1180 } 1181 1182 } else { 1183 m_process_table->push_front( handle ); 1184 } 1185 return sc_process_handle(handle); 1186} 1187 1188 1189sc_process_handle 1190sc_simcontext::create_thread_process( 1191 const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, 1192 sc_process_host* host_p, const sc_spawn_options* opt_p ) 1193{ 1194 sc_thread_handle handle = 1195 new sc_thread_process(name_p, free_host, method_p, host_p, opt_p); 1196 if ( m_ready_to_simulate ) { // dynamic process 1197 handle->prepare_for_simulation(); 1198 if ( !handle->dont_initialize() ) 1199 { 1200#ifdef SC_HAS_PHASE_CALLBACKS_ 1201 if( SC_UNLIKELY_( m_simulation_status 1202 & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) 1203 { 1204 std::stringstream msg; 1205 msg << m_simulation_status 1206 << ":\n\t immediate thread spawning of " 1207 "`" << handle->name() << "' ignored"; 1208 SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ 1209 , msg.str().c_str() ); 1210 } 1211 else 1212#endif // SC_HAS_PHASE_CALLBACKS_ 1213 { 1214 push_runnable_thread( handle ); 1215 } 1216 } 1217 else if ( handle->m_static_events.size() == 0 ) 1218 { 1219 SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, 1220 handle->name() ); 1221 } 1222 1223 } else { 1224 m_process_table->push_front( handle ); 1225 } 1226 return sc_process_handle(handle); 1227} 1228 1229void 1230sc_simcontext::add_trace_file( sc_trace_file* tf ) 1231{ 1232 m_trace_files.push_back( tf ); 1233 m_something_to_trace = true; 1234} 1235 1236void 1237sc_simcontext::remove_trace_file( sc_trace_file* tf ) 1238{ 1239 m_trace_files.erase( 1240 std::remove( m_trace_files.begin(), m_trace_files.end(), tf ) 1241 ); 1242 m_something_to_trace = ( m_trace_files.size() > 0 ); 1243} 1244 1245sc_cor* 1246sc_simcontext::next_cor() 1247{ 1248 if( m_error ) { 1249 return m_cor; 1250 } 1251 1252 sc_thread_handle thread_h = pop_runnable_thread(); 1253 while( thread_h != 0 ) { 1254 if ( thread_h->m_cor_p != NULL ) break; 1255 thread_h = pop_runnable_thread(); 1256 } 1257 1258 if( thread_h != 0 ) { 1259 return thread_h->m_cor_p; 1260 } else { 1261 return m_cor; 1262 } 1263} 1264 1265const ::std::vector<sc_object*>& 1266sc_simcontext::get_child_objects() const 1267{ 1268 static bool warn_get_child_objects=true; 1269 if ( warn_get_child_objects ) 1270 { 1271 warn_get_child_objects = false; 1272 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 1273 "sc_simcontext::get_child_objects() is deprecated,\n" \ 1274 " use sc_get_top_level_objects()" ); 1275 } 1276 return m_child_objects; 1277} 1278 1279void 1280sc_simcontext::add_child_event( sc_event* event_ ) 1281{ 1282 // no check if object_ is already in the set 1283 m_child_events.push_back( event_ ); 1284} 1285 1286void 1287sc_simcontext::add_child_object( sc_object* object_ ) 1288{ 1289 // no check if object_ is already in the set 1290 m_child_objects.push_back( object_ ); 1291} 1292 1293void 1294sc_simcontext::remove_child_event( sc_event* event_ ) 1295{ 1296 int size = m_child_events.size(); 1297 for( int i = 0; i < size; ++ i ) { 1298 if( event_ == m_child_events[i] ) { 1299 m_child_events[i] = m_child_events[size - 1]; 1300 m_child_events.resize(size-1); 1301 return; 1302 } 1303 } 1304 // no check if event_ is really in the set 1305} 1306 1307void 1308sc_simcontext::remove_child_object( sc_object* object_ ) 1309{ 1310 int size = m_child_objects.size(); 1311 for( int i = 0; i < size; ++ i ) { 1312 if( object_ == m_child_objects[i] ) { 1313 m_child_objects[i] = m_child_objects[size - 1]; 1314 m_child_objects.resize(size-1); 1315 return; 1316 } 1317 } 1318 // no check if object_ is really in the set 1319} 1320 1321sc_dt::uint64 1322sc_simcontext::delta_count() const 1323{ 1324 static bool warn_delta_count=true; 1325 if ( warn_delta_count ) 1326 { 1327 warn_delta_count = false; 1328 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 1329 "sc_simcontext::delta_count() is deprecated, use sc_delta_count()" ); 1330 } 1331 return m_delta_count; 1332} 1333 1334bool 1335sc_simcontext::is_running() const 1336{ 1337 static bool warn_is_running=true; 1338 if ( warn_is_running ) 1339 { 1340 warn_is_running = false; 1341 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 1342 "sc_simcontext::is_running() is deprecated, use sc_is_running()" ); 1343 } 1344 return m_ready_to_simulate; 1345} 1346 1347// +---------------------------------------------------------------------------- 1348// |"sc_simcontext::next_time" 1349// | 1350// | This method returns the time of the next event. If there are no events 1351// | it returns false. 1352// | 1353// | Arguments: 1354// | result = where to place time of the next event, if no event is 1355// | found this value will not be changed. 1356// | Result is true if an event is found, false if not. 1357// +---------------------------------------------------------------------------- 1358bool 1359sc_simcontext::next_time( sc_time& result ) const 1360{ 1361 while( m_timed_events->size() ) { 1362 sc_event_timed* et = m_timed_events->top(); 1363 if( et->event() != 0 ) { 1364 result = et->notify_time(); 1365 return true; 1366 } 1367 delete m_timed_events->extract_top(); 1368 } 1369 return false; 1370} 1371 1372void 1373sc_simcontext::remove_delta_event( sc_event* e ) 1374{ 1375 int i = e->m_delta_event_index; 1376 int j = m_delta_events.size() - 1; 1377 assert( i >= 0 && i <= j ); 1378 if( i != j ) { 1379 sc_event** l_delta_events = &m_delta_events[0]; 1380 l_delta_events[i] = l_delta_events[j]; 1381 l_delta_events[i]->m_delta_event_index = i; 1382 } 1383 m_delta_events.resize(m_delta_events.size()-1); 1384 e->m_delta_event_index = -1; 1385} 1386 1387// +---------------------------------------------------------------------------- 1388// |"sc_simcontext::preempt_with" 1389// | 1390// | This method executes the supplied method immediately, suspending the 1391// | caller. After executing the supplied method the caller's execution will 1392// | be restored. It is used to allow a method to immediately throw an 1393// | exception, e.g., when the method's kill_process() method was called. 1394// | There are three cases to consider: 1395// | (1) The caller is a method, e.g., murder by method. 1396// | (2) The caller is a thread instance, e.g., murder by thread. 1397// | (3) The caller is this method instance, e.g., suicide. 1398// | 1399// | Arguments: 1400// | method_h -> method to be executed. 1401// +---------------------------------------------------------------------------- 1402void 1403sc_simcontext::preempt_with( sc_method_handle method_h ) 1404{ 1405 sc_curr_proc_info caller_info; // process info for caller. 1406 sc_method_handle active_method_h; // active method or null. 1407 sc_thread_handle active_thread_h; // active thread or null. 1408 1409 // Determine the active process and take the thread to be run off the 1410 // run queue, if its there, since we will be explicitly causing its 1411 // execution. 1412 1413 active_method_h = DCAST<sc_method_handle>(sc_get_current_process_b()); 1414 active_thread_h = DCAST<sc_thread_handle>(sc_get_current_process_b()); 1415 if ( method_h->next_runnable() != NULL ) 1416 remove_runnable_method( method_h ); 1417 1418 // CALLER IS THE METHOD TO BE RUN: 1419 // 1420 // Should never get here, ignore it unless we are debugging. 1421 1422 if ( method_h == active_method_h ) 1423 { 1424 DEBUG_MSG(DEBUG_NAME,method_h,"self preemption of active method"); 1425 } 1426 1427 // THE CALLER IS A METHOD: 1428 // 1429 // (a) Set the current process information to our method. 1430 // (b) Invoke our method directly by-passing the run queue. 1431 // (c) Restore the process info to the caller. 1432 // (d) Check to see if the calling method should throw an exception 1433 // because of activity that occurred during the preemption. 1434 1435 else if ( active_method_h != NULL ) 1436 { 1437 caller_info = m_curr_proc_info; 1438 DEBUG_MSG( DEBUG_NAME, method_h, 1439 "preempting active method with method" ); 1440 sc_get_curr_simcontext()->set_curr_proc( (sc_process_b*)method_h ); 1441 method_h->run_process(); 1442 sc_get_curr_simcontext()->set_curr_proc((sc_process_b*)active_method_h); 1443 active_method_h->check_for_throws(); 1444 } 1445 1446 // CALLER IS A THREAD: 1447 // 1448 // (a) Use an invocation thread to execute the method. 1449 1450 else if ( active_thread_h != NULL ) 1451 { 1452 DEBUG_MSG( DEBUG_NAME, method_h, 1453 "preempting active thread with method" ); 1454 m_method_invoker_p->invoke_method(method_h); 1455 } 1456 1457 // CALLER IS THE SIMULATOR: 1458 // 1459 // That is not allowed. 1460 1461 else 1462 { 1463 caller_info = m_curr_proc_info; 1464 DEBUG_MSG( DEBUG_NAME, method_h, 1465 "preempting no active process with method" ); 1466 sc_get_curr_simcontext()->set_curr_proc( (sc_process_b*)method_h ); 1467 method_h->run_process(); 1468 m_curr_proc_info = caller_info; 1469 } 1470} 1471 1472//------------------------------------------------------------------------------ 1473//"sc_simcontext::requeue_current_process" 1474// 1475// This method requeues the current process at the beginning of the run queue 1476// if it is a thread. This is called by sc_process_handle::throw_it() to assure 1477// that a thread that is issuing a throw will execute immediately after the 1478// processes it notifies via the throw. 1479//------------------------------------------------------------------------------ 1480void sc_simcontext::requeue_current_process() 1481{ 1482 sc_thread_handle thread_p; 1483 thread_p = DCAST<sc_thread_handle>(get_curr_proc_info()->process_handle); 1484 if ( thread_p ) 1485 { 1486 execute_thread_next( thread_p ); 1487 } 1488} 1489 1490//------------------------------------------------------------------------------ 1491//"sc_simcontext::suspend_current_process" 1492// 1493// This method suspends the current process if it is a thread. This is called 1494// by sc_process_handle::throw_it() to allow the processes that have received 1495// a throw to execute. 1496//------------------------------------------------------------------------------ 1497void sc_simcontext::suspend_current_process() 1498{ 1499 sc_thread_handle thread_p; 1500 thread_p = DCAST<sc_thread_handle>(get_curr_proc_info()->process_handle); 1501 if ( thread_p ) 1502 { 1503 thread_p->suspend_me(); 1504 } 1505} 1506 1507void 1508sc_simcontext::trace_cycle( bool delta_cycle ) 1509{ 1510 int size; 1511 if( ( size = m_trace_files.size() ) != 0 ) { 1512 sc_trace_file** l_trace_files = &m_trace_files[0]; 1513 int i = size - 1; 1514 do { 1515 l_trace_files[i]->cycle( delta_cycle ); 1516 } while( -- i >= 0 ); 1517 } 1518} 1519 1520// ---------------------------------------------------------------------------- 1521 1522#if 1 1523#ifdef PURIFY 1524 static sc_simcontext sc_default_global_context; 1525 sc_simcontext* sc_curr_simcontext = &sc_default_global_context; 1526#else 1527 sc_simcontext* sc_curr_simcontext = 0; 1528 sc_simcontext* sc_default_global_context = 0; 1529#endif 1530#else 1531// Not MT-safe! 1532static sc_simcontext* sc_curr_simcontext = 0; 1533 1534 1535sc_simcontext* 1536sc_get_curr_simcontext() 1537{ 1538 if( sc_curr_simcontext == 0 ) { 1539#ifdef PURIFY 1540 static sc_simcontext sc_default_global_context; 1541 sc_curr_simcontext = &sc_default_global_context; 1542#else 1543 static sc_simcontext* sc_default_global_context = new sc_simcontext; 1544 sc_curr_simcontext = sc_default_global_context; 1545#endif 1546 } 1547 return sc_curr_simcontext; 1548} 1549#endif // 0 1550 1551// Generates unique names within each module. 1552 1553const char* 1554sc_gen_unique_name( const char* basename_, bool preserve_first ) 1555{ 1556 sc_simcontext* simc = sc_get_curr_simcontext(); 1557 sc_module* curr_module = simc->hierarchy_curr(); 1558 if( curr_module != 0 ) { 1559 return curr_module->gen_unique_name( basename_, preserve_first ); 1560 } else { 1561 sc_process_b* curr_proc_p = sc_get_current_process_b(); 1562 if ( curr_proc_p ) 1563 { 1564 return curr_proc_p->gen_unique_name( basename_, preserve_first ); 1565 } 1566 else 1567 { 1568 return simc->gen_unique_name( basename_, preserve_first ); 1569 } 1570 } 1571} 1572 1573// Get a handle for the current process 1574// 1575// Note that this method should not be called if the current process is 1576// in the act of being deleted, it will mess up the reference count management 1577// of sc_process_b instance the handle represents. Instead, use the a 1578// pointer to the raw sc_process_b instance, which may be acquired via 1579// sc_get_current_process_b(). 1580 1581sc_process_handle 1582sc_get_current_process_handle() 1583{ 1584 return ( sc_is_running() ) ? 1585 sc_process_handle(sc_get_current_process_b()) : 1586 sc_get_last_created_process_handle(); 1587} 1588 1589// THE FOLLOWING FUNCTION IS DEPRECATED IN 2.1 1590sc_process_b* 1591sc_get_curr_process_handle() 1592{ 1593 static bool warn=true; 1594 if ( warn ) 1595 { 1596 warn = false; 1597 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 1598 "sc_get_curr_process_handle deprecated use sc_get_current_process_handle" 1599 ); 1600 } 1601 1602 return sc_get_curr_simcontext()->get_curr_proc_info()->process_handle; 1603} 1604 1605// Return indication if there are more processes to execute in this delta phase 1606 1607bool 1608sc_simcontext::pending_activity_at_current_time() const 1609{ 1610 return ( m_delta_events.size() != 0) || 1611 ( m_runnable->is_initialized() && !m_runnable->is_empty() ) || 1612 m_prim_channel_registry->pending_updates(); 1613} 1614 1615// Return time of next activity. 1616 1617sc_time sc_time_to_pending_activity( const sc_simcontext* simc_p ) 1618{ 1619 // If there is an activity pending at the current time 1620 // return a delta of zero. 1621 1622 sc_time result=SC_ZERO_TIME; // time of pending activity. 1623 1624 if ( simc_p->pending_activity_at_current_time() ) 1625 { 1626 return result; 1627 } 1628 1629 // Any activity will take place in the future pick up the next event's time. 1630 1631 else 1632 { 1633 result = simc_p->max_time(); 1634 simc_p->next_time(result); 1635 result -= sc_time_stamp(); 1636 } 1637 return result; 1638} 1639 1640// Set the random seed for controlled randomization -- not yet implemented 1641 1642void 1643sc_set_random_seed( unsigned int ) 1644{ 1645 SC_REPORT_WARNING( SC_ID_NOT_IMPLEMENTED_, 1646 "void sc_set_random_seed( unsigned int )" ); 1647} 1648 1649 1650// +---------------------------------------------------------------------------- 1651// |"sc_start" 1652// | 1653// | This function starts, or restarts, the execution of the simulator. 1654// | 1655// | Arguments: 1656// | duration = the amount of time the simulator should execute. 1657// | p = event starvation policy. 1658// +---------------------------------------------------------------------------- 1659void 1660sc_start( const sc_time& duration, sc_starvation_policy p ) 1661{ 1662 sc_simcontext* context_p; // current simulation context. 1663 sc_time entry_time; // simulation time upon entry. 1664 sc_time exit_time; // simulation time to set upon exit. 1665 sc_dt::uint64 starting_delta; // delta count upon entry. 1666 int status; // current simulation status. 1667 1668 // Set up based on the arguments passed to us: 1669 1670 context_p = sc_get_curr_simcontext(); 1671 starting_delta = sc_delta_count(); 1672 entry_time = context_p->m_curr_time; 1673 if ( p == SC_RUN_TO_TIME ) 1674 exit_time = context_p->m_curr_time + duration; 1675 1676 // called with duration = SC_ZERO_TIME for the first time 1677 static bool init_delta_or_pending_updates = 1678 ( starting_delta == 0 && exit_time == SC_ZERO_TIME ); 1679 1680 // If the simulation status is bad issue the appropriate message: 1681 1682 status = context_p->sim_status(); 1683 if( status != SC_SIM_OK ) 1684 { 1685 if ( status == SC_SIM_USER_STOP ) 1686 SC_REPORT_ERROR(SC_ID_SIMULATION_START_AFTER_STOP_, ""); 1687 if ( status == SC_SIM_ERROR ) 1688 SC_REPORT_ERROR(SC_ID_SIMULATION_START_AFTER_ERROR_, ""); 1689 return; 1690 } 1691 1692 if ( context_p->m_prim_channel_registry->pending_updates() ) 1693 init_delta_or_pending_updates = true; 1694 1695 // If the simulation status is good perform the simulation: 1696 1697 context_p->simulate( duration ); 1698 1699 // Re-check the status: 1700 1701 status = context_p->sim_status(); 1702 1703 // Update the current time to the exit time if that is the starvation 1704 // policy: 1705 1706 if ( p == SC_RUN_TO_TIME && !context_p->m_paused && status == SC_SIM_OK ) 1707 { 1708 context_p->m_curr_time = exit_time; 1709 } 1710 1711 // If there was no activity and the simulation clock did not move warn 1712 // the user, except if we're in a first sc_start(SC_ZERO_TIME) for 1713 // initialisation (only) or there have been pending updates: 1714 1715 if ( !init_delta_or_pending_updates && 1716 starting_delta == sc_delta_count() && 1717 context_p->m_curr_time == entry_time && 1718 status == SC_SIM_OK ) 1719 { 1720 SC_REPORT_WARNING(SC_ID_NO_SC_START_ACTIVITY_, ""); 1721 } 1722 1723 // reset init/update flag for subsequent calls 1724 init_delta_or_pending_updates = false; 1725} 1726 1727void 1728sc_start() 1729{ 1730 sc_start( sc_max_time() - sc_time_stamp(), 1731 SC_EXIT_ON_STARVATION ); 1732} 1733 1734// for backward compatibility with 1.0 1735#if 0 1736void 1737sc_start( double duration ) // in default time units 1738{ 1739 static bool warn_sc_start=true; 1740 if ( warn_sc_start ) 1741 { 1742 warn_sc_start = false; 1743 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 1744 "sc_start(double) deprecated, use sc_start(sc_time) or sc_start()"); 1745 } 1746 1747 if( duration == -1 ) // simulate forever 1748 { 1749 sc_start( 1750 sc_time(~sc_dt::UINT64_ZERO, false) - sc_time_stamp() ); 1751 } 1752 else 1753 { 1754 sc_start( sc_time( duration, true ) ); 1755 } 1756} 1757#endif // 1758 1759void 1760sc_stop() 1761{ 1762 sc_get_curr_simcontext()->stop(); 1763} 1764 1765 1766// The following function is deprecated in favor of sc_start(SC_ZERO_TIME): 1767 1768void 1769sc_initialize() 1770{ 1771 static bool warning_initialize = true; 1772 1773 if ( warning_initialize ) 1774 { 1775 warning_initialize = false; 1776 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 1777 "sc_initialize() is deprecated: use sc_start(SC_ZERO_TIME)" ); 1778 } 1779 sc_get_curr_simcontext()->initialize(); 1780} 1781 1782// The following function has been deprecated in favor of sc_start(duration): 1783 1784void 1785sc_cycle( const sc_time& duration ) 1786{ 1787 static bool warning_cycle = true; 1788 1789 if ( warning_cycle ) 1790 { 1791 warning_cycle = false; 1792 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 1793 "sc_cycle is deprecated: use sc_start(sc_time)" ); 1794 } 1795 sc_get_curr_simcontext()->cycle( duration ); 1796} 1797 1798sc_event* sc_find_event( const char* name ) 1799{ 1800 return sc_get_curr_simcontext()->get_object_manager()->find_event( name ); 1801} 1802 1803sc_object* sc_find_object( const char* name ) 1804{ 1805 return sc_get_curr_simcontext()->get_object_manager()->find_object( name ); 1806} 1807 1808 1809const sc_time& 1810sc_max_time() 1811{ 1812 return sc_get_curr_simcontext()->max_time(); 1813} 1814 1815const sc_time& 1816sc_time_stamp() 1817{ 1818 return sc_get_curr_simcontext()->time_stamp(); 1819} 1820 1821double 1822sc_simulation_time() 1823{ 1824 static bool warn_simulation_time=true; 1825 if ( warn_simulation_time ) 1826 { 1827 warn_simulation_time=false; 1828 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 1829 "sc_simulation_time() is deprecated use sc_time_stamp()" ); 1830 } 1831 return sc_get_curr_simcontext()->time_stamp().to_default_time_units(); 1832} 1833 1834void 1835sc_defunct_process_function( sc_module* ) 1836{ 1837 // This function is pointed to by defunct sc_thread_process'es and 1838 // sc_cthread_process'es. In a correctly constructed world, this 1839 // function should never be called; hence the assert. 1840 assert( false ); 1841} 1842 1843//------------------------------------------------------------------------------ 1844//"sc_set_stop_mode" 1845// 1846// This function sets the mode of operation when sc_stop() is called. 1847// mode = SC_STOP_IMMEDIATE or SC_STOP_FINISH_DELTA. 1848//------------------------------------------------------------------------------ 1849void sc_set_stop_mode(sc_stop_mode mode) 1850{ 1851 if ( sc_is_running() ) 1852 { 1853 SC_REPORT_ERROR(SC_ID_STOP_MODE_AFTER_START_,""); 1854 } 1855 else 1856 { 1857 switch( mode ) 1858 { 1859 case SC_STOP_IMMEDIATE: 1860 case SC_STOP_FINISH_DELTA: 1861 stop_mode = mode; 1862 break; 1863 default: 1864 break; 1865 } 1866 } 1867} 1868 1869sc_stop_mode 1870sc_get_stop_mode() 1871{ 1872 return stop_mode; 1873} 1874 1875bool sc_is_unwinding() 1876{ 1877 return sc_get_current_process_handle().is_unwinding(); 1878} 1879 1880// The IEEE 1666 Standard for 2011 designates that the treatment of 1881// certain process control interactions as being "implementation dependent". 1882// These interactions are: 1883// (1) What happens when a resume() call is performed on a disabled, 1884// suspended process. 1885// (2) What happens when sync_reset_on() or sync_reset_off() is called 1886// on a suspended process. 1887// (3) What happens when the value specified in a reset_signal_is() 1888// call changes value while a process is suspended. 1889// 1890// By default this Proof of Concept implementation reports an error 1891// for these interactions. However, the implementation also provides 1892// a non-error treatment. The non-error treatment for the interactions is: 1893// (1) A resume() call performed on a disabled, suspended process will 1894// mark the process as no longer suspended, and if it is capable 1895// of execution (not waiting on any events) it will be placed on 1896// the queue of runnable processes. See the state diagram below. 1897// (2) A call to sync_reset_on() or sync_reset_off() will set or clear 1898// the synchronous reset flag. Whether the process is in reset or 1899// not will be determined when the process actually executes by 1900// looking at the flag's value at that time. 1901// (3) If a suspended process has a reset_signal_is() specification 1902// the value of the reset variable at the time of its next execution 1903// will determine whether it is in reset or not. 1904// 1905// TO GET THE NON-ERROR BEHAVIOR SET THE VARIABLE BELOW TO TRUE. 1906// 1907// This can be done in this source before you build the library, or you 1908// can use an assignment as the first statement in your sc_main() function: 1909// sc_core::sc_allow_process_control_corners = true; 1910 1911bool sc_allow_process_control_corners = false; 1912 1913// The state transition diagram for the interaction of disable and suspend 1914// when sc_allow_process_control_corners is true is shown below: 1915// 1916// ...................................................................... 1917// . ENABLED . DISABLED . 1918// . . . 1919// . +----------+ disable +----------+ . 1920// . +------------>| |-------.-------->| | . 1921// . | | runnable | . | runnable | . 1922// . | +-------| |<------.---------| |------+ . 1923// . | | +----------+ enable +----------+ | . 1924// . | | | ^ . | ^ | . 1925// . | | suspend | | resume . suspend | | resume | . 1926// . | | V | . V | | . 1927// . | | +----------+ disable +----------+ | . 1928// . | | | suspend |-------.-------->| suspend | | . 1929// . t | r | | | . | | | r . 1930// . r | u | | ready |<------.---------| ready | | u . 1931// . i | n | +----------+ enable +----------+ | n . 1932// . g | / | ^ . | / . 1933// . g | w | trigger| . | w . 1934// . e | a | | . | a . 1935// . r | i | +----------+ disable +----------+ | i . 1936// . | t | | suspend |-------.-------->| suspend | | t . 1937// . | | | | . | | | . 1938// . | | | waiting |<------.---------| waiting | | . 1939// . | | +----------+ enable +----------+ | . 1940// . | | | ^ . | ^ | . 1941// . | | suspend | | resume . suspend | | resume | . 1942// . | | V | . V | | . 1943// . | | +----------+ disable +----------+ | . 1944// . | +------>| |-------.-------->| | | . 1945// . | | waiting | . | waiting | | . 1946// . +-------------| |<------.---------| |<-----+ . 1947// . +----------+ enable +----------+ . 1948// . . . 1949// ...................................................................... 1950 1951// ---------------------------------------------------------------------------- 1952 1953static std::ostream& 1954print_status_expression( std::ostream& os, sc_status s ); 1955 1956// utility helper to print a simulation status 1957std::ostream& operator << ( std::ostream& os, sc_status s ) 1958{ 1959 // print primitive values 1960 switch(s) 1961 { 1962# define PRINT_STATUS( Status ) \ 1963 case Status: { os << #Status; } break 1964 1965 PRINT_STATUS( SC_UNITIALIZED ); 1966 PRINT_STATUS( SC_ELABORATION ); 1967 PRINT_STATUS( SC_BEFORE_END_OF_ELABORATION ); 1968 PRINT_STATUS( SC_END_OF_ELABORATION ); 1969 PRINT_STATUS( SC_START_OF_SIMULATION ); 1970 1971 PRINT_STATUS( SC_RUNNING ); 1972 PRINT_STATUS( SC_PAUSED ); 1973 PRINT_STATUS( SC_STOPPED ); 1974 PRINT_STATUS( SC_END_OF_SIMULATION ); 1975 1976 PRINT_STATUS( SC_END_OF_INITIALIZATION ); 1977// PRINT_STATUS( SC_END_OF_EVALUATION ); 1978 PRINT_STATUS( SC_END_OF_UPDATE ); 1979 PRINT_STATUS( SC_BEFORE_TIMESTEP ); 1980 1981 PRINT_STATUS( SC_STATUS_ANY ); 1982 1983# undef PRINT_STATUS 1984 default: 1985 1986 if( s & SC_STATUS_ANY ) // combination of status bits 1987 print_status_expression( os, s ); 1988 else // invalid number, print hex value 1989 os << "0x" << std::hex << +s; 1990 } 1991 1992 return os; 1993} 1994 1995// pretty-print a combination of sc_status bits (i.e. a callback mask) 1996static std::ostream& 1997print_status_expression( std::ostream& os, sc_status s ) 1998{ 1999 std::vector<sc_status> bits; 2000 unsigned is_set = SC_ELABORATION; 2001 2002 // collect bits 2003 while( is_set <= SC_STATUS_LAST ) 2004 { 2005 if( s & is_set ) 2006 bits.push_back( (sc_status)is_set ); 2007 is_set <<= 1; 2008 } 2009 if( s & ~SC_STATUS_ANY ) // remaining bits 2010 bits.push_back( (sc_status)( s & ~SC_STATUS_ANY ) ); 2011 2012 // print expression 2013 std::vector<sc_status>::size_type i=0, n=bits.size(); 2014 if ( n>1 ) 2015 os << "("; 2016 for( ; i<n-1; ++i ) 2017 os << bits[i] << "|"; 2018 os << bits[i]; 2019 if ( n>1 ) 2020 os << ")"; 2021 return os; 2022} 2023 2024} // namespace sc_core 2025 2026/***************************************************************************** 2027 2028 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 2029 changes you are making here. 2030 2031 Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. 2032 Description of Modification: - Added sc_stop() detection into initial_crunch 2033 and crunch. This makes it possible to exit out 2034 of a combinational loop using sc_stop(). 2035 2036 Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 2037 Description of Modification: - sc_stop mode 2038 - phase callbacks 2039 2040 Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, 2041 25 August 2003 2042 Description of Modification: - support for dynamic process 2043 - support for sc export registry 2044 - new member methods elaborate(), 2045 prepare_to_simulate(), and initial_crunch() 2046 that are invoked by initialize() in that order 2047 - implement sc_get_last_created_process_handle() for use 2048 before simulation starts 2049 - remove "set_curr_proc(handle)" from 2050 register_method_process and 2051 register_thread_process - led to bugs 2052 2053 Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 04 Sep 2003 2054 Description of Modification: - changed process existence structures to 2055 linked lists to eliminate exponential 2056 execution problem with using sc_pvector. 2057 *****************************************************************************/ 2058// $Log: sc_simcontext.cpp,v $ 2059// Revision 1.37 2011/08/29 18:04:32 acg 2060// Philipp A. Hartmann: miscellaneous clean ups. 2061// 2062// Revision 1.36 2011/08/26 20:46:10 acg 2063// Andy Goodrich: moved the modification log to the end of the file to 2064// eliminate source line number skew when check-ins are done. 2065// 2066// Revision 1.35 2011/08/24 22:05:51 acg 2067// Torsten Maehne: initialization changes to remove warnings. 2068// 2069// Revision 1.34 2011/08/04 17:15:28 acg 2070// Andy Goodrich: added documentation to crunch() routine. 2071// 2072// Revision 1.32 2011/07/24 11:16:36 acg 2073// Philipp A. Hartmann: fix reference counting on deferred deletions of 2074// processes. 2075// 2076// Revision 1.31 2011/07/01 18:49:07 acg 2077// Andy Goodrich: moved pln() from sc_simcontext.cpp to sc_ver.cpp. 2078// 2079// Revision 1.30 2011/05/09 04:07:49 acg 2080// Philipp A. Hartmann: 2081// (1) Restore hierarchy in all phase callbacks. 2082// (2) Ensure calls to before_end_of_elaboration. 2083// 2084// Revision 1.29 2011/04/08 22:39:09 acg 2085// Andy Goodrich: moved method invocation code to sc_method.h so that the 2086// details are hidden from sc_simcontext. 2087// 2088// Revision 1.28 2011/04/05 20:50:57 acg 2089// Andy Goodrich: 2090// (1) changes to make sure that event(), posedge() and negedge() only 2091// return true if the clock has not moved. 2092// (2) fixes for method self-resumes. 2093// (3) added SC_PRERELEASE_VERSION 2094// (4) removed kernel events from the object hierarchy, added 2095// sc_hierarchy_name_exists(). 2096// 2097// Revision 1.27 2011/04/05 06:14:15 acg 2098// Andy Goodrich: fix typo. 2099// 2100// Revision 1.26 2011/04/05 06:03:32 acg 2101// Philipp A. Hartmann: added code to set ready to run bit for a suspended 2102// process that does not have dont_initialize specified at simulation 2103// start up. 2104// 2105// Revision 1.25 2011/04/01 21:31:55 acg 2106// Andy Goodrich: make sure processes suspended before the start of execution 2107// don't get scheduled for initial execution. 2108// 2109// Revision 1.24 2011/03/28 13:02:52 acg 2110// Andy Goodrich: Changes for disable() interactions. 2111// 2112// Revision 1.23 2011/03/12 21:07:51 acg 2113// Andy Goodrich: changes to kernel generated event support. 2114// 2115// Revision 1.22 2011/03/07 17:38:43 acg 2116// Andy Goodrich: tightening up of checks for undefined interaction between 2117// synchronous reset and suspend. 2118// 2119// Revision 1.21 2011/03/06 19:57:11 acg 2120// Andy Goodrich: refinements for the illegal suspend - synchronous reset 2121// interaction. 2122// 2123// Revision 1.20 2011/03/06 15:58:50 acg 2124// Andy Goodrich: added escape to turn off process control corner case 2125// checks. 2126// 2127// Revision 1.19 2011/03/05 04:45:16 acg 2128// Andy Goodrich: moved active process calculation to the sc_simcontext class. 2129// 2130// Revision 1.18 2011/03/05 01:39:21 acg 2131// Andy Goodrich: changes for named events. 2132// 2133// Revision 1.17 2011/02/18 20:27:14 acg 2134// Andy Goodrich: Updated Copyrights. 2135// 2136// Revision 1.16 2011/02/17 19:53:28 acg 2137// Andy Goodrich: eliminated use of ready_to_run() as part of process control 2138// simplification. 2139// 2140// Revision 1.15 2011/02/13 21:47:38 acg 2141// Andy Goodrich: update copyright notice. 2142// 2143// Revision 1.14 2011/02/11 13:25:24 acg 2144// Andy Goodrich: Philipp A. Hartmann's changes: 2145// (1) Removal of SC_CTHREAD method overloads. 2146// (2) New exception processing code. 2147// 2148// Revision 1.13 2011/02/08 08:42:50 acg 2149// Andy Goodrich: fix ordering of check for stopped versus paused. 2150// 2151// Revision 1.12 2011/02/07 19:17:20 acg 2152// Andy Goodrich: changes for IEEE 1666 compatibility. 2153// 2154// Revision 1.11 2011/02/02 07:18:11 acg 2155// Andy Goodrich: removed toggle() calls for the new crunch() toggle usage. 2156// 2157// Revision 1.10 2011/02/01 23:01:53 acg 2158// Andy Goodrich: removed dead code. 2159// 2160// Revision 1.9 2011/02/01 21:11:59 acg 2161// Andy Goodrich: 2162// (1) Use of new toggle_methods() and toggle_threads() run queue methods 2163// to make sure the thread run queue does not execute when allow preempt_me() 2164// is called from an SC_METHOD. 2165// (2) Use of execute_thread_next() to allow thread execution in the current 2166// delta cycle() rather than push_runnable_thread_front which executed 2167// in the following cycle. 2168// 2169// Revision 1.8 2011/01/25 20:50:37 acg 2170// Andy Goodrich: changes for IEEE 1666 2011. 2171// 2172// Revision 1.7 2011/01/19 23:21:50 acg 2173// Andy Goodrich: changes for IEEE 1666 2011 2174// 2175// Revision 1.6 2011/01/18 20:10:45 acg 2176// Andy Goodrich: changes for IEEE1666_2011 semantics. 2177// 2178// Revision 1.5 2010/11/20 17:10:57 acg 2179// Andy Goodrich: reset processing changes for new IEEE 1666 standard. 2180// 2181// Revision 1.4 2010/07/22 20:02:33 acg 2182// Andy Goodrich: bug fixes. 2183// 2184// Revision 1.3 2008/05/22 17:06:26 acg 2185// Andy Goodrich: updated copyright notice to include 2008. 2186// 2187// Revision 1.2 2007/09/20 20:32:35 acg 2188// Andy Goodrich: changes to the semantics of throw_it() to match the 2189// specification. A call to throw_it() will immediately suspend the calling 2190// thread until all the throwees have executed. At that point the calling 2191// thread will be restarted before the execution of any other threads. 2192// 2193// Revision 1.1.1.1 2006/12/15 20:20:05 acg 2194// SystemC 2.3 2195// 2196// Revision 1.21 2006/08/29 23:37:13 acg 2197// Andy Goodrich: Added check for negative time. 2198// 2199// Revision 1.20 2006/05/26 20:33:16 acg 2200// Andy Goodrich: changes required by additional platform compilers (i.e., 2201// Microsoft VC++, Sun Forte, HP aCC). 2202// 2203// Revision 1.19 2006/05/08 17:59:52 acg 2204// Andy Goodrich: added a check before m_curr_time is set to make sure it 2205// is not set to a time before its current value. This will treat 2206// sc_event.notify( ) calls with negative times as calls with a zero time. 2207// 2208// Revision 1.18 2006/04/20 17:08:17 acg 2209// Andy Goodrich: 3.0 style process changes. 2210// 2211// Revision 1.17 2006/04/11 23:13:21 acg 2212// Andy Goodrich: Changes for reduced reset support that only includes 2213// sc_cthread, but has preliminary hooks for expanding to method and thread 2214// processes also. 2215// 2216// Revision 1.16 2006/03/21 00:00:34 acg 2217// Andy Goodrich: changed name of sc_get_current_process_base() to be 2218// sc_get_current_process_b() since its returning an sc_process_b instance. 2219// 2220// Revision 1.15 2006/03/13 20:26:50 acg 2221// Andy Goodrich: Addition of forward class declarations, e.g., 2222// sc_reset, to keep gcc 4.x happy. 2223// 2224// Revision 1.14 2006/02/02 23:42:41 acg 2225// Andy Goodrich: implemented a much better fix to the sc_event_finder 2226// proliferation problem. This new version allocates only a single event 2227// finder for each port for each type of event, e.g., pos(), neg(), and 2228// value_change(). The event finder persists as long as the port does, 2229// which is what the LRM dictates. Because only a single instance is 2230// allocated for each event type per port there is not a potential 2231// explosion of storage as was true in the 2.0.1/2.1 versions. 2232// 2233// Revision 1.13 2006/02/02 21:29:10 acg 2234// Andy Goodrich: removed the call to sc_event_finder::free_instances() that 2235// was in end_of_elaboration(), leaving only the call in clean(). This is 2236// because the LRM states that sc_event_finder instances are persistent as 2237// long as the sc_module hierarchy is valid. 2238// 2239// Revision 1.12 2006/02/02 21:09:50 acg 2240// Andy Goodrich: added call to sc_event_finder::free_instances in the clean() 2241// method. 2242// 2243// Revision 1.11 2006/02/02 20:43:14 acg 2244// Andy Goodrich: Added an existence linked list to sc_event_finder so that 2245// the dynamically allocated instances can be freed after port binding 2246// completes. This replaces the individual deletions in ~sc_bind_ef, as these 2247// caused an exception if an sc_event_finder instance was used more than 2248// once, due to a double freeing of the instance. 2249// 2250// Revision 1.10 2006/01/31 21:43:26 acg 2251// Andy Goodrich: added comments in constructor to highlight environmental 2252// overrides section. 2253// 2254// Revision 1.9 2006/01/26 21:04:54 acg 2255// Andy Goodrich: deprecation message changes and additional messages. 2256// 2257// Revision 1.8 2006/01/25 00:31:19 acg 2258// Andy Goodrich: Changed over to use a standard message id of 2259// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. 2260// 2261// Revision 1.7 2006/01/24 20:49:05 acg 2262// Andy Goodrich: changes to remove the use of deprecated features within the 2263// simulator, and to issue warning messages when deprecated features are used. 2264// 2265// Revision 1.6 2006/01/19 00:29:52 acg 2266// Andy Goodrich: Yet another implementation for signal write checking. This 2267// one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to 2268// DISABLE will disable write checking on signals. 2269// 2270// Revision 1.5 2006/01/13 18:44:30 acg 2271// Added $Log to record CVS changes into the source. 2272// 2273// Revision 1.4 2006/01/03 23:18:44 acg 2274// Changed copyright to include 2006. 2275// 2276// Revision 1.3 2005/12/20 22:11:10 acg 2277// Fixed $Log lines. 2278// 2279// Revision 1.2 2005/12/20 22:02:30 acg 2280// Changed where delta cycles are incremented to match IEEE 1666. Added the 2281// event_occurred() method to hide how delta cycle comparisions are done within 2282// sc_simcontext. Changed the boolean update_phase to an enum that shows all 2283// the phases. 2284// Taf! 2285