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