00001 /***************************************************************************** 00002 00003 The following code is derived, directly or indirectly, from the SystemC 00004 source code Copyright (c) 1996-2014 by all Contributors. 00005 All Rights reserved. 00006 00007 The contents of this file are subject to the restrictions and limitations 00008 set forth in the SystemC Open Source License (the "License"); 00009 You may not use this file except in compliance with such restrictions and 00010 limitations. You may obtain instructions on how to receive a copy of the 00011 License at http://www.accellera.org/. Software distributed by Contributors 00012 under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 00013 ANY KIND, either express or implied. See the License for the specific 00014 language governing rights and limitations under the License. 00015 00016 *****************************************************************************/ 00017 00018 /***************************************************************************** 00019 00020 sc_simcontext_int.h -- For inline definitions of some utility functions. 00021 DO NOT EXPORT THIS INCLUDE FILE. Include this file 00022 after "sc_process_int.h" so that we can get the base 00023 class right. 00024 00025 Original Author: Stan Y. Liao, Synopsys, Inc. 00026 00027 CHANGE LOG AT THE END OF THE FILE 00028 *****************************************************************************/ 00029 00030 #ifndef SC_SIMCONTEXT_INT_H 00031 #define SC_SIMCONTEXT_INT_H 00032 00033 #include "sysc/kernel/sc_simcontext.h" 00034 #include "sysc/kernel/sc_runnable.h" 00035 #include "sysc/kernel/sc_runnable_int.h" 00036 00037 // DEBUGGING MACROS: 00038 // 00039 // DEBUG_MSG(NAME,P,MSG) 00040 // MSG = message to print 00041 // NAME = name that must match the process for the message to print, or 00042 // null if the message should be printed unconditionally. 00043 // P = pointer to process message is for, or NULL in which case the 00044 // message will not print. 00045 #if 0 00046 # define DEBUG_NAME "" 00047 # define DEBUG_MSG(NAME,P,MSG) \ 00048 { \ 00049 if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ 00050 std::cout << "**** " << sc_time_stamp() << " (" \ 00051 << sc_get_current_process_name() << "): " << MSG \ 00052 << " - " << P->name() << std::endl; \ 00053 } 00054 #else 00055 # define DEBUG_MSG(NAME,P,MSG) 00056 #endif 00057 00058 00059 namespace sc_core { 00060 00061 inline 00062 const char* 00063 sc_get_current_process_name() 00064 { 00065 sc_process_b* active_p; // active process to get name of. 00066 const char* result; // name of active process. 00067 00068 active_p = sc_get_curr_simcontext()->get_curr_proc(); 00069 if ( active_p ) 00070 result = active_p->name(); 00071 else 00072 result = "** NONE **"; 00073 return result; 00074 } 00075 00076 // We use m_current_writer rather than m_curr_proc_info.process_handle to 00077 // return the active process for sc_signal<T>::check_write since that lets 00078 // us turn it off a library compile time, and only incur the overhead at 00079 // the time of process switches rather than having to interrogate an 00080 // additional switch every time a signal is written. 00081 00082 inline 00083 void 00084 sc_simcontext::set_curr_proc( sc_process_b* process_h ) 00085 { 00086 assert( 0 ); // 10/29/2014 GL TODO: clean up the codes later 00087 //m_curr_proc_info.process_handle = process_h; 00088 //m_curr_proc_info.kind = process_h->proc_kind(); 00089 //m_current_writer = m_write_check ? process_h : (sc_object*)0; 00090 } 00091 00092 inline 00093 void 00094 sc_simcontext::reset_curr_proc() 00095 { 00096 //m_curr_proc_info.process_handle = 0; 00097 //m_curr_proc_info.kind = SC_NO_PROC_; 00098 //m_current_writer = 0; 00099 sc_process_b::m_last_created_process_p = 0; 00100 } 00101 00102 inline 00103 void 00104 sc_simcontext::execute_method_next( sc_method_handle method_h ) 00105 { 00106 m_runnable->execute_method_next( method_h ); 00107 } 00108 00109 inline 00110 void 00111 sc_simcontext::execute_thread_next( sc_thread_handle thread_h ) 00112 { 00113 m_runnable->execute_thread_next( thread_h ); 00114 } 00115 00116 // +---------------------------------------------------------------------------- 00117 // |"sc_simcontext::preempt_with" 00118 // | 00119 // | This method executes the supplied thread immediately, suspending the 00120 // | caller. After executing the supplied thread the caller's execution will 00121 // | be restored. It is used to allow a thread to immediately throw an 00122 // | exception, e.g., when the thread's kill_process() method was called. 00123 // | There are three cases to consider: 00124 // | (1) The caller is a method, e.g., murder by method. 00125 // | (2) The caller is another thread instance, e.g., murder by thread. 00126 // | (3) The caller is this thread instance, e.g., suicide. 00127 // | 00128 // | Arguments: 00129 // | thread_h -> thread to be executed. 00130 // +---------------------------------------------------------------------------- 00131 inline 00132 void 00133 sc_simcontext::preempt_with( sc_thread_handle thread_h ) 00134 { 00135 assert( 0 ); // 10/28/2014 GL TODO: clean up the codes later 00136 /* 00137 00138 sc_thread_handle active_p; // active thread or null. 00139 sc_curr_proc_info caller_info; // process info for caller. 00140 00141 // Determine the active process and take the thread to be run off the 00142 // run queue, if its there, since we will be explicitly causing its 00143 // execution. 00144 00145 active_p = DCAST<sc_thread_handle>(sc_get_current_process_b()); 00146 if ( thread_h->next_runnable() != NULL ) 00147 remove_runnable_thread( thread_h ); 00148 00149 // THE CALLER IS A METHOD: 00150 // 00151 // (a) Set the current process information to our thread. 00152 // (b) If the method was called by an invoker thread push that thread 00153 // onto the front of the run queue, this will cause the method 00154 // to be resumed after this thread waits. 00155 // (c) Invoke our thread directly by-passing the run queue. 00156 // (d) Restore the process info to the caller. 00157 // (e) Check to see if the calling method should throw an exception 00158 // because of activity that occurred during the preemption. 00159 00160 if ( active_p == NULL ) 00161 { 00162 std::vector<sc_thread_handle>* invokers_p; // active invokers stack. 00163 sc_thread_handle invoke_thread_p; // latest invocation thread. 00164 sc_method_handle method_p; // active method. 00165 00166 method_p = DCAST<sc_method_handle>(sc_get_current_process_b()); 00167 invokers_p = &get_active_invokers(); 00168 caller_info = m_curr_proc_info; 00169 if ( invokers_p->size() != 0 ) 00170 { 00171 invoke_thread_p = invokers_p->back(); 00172 DEBUG_MSG( DEBUG_NAME, invoke_thread_p, 00173 "queueing invocation thread to execute next" ); 00174 execute_thread_next(invoke_thread_p); 00175 } 00176 DEBUG_MSG( DEBUG_NAME, thread_h, "preempting method with thread" ); 00177 set_curr_proc( (sc_process_b*)thread_h ); 00178 m_cor_pkg->yield( thread_h->m_cor_p ); 00179 m_curr_proc_info = caller_info; 00180 DEBUG_MSG(DEBUG_NAME, thread_h, "back from preempting method w/thread"); 00181 method_p->check_for_throws(); 00182 } 00183 00184 // CALLER IS A THREAD, BUT NOT THE THREAD TO BE RUN: 00185 // 00186 // (a) Push the calling thread onto the front of the runnable queue 00187 // so it be the first thread to be run after this thread. 00188 // (b) Push the thread to be run onto the front of the runnable queue so 00189 // it will execute when we suspend the calling thread. 00190 // (c) Suspend the active thread. 00191 00192 else if ( active_p != thread_h ) 00193 { 00194 DEBUG_MSG( DEBUG_NAME, thread_h, 00195 "preempting active thread with thread" ); 00196 execute_thread_next( active_p ); 00197 execute_thread_next( thread_h ); 00198 active_p->suspend_me(); 00199 } 00200 00201 // CALLER IS THE THREAD TO BE RUN: 00202 // 00203 // (a) Push the thread to be run onto the front of the runnable queue so 00204 // it will execute when we suspend the calling thread. 00205 // (b) Suspend the active thread. 00206 00207 else 00208 { 00209 DEBUG_MSG(DEBUG_NAME,thread_h,"self preemption of active thread"); 00210 execute_thread_next( thread_h ); 00211 active_p->suspend_me(); 00212 }*/ 00213 } 00214 00215 00216 inline 00217 void 00218 sc_simcontext::push_runnable_method( sc_method_handle method_h ) 00219 { 00220 m_runnable->push_back_method( method_h ); 00221 } 00222 00223 inline 00224 void 00225 sc_simcontext::push_runnable_method_front( sc_method_handle method_h ) 00226 { 00227 m_runnable->push_front_method( method_h ); 00228 } 00229 00230 inline 00231 void 00232 sc_simcontext::push_runnable_thread( sc_thread_handle thread_h ) 00233 { 00234 m_runnable->push_back_thread( thread_h ); 00235 } 00236 00237 inline 00238 void 00239 sc_simcontext::push_runnable_thread_front( sc_thread_handle thread_h ) 00240 { 00241 m_runnable->push_front_thread( thread_h ); 00242 } 00243 00244 00245 inline 00246 sc_method_handle 00247 sc_simcontext::pop_runnable_method() 00248 { 00249 sc_method_handle method_h = m_runnable->pop_method(); 00250 if( method_h == 0 ) { 00251 reset_curr_proc(); 00252 return 0; 00253 } 00254 // set_curr_proc( (sc_process_b*)method_h ); 00255 return method_h; 00256 } 00257 00258 inline 00259 sc_thread_handle 00260 sc_simcontext::pop_runnable_thread() 00261 { 00262 sc_thread_handle thread_h = m_runnable->pop_thread(); 00263 if( thread_h == 0 ) { 00264 reset_curr_proc(); 00265 return 0; 00266 } 00267 // set_curr_proc( (sc_process_b*)thread_h ); 00268 return thread_h; 00269 } 00270 00271 inline 00272 void 00273 sc_simcontext::remove_runnable_method( sc_method_handle method_h ) 00274 { 00275 m_runnable->remove_method( method_h ); 00276 } 00277 00278 inline 00279 void 00280 sc_simcontext::remove_runnable_thread( sc_thread_handle thread_h ) 00281 { 00282 m_runnable->remove_thread( thread_h ); 00283 } 00284 00285 inline 00286 std::vector<sc_thread_handle>& 00287 sc_simcontext::get_active_invokers() 00288 { 00289 return m_active_invokers; 00290 } 00291 00292 // ---------------------------------------------------------------------------- 00293 00294 extern void sc_defunct_process_function( sc_module* ); 00295 00296 00297 } // namespace sc_core 00298 00299 #undef DEBUG_MSG 00300 #undef DEBUG_NAME 00301 00302 // $Log: sc_simcontext_int.h,v $ 00303 // Revision 1.14 2011/08/29 18:04:32 acg 00304 // Philipp A. Hartmann: miscellaneous clean ups. 00305 // 00306 // Revision 1.13 2011/08/26 20:46:11 acg 00307 // Andy Goodrich: moved the modification log to the end of the file to 00308 // eliminate source line number skew when check-ins are done. 00309 // 00310 // Revision 1.12 2011/07/29 22:45:06 acg 00311 // Andy Goodrich: added invocation of sc_method_process::check_for_throws() 00312 // to the preempt_with() code to handle case where the preempting process 00313 // causes a throw on the invoking method process. 00314 // 00315 // Revision 1.11 2011/04/13 02:45:11 acg 00316 // Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG 00317 // macro was used. 00318 // 00319 // Revision 1.10 2011/04/11 22:05:48 acg 00320 // Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations. 00321 // 00322 // Revision 1.9 2011/04/10 22:12:32 acg 00323 // Andy Goodrich: adding debugging macros. 00324 // 00325 // Revision 1.8 2011/04/08 18:26:07 acg 00326 // Andy Goodrich: added execute_method_next() to handle method dispatch 00327 // for asynchronous notifications that occur outside the evaluation phase. 00328 // 00329 // Revision 1.7 2011/02/18 20:27:14 acg 00330 // Andy Goodrich: Updated Copyrights. 00331 // 00332 // Revision 1.6 2011/02/13 21:47:38 acg 00333 // Andy Goodrich: update copyright notice. 00334 // 00335 // Revision 1.5 2011/02/08 08:17:50 acg 00336 // Andy Goodrich: fixed bug in preempt_with() where I was resetting the 00337 // process context rather than saving and restoring it. 00338 // 00339 // Revision 1.4 2011/02/01 21:12:56 acg 00340 // Andy Goodrich: addition of preempt_with() method to allow immediate 00341 // execution of threads for throws. 00342 // 00343 // Revision 1.3 2011/01/25 20:50:37 acg 00344 // Andy Goodrich: changes for IEEE 1666 2011. 00345 // 00346 // Revision 1.2 2008/05/22 17:06:26 acg 00347 // Andy Goodrich: updated copyright notice to include 2008. 00348 // 00349 // Revision 1.1.1.1 2006/12/15 20:20:05 acg 00350 // SystemC 2.3 00351 // 00352 // Revision 1.6 2006/05/26 20:33:16 acg 00353 // Andy Goodrich: changes required by additional platform compilers (i.e., 00354 // Microsoft VC++, Sun Forte, HP aCC). 00355 // 00356 // Revision 1.5 2006/01/19 00:29:52 acg 00357 // Andy Goodrich: Yet another implementation for signal write checking. This 00358 // one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to 00359 // DISABLE will disable write checking on signals. 00360 // 00361 // Revision 1.4 2006/01/18 21:42:37 acg 00362 // Andy Goodrich: Changes for check writer support. 00363 // 00364 // Revision 1.3 2006/01/13 18:44:30 acg 00365 // Added $Log to record CVS changes into the source. 00366 00367 #endif