summaryrefslogtreecommitdiff
path: root/ext/systemc/src/sysc/kernel/sc_simcontext_int.h
diff options
context:
space:
mode:
Diffstat (limited to 'ext/systemc/src/sysc/kernel/sc_simcontext_int.h')
-rw-r--r--ext/systemc/src/sysc/kernel/sc_simcontext_int.h365
1 files changed, 365 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/kernel/sc_simcontext_int.h b/ext/systemc/src/sysc/kernel/sc_simcontext_int.h
new file mode 100644
index 000000000..039237f4a
--- /dev/null
+++ b/ext/systemc/src/sysc/kernel/sc_simcontext_int.h
@@ -0,0 +1,365 @@
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_simcontext_int.h -- For inline definitions of some utility functions.
+ DO NOT EXPORT THIS INCLUDE FILE. Include this file
+ after "sc_process_int.h" so that we can get the base
+ class right.
+
+ Original Author: Stan Y. Liao, Synopsys, Inc.
+
+ CHANGE LOG AT THE END OF THE FILE
+ *****************************************************************************/
+
+#ifndef SC_SIMCONTEXT_INT_H
+#define SC_SIMCONTEXT_INT_H
+
+#include "sysc/kernel/sc_simcontext.h"
+#include "sysc/kernel/sc_runnable.h"
+#include "sysc/kernel/sc_runnable_int.h"
+
+// DEBUGGING MACROS:
+//
+// DEBUG_MSG(NAME,P,MSG)
+// MSG = message to print
+// NAME = name that must match the process for the message to print, or
+// null if the message should be printed unconditionally.
+// P = pointer to process message is for, or NULL in which case the
+// message will not print.
+#if 0
+# define DEBUG_NAME ""
+# define DEBUG_MSG(NAME,P,MSG) \
+ { \
+ if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \
+ std::cout << "**** " << sc_time_stamp() << " (" \
+ << sc_get_current_process_name() << "): " << MSG \
+ << " - " << P->name() << std::endl; \
+ }
+#else
+# define DEBUG_MSG(NAME,P,MSG)
+#endif
+
+
+namespace sc_core {
+
+inline
+const char*
+sc_get_current_process_name()
+{
+ sc_process_b* active_p; // active process to get name of.
+ const char* result; // name of active process.
+
+ active_p = sc_get_curr_simcontext()->get_curr_proc_info()->process_handle;
+ if ( active_p )
+ result = active_p->name();
+ else
+ result = "** NONE **";
+ return result;
+}
+
+// We use m_current_writer rather than m_curr_proc_info.process_handle to
+// return the active process for sc_signal<T>::check_write since that lets
+// us turn it off a library compile time, and only incur the overhead at
+// the time of process switches rather than having to interrogate an
+// additional switch every time a signal is written.
+
+inline
+void
+sc_simcontext::set_curr_proc( sc_process_b* process_h )
+{
+ m_curr_proc_info.process_handle = process_h;
+ m_curr_proc_info.kind = process_h->proc_kind();
+ m_current_writer = m_write_check ? process_h : (sc_object*)0;
+}
+
+inline
+void
+sc_simcontext::reset_curr_proc()
+{
+ m_curr_proc_info.process_handle = 0;
+ m_curr_proc_info.kind = SC_NO_PROC_;
+ m_current_writer = 0;
+ sc_process_b::m_last_created_process_p = 0;
+}
+
+inline
+void
+sc_simcontext::execute_method_next( sc_method_handle method_h )
+{
+ m_runnable->execute_method_next( method_h );
+}
+
+inline
+void
+sc_simcontext::execute_thread_next( sc_thread_handle thread_h )
+{
+ m_runnable->execute_thread_next( thread_h );
+}
+
+// +----------------------------------------------------------------------------
+// |"sc_simcontext::preempt_with"
+// |
+// | This method executes the supplied thread immediately, suspending the
+// | caller. After executing the supplied thread the caller's execution will
+// | be restored. It is used to allow a thread to immediately throw an
+// | exception, e.g., when the thread's kill_process() method was called.
+// | There are three cases to consider:
+// | (1) The caller is a method, e.g., murder by method.
+// | (2) The caller is another thread instance, e.g., murder by thread.
+// | (3) The caller is this thread instance, e.g., suicide.
+// |
+// | Arguments:
+// | thread_h -> thread to be executed.
+// +----------------------------------------------------------------------------
+inline
+void
+sc_simcontext::preempt_with( sc_thread_handle thread_h )
+{
+ sc_thread_handle active_p; // active thread or null.
+ sc_curr_proc_info caller_info; // process info for caller.
+
+ // Determine the active process and take the thread to be run off the
+ // run queue, if its there, since we will be explicitly causing its
+ // execution.
+
+ active_p = DCAST<sc_thread_handle>(sc_get_current_process_b());
+ if ( thread_h->next_runnable() != NULL )
+ remove_runnable_thread( thread_h );
+
+ // THE CALLER IS A METHOD:
+ //
+ // (a) Set the current process information to our thread.
+ // (b) If the method was called by an invoker thread push that thread
+ // onto the front of the run queue, this will cause the method
+ // to be resumed after this thread waits.
+ // (c) Invoke our thread directly by-passing the run queue.
+ // (d) Restore the process info to the caller.
+ // (e) Check to see if the calling method should throw an exception
+ // because of activity that occurred during the preemption.
+
+ if ( active_p == NULL )
+ {
+ std::vector<sc_thread_handle>* invokers_p; // active invokers stack.
+ sc_thread_handle invoke_thread_p; // latest invocation thread.
+ sc_method_handle method_p; // active method.
+
+ method_p = DCAST<sc_method_handle>(sc_get_current_process_b());
+ invokers_p = &get_active_invokers();
+ caller_info = m_curr_proc_info;
+ if ( invokers_p->size() != 0 )
+ {
+ invoke_thread_p = invokers_p->back();
+ DEBUG_MSG( DEBUG_NAME, invoke_thread_p,
+ "queueing invocation thread to execute next" );
+ execute_thread_next(invoke_thread_p);
+ }
+ DEBUG_MSG( DEBUG_NAME, thread_h, "preempting method with thread" );
+ set_curr_proc( (sc_process_b*)thread_h );
+ m_cor_pkg->yield( thread_h->m_cor_p );
+ m_curr_proc_info = caller_info;
+ DEBUG_MSG(DEBUG_NAME, thread_h, "back from preempting method w/thread");
+ method_p->check_for_throws();
+ }
+
+ // CALLER IS A THREAD, BUT NOT THE THREAD TO BE RUN:
+ //
+ // (a) Push the calling thread onto the front of the runnable queue
+ // so it be the first thread to be run after this thread.
+ // (b) Push the thread to be run onto the front of the runnable queue so
+ // it will execute when we suspend the calling thread.
+ // (c) Suspend the active thread.
+
+ else if ( active_p != thread_h )
+ {
+ DEBUG_MSG( DEBUG_NAME, thread_h,
+ "preempting active thread with thread" );
+ execute_thread_next( active_p );
+ execute_thread_next( thread_h );
+ active_p->suspend_me();
+ }
+
+ // CALLER IS THE THREAD TO BE RUN:
+ //
+ // (a) Push the thread to be run onto the front of the runnable queue so
+ // it will execute when we suspend the calling thread.
+ // (b) Suspend the active thread.
+
+ else
+ {
+ DEBUG_MSG(DEBUG_NAME,thread_h,"self preemption of active thread");
+ execute_thread_next( thread_h );
+ active_p->suspend_me();
+ }
+}
+
+
+inline
+void
+sc_simcontext::push_runnable_method( sc_method_handle method_h )
+{
+ m_runnable->push_back_method( method_h );
+}
+
+inline
+void
+sc_simcontext::push_runnable_method_front( sc_method_handle method_h )
+{
+ m_runnable->push_front_method( method_h );
+}
+
+inline
+void
+sc_simcontext::push_runnable_thread( sc_thread_handle thread_h )
+{
+ m_runnable->push_back_thread( thread_h );
+}
+
+inline
+void
+sc_simcontext::push_runnable_thread_front( sc_thread_handle thread_h )
+{
+ m_runnable->push_front_thread( thread_h );
+}
+
+
+inline
+sc_method_handle
+sc_simcontext::pop_runnable_method()
+{
+ sc_method_handle method_h = m_runnable->pop_method();
+ if( method_h == 0 ) {
+ reset_curr_proc();
+ return 0;
+ }
+ set_curr_proc( (sc_process_b*)method_h );
+ return method_h;
+}
+
+inline
+sc_thread_handle
+sc_simcontext::pop_runnable_thread()
+{
+ sc_thread_handle thread_h = m_runnable->pop_thread();
+ if( thread_h == 0 ) {
+ reset_curr_proc();
+ return 0;
+ }
+ set_curr_proc( (sc_process_b*)thread_h );
+ return thread_h;
+}
+
+inline
+void
+sc_simcontext::remove_runnable_method( sc_method_handle method_h )
+{
+ m_runnable->remove_method( method_h );
+}
+
+inline
+void
+sc_simcontext::remove_runnable_thread( sc_thread_handle thread_h )
+{
+ m_runnable->remove_thread( thread_h );
+}
+
+inline
+std::vector<sc_thread_handle>&
+sc_simcontext::get_active_invokers()
+{
+ return m_active_invokers;
+}
+
+// ----------------------------------------------------------------------------
+
+extern void sc_defunct_process_function( sc_module* );
+
+
+} // namespace sc_core
+
+#undef DEBUG_MSG
+#undef DEBUG_NAME
+
+// $Log: sc_simcontext_int.h,v $
+// Revision 1.14 2011/08/29 18:04:32 acg
+// Philipp A. Hartmann: miscellaneous clean ups.
+//
+// Revision 1.13 2011/08/26 20:46:11 acg
+// Andy Goodrich: moved the modification log to the end of the file to
+// eliminate source line number skew when check-ins are done.
+//
+// Revision 1.12 2011/07/29 22:45:06 acg
+// Andy Goodrich: added invocation of sc_method_process::check_for_throws()
+// to the preempt_with() code to handle case where the preempting process
+// causes a throw on the invoking method process.
+//
+// Revision 1.11 2011/04/13 02:45:11 acg
+// Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG
+// macro was used.
+//
+// Revision 1.10 2011/04/11 22:05:48 acg
+// Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations.
+//
+// Revision 1.9 2011/04/10 22:12:32 acg
+// Andy Goodrich: adding debugging macros.
+//
+// Revision 1.8 2011/04/08 18:26:07 acg
+// Andy Goodrich: added execute_method_next() to handle method dispatch
+// for asynchronous notifications that occur outside the evaluation phase.
+//
+// Revision 1.7 2011/02/18 20:27:14 acg
+// Andy Goodrich: Updated Copyrights.
+//
+// Revision 1.6 2011/02/13 21:47:38 acg
+// Andy Goodrich: update copyright notice.
+//
+// Revision 1.5 2011/02/08 08:17:50 acg
+// Andy Goodrich: fixed bug in preempt_with() where I was resetting the
+// process context rather than saving and restoring it.
+//
+// Revision 1.4 2011/02/01 21:12:56 acg
+// Andy Goodrich: addition of preempt_with() method to allow immediate
+// execution of threads for throws.
+//
+// Revision 1.3 2011/01/25 20:50:37 acg
+// Andy Goodrich: changes for IEEE 1666 2011.
+//
+// Revision 1.2 2008/05/22 17:06:26 acg
+// Andy Goodrich: updated copyright notice to include 2008.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.6 2006/05/26 20:33:16 acg
+// Andy Goodrich: changes required by additional platform compilers (i.e.,
+// Microsoft VC++, Sun Forte, HP aCC).
+//
+// Revision 1.5 2006/01/19 00:29:52 acg
+// Andy Goodrich: Yet another implementation for signal write checking. This
+// one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to
+// DISABLE will disable write checking on signals.
+//
+// Revision 1.4 2006/01/18 21:42:37 acg
+// Andy Goodrich: Changes for check writer support.
+//
+// Revision 1.3 2006/01/13 18:44:30 acg
+// Added $Log to record CVS changes into the source.
+
+#endif