SystemC  2.3.1
Accellera SystemC proof-of-concept library
sc_simcontext_int.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  The following code is derived, directly or indirectly, from the SystemC
4  source code Copyright (c) 1996-2014 by all Contributors.
5  All Rights reserved.
6 
7  The contents of this file are subject to the restrictions and limitations
8  set forth in the SystemC Open Source License (the "License");
9  You may not use this file except in compliance with such restrictions and
10  limitations. You may obtain instructions on how to receive a copy of the
11  License at http://www.accellera.org/. Software distributed by Contributors
12  under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
13  ANY KIND, either express or implied. See the License for the specific
14  language governing rights and limitations under the License.
15 
16  *****************************************************************************/
17 
18 /*****************************************************************************
19 
20  sc_simcontext_int.h -- For inline definitions of some utility functions.
21  DO NOT EXPORT THIS INCLUDE FILE. Include this file
22  after "sc_process_int.h" so that we can get the base
23  class right.
24 
25  Original Author: Stan Y. Liao, Synopsys, Inc.
26 
27  CHANGE LOG AT THE END OF THE FILE
28  *****************************************************************************/
29 
30 #ifndef SC_SIMCONTEXT_INT_H
31 #define SC_SIMCONTEXT_INT_H
32 
36 
37 // DEBUGGING MACROS:
38 //
39 // DEBUG_MSG(NAME,P,MSG)
40 // MSG = message to print
41 // NAME = name that must match the process for the message to print, or
42 // null if the message should be printed unconditionally.
43 // P = pointer to process message is for, or NULL in which case the
44 // message will not print.
45 #if 0
46 # define DEBUG_NAME ""
47 # define DEBUG_MSG(NAME,P,MSG) \
48  { \
49  if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \
50  std::cout << "**** " << sc_time_stamp() << " (" \
51  << sc_get_current_process_name() << "): " << MSG \
52  << " - " << P->name() << std::endl; \
53  }
54 #else
55 # define DEBUG_MSG(NAME,P,MSG)
56 #endif
57 
58 
59 namespace sc_core {
60 
61 inline
62 const char*
64 {
65  sc_process_b* active_p; // active process to get name of.
66  const char* result; // name of active process.
67 
69  if ( active_p )
70  result = active_p->name();
71  else
72  result = "** NONE **";
73  return result;
74 }
75 
76 // We use m_current_writer rather than m_curr_proc_info.process_handle to
77 // return the active process for sc_signal<T>::check_write since that lets
78 // us turn it off a library compile time, and only incur the overhead at
79 // the time of process switches rather than having to interrogate an
80 // additional switch every time a signal is written.
81 
82 inline
83 void
85 {
86  m_curr_proc_info.process_handle = process_h;
87  m_curr_proc_info.kind = process_h->proc_kind();
88  m_current_writer = m_write_check ? process_h : (sc_object*)0;
89 }
90 
91 inline
92 void
94 {
95  m_curr_proc_info.process_handle = 0;
96  m_curr_proc_info.kind = SC_NO_PROC_;
97  m_current_writer = 0;
99 }
100 
101 inline
102 void
103 sc_simcontext::execute_method_next( sc_method_handle method_h )
104 {
105  m_runnable->execute_method_next( method_h );
106 }
107 
108 inline
109 void
110 sc_simcontext::execute_thread_next( sc_thread_handle thread_h )
111 {
112  m_runnable->execute_thread_next( thread_h );
113 }
114 
115 // +----------------------------------------------------------------------------
116 // |"sc_simcontext::preempt_with"
117 // |
118 // | This method executes the supplied thread immediately, suspending the
119 // | caller. After executing the supplied thread the caller's execution will
120 // | be restored. It is used to allow a thread to immediately throw an
121 // | exception, e.g., when the thread's kill_process() method was called.
122 // | There are three cases to consider:
123 // | (1) The caller is a method, e.g., murder by method.
124 // | (2) The caller is another thread instance, e.g., murder by thread.
125 // | (3) The caller is this thread instance, e.g., suicide.
126 // |
127 // | Arguments:
128 // | thread_h -> thread to be executed.
129 // +----------------------------------------------------------------------------
130 inline
131 void
132 sc_simcontext::preempt_with( sc_thread_handle thread_h )
133 {
134  sc_thread_handle active_p; // active thread or null.
135  sc_curr_proc_info caller_info; // process info for caller.
136 
137  // Determine the active process and take the thread to be run off the
138  // run queue, if its there, since we will be explicitly causing its
139  // execution.
140 
141  active_p = DCAST<sc_thread_handle>(sc_get_current_process_b());
142  if ( thread_h->next_runnable() != NULL )
143  remove_runnable_thread( thread_h );
144 
145  // THE CALLER IS A METHOD:
146  //
147  // (a) Set the current process information to our thread.
148  // (b) If the method was called by an invoker thread push that thread
149  // onto the front of the run queue, this will cause the method
150  // to be resumed after this thread waits.
151  // (c) Invoke our thread directly by-passing the run queue.
152  // (d) Restore the process info to the caller.
153  // (e) Check to see if the calling method should throw an exception
154  // because of activity that occurred during the preemption.
155 
156  if ( active_p == NULL )
157  {
158  std::vector<sc_thread_handle>* invokers_p; // active invokers stack.
159  sc_thread_handle invoke_thread_p; // latest invocation thread.
160  sc_method_handle method_p; // active method.
161 
162  method_p = DCAST<sc_method_handle>(sc_get_current_process_b());
163  invokers_p = &get_active_invokers();
164  caller_info = m_curr_proc_info;
165  if ( invokers_p->size() != 0 )
166  {
167  invoke_thread_p = invokers_p->back();
168  DEBUG_MSG( DEBUG_NAME, invoke_thread_p,
169  "queueing invocation thread to execute next" );
170  execute_thread_next(invoke_thread_p);
171  }
172  DEBUG_MSG( DEBUG_NAME, thread_h, "preempting method with thread" );
173  set_curr_proc( (sc_process_b*)thread_h );
174  m_cor_pkg->yield( thread_h->m_cor_p );
175  m_curr_proc_info = caller_info;
176  DEBUG_MSG(DEBUG_NAME, thread_h, "back from preempting method w/thread");
177  method_p->check_for_throws();
178  }
179 
180  // CALLER IS A THREAD, BUT NOT THE THREAD TO BE RUN:
181  //
182  // (a) Push the calling thread onto the front of the runnable queue
183  // so it be the first thread to be run after this thread.
184  // (b) Push the thread to be run onto the front of the runnable queue so
185  // it will execute when we suspend the calling thread.
186  // (c) Suspend the active thread.
187 
188  else if ( active_p != thread_h )
189  {
190  DEBUG_MSG( DEBUG_NAME, thread_h,
191  "preempting active thread with thread" );
192  execute_thread_next( active_p );
193  execute_thread_next( thread_h );
194  active_p->suspend_me();
195  }
196 
197  // CALLER IS THE THREAD TO BE RUN:
198  //
199  // (a) Push the thread to be run onto the front of the runnable queue so
200  // it will execute when we suspend the calling thread.
201  // (b) Suspend the active thread.
202 
203  else
204  {
205  DEBUG_MSG(DEBUG_NAME,thread_h,"self preemption of active thread");
206  execute_thread_next( thread_h );
207  active_p->suspend_me();
208  }
209 }
210 
211 
212 inline
213 void
214 sc_simcontext::push_runnable_method( sc_method_handle method_h )
215 {
216  m_runnable->push_back_method( method_h );
217 }
218 
219 inline
220 void
221 sc_simcontext::push_runnable_method_front( sc_method_handle method_h )
222 {
223  m_runnable->push_front_method( method_h );
224 }
225 
226 inline
227 void
228 sc_simcontext::push_runnable_thread( sc_thread_handle thread_h )
229 {
230  m_runnable->push_back_thread( thread_h );
231 }
232 
233 inline
234 void
235 sc_simcontext::push_runnable_thread_front( sc_thread_handle thread_h )
236 {
237  m_runnable->push_front_thread( thread_h );
238 }
239 
240 
241 inline
243 sc_simcontext::pop_runnable_method()
244 {
245  sc_method_handle method_h = m_runnable->pop_method();
246  if( method_h == 0 ) {
247  reset_curr_proc();
248  return 0;
249  }
250  set_curr_proc( (sc_process_b*)method_h );
251  return method_h;
252 }
253 
254 inline
256 sc_simcontext::pop_runnable_thread()
257 {
258  sc_thread_handle thread_h = m_runnable->pop_thread();
259  if( thread_h == 0 ) {
260  reset_curr_proc();
261  return 0;
262  }
263  set_curr_proc( (sc_process_b*)thread_h );
264  return thread_h;
265 }
266 
267 inline
268 void
269 sc_simcontext::remove_runnable_method( sc_method_handle method_h )
270 {
271  m_runnable->remove_method( method_h );
272 }
273 
274 inline
275 void
276 sc_simcontext::remove_runnable_thread( sc_thread_handle thread_h )
277 {
278  m_runnable->remove_thread( thread_h );
279 }
280 
281 inline
282 std::vector<sc_thread_handle>&
284 {
285  return m_active_invokers;
286 }
287 
288 // ----------------------------------------------------------------------------
289 
290 extern void sc_defunct_process_function( sc_module* );
291 
292 
293 } // namespace sc_core
294 
295 #undef DEBUG_MSG
296 #undef DEBUG_NAME
297 
298 // $Log: sc_simcontext_int.h,v $
299 // Revision 1.14 2011/08/29 18:04:32 acg
300 // Philipp A. Hartmann: miscellaneous clean ups.
301 //
302 // Revision 1.13 2011/08/26 20:46:11 acg
303 // Andy Goodrich: moved the modification log to the end of the file to
304 // eliminate source line number skew when check-ins are done.
305 //
306 // Revision 1.12 2011/07/29 22:45:06 acg
307 // Andy Goodrich: added invocation of sc_method_process::check_for_throws()
308 // to the preempt_with() code to handle case where the preempting process
309 // causes a throw on the invoking method process.
310 //
311 // Revision 1.11 2011/04/13 02:45:11 acg
312 // Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG
313 // macro was used.
314 //
315 // Revision 1.10 2011/04/11 22:05:48 acg
316 // Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations.
317 //
318 // Revision 1.9 2011/04/10 22:12:32 acg
319 // Andy Goodrich: adding debugging macros.
320 //
321 // Revision 1.8 2011/04/08 18:26:07 acg
322 // Andy Goodrich: added execute_method_next() to handle method dispatch
323 // for asynchronous notifications that occur outside the evaluation phase.
324 //
325 // Revision 1.7 2011/02/18 20:27:14 acg
326 // Andy Goodrich: Updated Copyrights.
327 //
328 // Revision 1.6 2011/02/13 21:47:38 acg
329 // Andy Goodrich: update copyright notice.
330 //
331 // Revision 1.5 2011/02/08 08:17:50 acg
332 // Andy Goodrich: fixed bug in preempt_with() where I was resetting the
333 // process context rather than saving and restoring it.
334 //
335 // Revision 1.4 2011/02/01 21:12:56 acg
336 // Andy Goodrich: addition of preempt_with() method to allow immediate
337 // execution of threads for throws.
338 //
339 // Revision 1.3 2011/01/25 20:50:37 acg
340 // Andy Goodrich: changes for IEEE 1666 2011.
341 //
342 // Revision 1.2 2008/05/22 17:06:26 acg
343 // Andy Goodrich: updated copyright notice to include 2008.
344 //
345 // Revision 1.1.1.1 2006/12/15 20:20:05 acg
346 // SystemC 2.3
347 //
348 // Revision 1.6 2006/05/26 20:33:16 acg
349 // Andy Goodrich: changes required by additional platform compilers (i.e.,
350 // Microsoft VC++, Sun Forte, HP aCC).
351 //
352 // Revision 1.5 2006/01/19 00:29:52 acg
353 // Andy Goodrich: Yet another implementation for signal write checking. This
354 // one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to
355 // DISABLE will disable write checking on signals.
356 //
357 // Revision 1.4 2006/01/18 21:42:37 acg
358 // Andy Goodrich: Changes for check writer support.
359 //
360 // Revision 1.3 2006/01/13 18:44:30 acg
361 // Added $Log to record CVS changes into the source.
362 
363 #endif
const char * name() const
Definition: sc_object.h:67
void push_front_thread(sc_thread_handle)
static sc_process_b * m_last_created_process_p
Definition: sc_process.h:444
friend class sc_process_b
void push_front_method(sc_method_handle)
sc_process_b * sc_get_current_process_b()
sc_curr_proc_handle get_curr_proc_info()
sc_simcontext * sc_get_curr_simcontext()
class sc_thread_process * sc_thread_handle
Definition: sc_process.h:58
void push_back_method(sc_method_handle)
void execute_method_next(sc_method_handle)
#define DEBUG_MSG(NAME, P, MSG)
void set_curr_proc(sc_process_b *)
const char * sc_get_current_process_name()
void execute_thread_next(sc_thread_handle)
void remove_method(sc_method_handle)
void push_back_thread(sc_thread_handle)
void remove_thread(sc_thread_handle)
sc_process_b * process_handle
Definition: sc_simcontext.h:71
sc_curr_proc_kind kind
Definition: sc_simcontext.h:72
sc_method_handle pop_method()
class sc_method_process * sc_method_handle
Definition: sc_process.h:57
virtual void yield(sc_cor *next_cor)=0
sc_curr_proc_kind proc_kind() const
Definition: sc_process.h:588
void sc_defunct_process_function(sc_module *)
sc_thread_handle pop_thread()
std::vector< sc_thread_handle > & get_active_invokers()