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