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