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