diff options
Diffstat (limited to 'ext/systemc/src/sysc/kernel/sc_simcontext_int.h')
-rw-r--r-- | ext/systemc/src/sysc/kernel/sc_simcontext_int.h | 365 |
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 |