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