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