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_method_process.h -- Method process declarations
23
24  Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005
25
26
27  CHANGE LOG AT THE END OF THE FILE
28 *****************************************************************************/
29
30// $Log: sc_method_process.h,v $
31// Revision 1.23  2011/09/05 21:20:22  acg
32//  Andy Goodrich: result of automake invocation.
33//
34// Revision 1.22  2011/08/29 18:04:32  acg
35//  Philipp A. Hartmann: miscellaneous clean ups.
36//
37// Revision 1.21  2011/08/26 20:46:10  acg
38//  Andy Goodrich: moved the modification log to the end of the file to
39//  eliminate source line number skew when check-ins are done.
40//
41
42#if !defined(sc_method_process_h_INCLUDED)
43#define sc_method_process_h_INCLUDED
44
45#include "sysc/kernel/sc_process.h"
46#include "sysc/kernel/sc_spawn_options.h"
47#include "sysc/kernel/sc_cor.h"
48#include "sysc/kernel/sc_event.h"
49#include "sysc/kernel/sc_except.h"
50
51
52// DEBUGGING MACROS:
53//
54// DEBUG_MSG(NAME,P,MSG)
55//     MSG  = message to print
56//     NAME = name that must match the process for the message to print, or
57//            null if the message should be printed unconditionally.
58//     P    = pointer to process message is for, or NULL in which case the
59//            message will not print.
60#if 0
61#   define DEBUG_NAME ""
62#   define DEBUG_MSG(NAME,P,MSG) \
63    { \
64        if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \
65          std::cout << "**** " << sc_time_stamp() << " ("  \
66	            << sc_get_current_process_name() << "): " << MSG \
67		    << " - " << P->name() << std::endl; \
68    }
69#else
70#   define DEBUG_MSG(NAME,P,MSG)
71#endif
72
73
74namespace sc_core {
75
76// forward function and class declarations:
77
78void sc_method_cor_fn( void* );
79void sc_cmethod_cor_fn( void* );
80void sc_set_stack_size( sc_method_handle, std::size_t );
81class sc_event;
82class sc_module;
83class sc_process_table;
84class sc_process_handle;
85class sc_simcontext;
86class sc_runnable;
87
88void next_trigger( sc_simcontext* );
89void next_trigger( const sc_event&, sc_simcontext* );
90void next_trigger( const sc_event_or_list&, sc_simcontext* );
91void next_trigger( const sc_event_and_list&, sc_simcontext* );
92void next_trigger( const sc_time&, sc_simcontext* );
93void next_trigger( const sc_time&, const sc_event&, sc_simcontext* );
94void next_trigger( const sc_time&, const sc_event_or_list&, sc_simcontext* );
95void next_trigger( const sc_time&, const sc_event_and_list&, sc_simcontext* );
96
97struct sc_invoke_method;
98//==============================================================================
99// sc_method_process -
100//
101//==============================================================================
102class sc_method_process : public sc_process_b {
103    friend struct sc_invoke_method;
104    friend void sc_method_cor_fn( void* );
105    friend void sc_cmethod_cor_fn( void* );
106    friend void sc_set_stack_size( sc_method_handle, std::size_t );
107    friend class sc_event;
108    friend class sc_module;
109    friend class sc_process_table;
110    friend class sc_process_handle;
111    friend class sc_simcontext;
112    friend class sc_runnable;
113
114    friend void next_trigger( sc_simcontext* );
115    friend void next_trigger( const sc_event&,
116                  sc_simcontext* );
117    friend void next_trigger( const sc_event_or_list&,
118                  sc_simcontext* );
119    friend void next_trigger( const sc_event_and_list&,
120                  sc_simcontext* );
121    friend void next_trigger( const sc_time&,
122                  sc_simcontext* );
123    friend void next_trigger( const sc_time&, const sc_event&,
124                  sc_simcontext* );
125    friend void next_trigger( const sc_time&, const sc_event_or_list&,
126                  sc_simcontext* );
127    friend void next_trigger( const sc_time&, const sc_event_and_list&,
128                  sc_simcontext* );
129
130  public:
131    sc_method_process( const char* name_p, bool free_host,
132        SC_ENTRY_FUNC method_p, sc_process_host* host_p,
133        const sc_spawn_options* opt_p );
134
135    virtual const char* kind() const
136        { return "sc_method_process"; }
137
138  protected:
139    void check_for_throws();
140    virtual void disable_process(
141        sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
142    virtual void enable_process(
143        sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
144    inline bool run_process();
145    virtual void kill_process(
146        sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
147    sc_method_handle next_exist();
148    sc_method_handle next_runnable();
149    void clear_trigger();
150    void next_trigger( const sc_event& );
151    void next_trigger( const sc_event_or_list& );
152    void next_trigger( const sc_event_and_list& );
153    void next_trigger( const sc_time& );
154    void next_trigger( const sc_time&, const sc_event& );
155    void next_trigger( const sc_time&, const sc_event_or_list& );
156    void next_trigger( const sc_time&, const sc_event_and_list& );
157    virtual void resume_process(
158        sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
159    void set_next_exist( sc_method_handle next_p );
160    void set_next_runnable( sc_method_handle next_p );
161    void set_stack_size( std::size_t size );
162    virtual void suspend_process(
163        sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
164    virtual void throw_reset( bool async );
165    virtual void throw_user( const sc_throw_it_helper& helper,
166        sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
167    bool trigger_dynamic( sc_event* );
168    inline void trigger_static();
169
170  protected:
171    sc_cor*                          m_cor;        // Thread's coroutine.
172    std::size_t                      m_stack_size; // Thread stack size.
173    std::vector<sc_process_monitor*> m_monitor_q;  // Thread monitors.
174
175  private:
176    // may not be deleted manually (called from sc_process_b)
177    virtual ~sc_method_process();
178
179  private: // disabled
180    sc_method_process( const sc_method_process& );
181    const sc_method_process& operator = ( const sc_method_process& );
182
183};
184
185inline
186void
187sc_method_process::next_trigger( const sc_event& e )
188{
189    clear_trigger();
190    e.add_dynamic( this );
191    m_event_p = &e;
192    m_trigger_type = EVENT;
193}
194
195inline
196void
197sc_method_process::next_trigger( const sc_event_or_list& el )
198{
199    clear_trigger();
200    el.add_dynamic( this );
201    m_event_list_p = &el;
202    m_trigger_type = OR_LIST;
203}
204
205inline
206void
207sc_method_process::next_trigger( const sc_event_and_list& el )
208{
209    clear_trigger();
210    el.add_dynamic( this );
211    m_event_list_p = &el;
212    m_event_count = el.size();
213    m_trigger_type = AND_LIST;
214}
215
216inline
217void
218sc_method_process::next_trigger( const sc_time& t )
219{
220    clear_trigger();
221    m_timeout_event_p->notify_internal( t );
222    m_timeout_event_p->add_dynamic( this );
223    m_trigger_type = TIMEOUT;
224}
225
226inline
227void
228sc_method_process::next_trigger( const sc_time& t, const sc_event& e )
229{
230    clear_trigger();
231    m_timeout_event_p->notify_internal( t );
232    m_timeout_event_p->add_dynamic( this );
233    e.add_dynamic( this );
234    m_event_p = &e;
235    m_trigger_type = EVENT_TIMEOUT;
236}
237
238inline
239void
240sc_method_process::next_trigger( const sc_time& t, const sc_event_or_list& el )
241{
242    clear_trigger();
243    m_timeout_event_p->notify_internal( t );
244    m_timeout_event_p->add_dynamic( this );
245    el.add_dynamic( this );
246    m_event_list_p = &el;
247    m_trigger_type = OR_LIST_TIMEOUT;
248}
249
250inline
251void
252sc_method_process::next_trigger( const sc_time& t, const sc_event_and_list& el )
253{
254    clear_trigger();
255    m_timeout_event_p->notify_internal( t );
256    m_timeout_event_p->add_dynamic( this );
257    el.add_dynamic( this );
258    m_event_list_p = &el;
259    m_event_count = el.size();
260    m_trigger_type = AND_LIST_TIMEOUT;
261}
262
263inline
264void sc_method_process::set_next_exist(sc_method_handle next_p)
265{
266    m_exist_p = next_p;
267}
268
269inline
270sc_method_handle sc_method_process::next_exist()
271{
272    return (sc_method_handle)m_exist_p;
273}
274
275
276inline
277void sc_method_process::set_next_runnable(sc_method_handle next_p)
278{
279    m_runnable_p = next_p;
280}
281
282inline
283sc_method_handle sc_method_process::next_runnable()
284{
285    return (sc_method_handle)m_runnable_p;
286}
287
288// +----------------------------------------------------------------------------
289// |"sc_method_process::run_process"
290// |
291// | This method executes this object instance, including fielding exceptions.
292// |
293// | Result is false if an unfielded exception occurred, true if not.
294// +----------------------------------------------------------------------------
295inline bool sc_method_process::run_process()
296{
297    // Execute this object instance's semantics and catch any exceptions that
298    // are generated:
299
300    bool restart = false;
301    do {
302        try {
303            DEBUG_MSG(DEBUG_NAME,this,"executing method semantics");
304            semantics();
305            restart = false;
306        }
307        catch( sc_unwind_exception& ex ) {
308            DEBUG_MSG(DEBUG_NAME,this,"caught unwind exception");
309            ex.clear();
310            restart = ex.is_reset();
311        }
312        catch( ... ) {
313            sc_report* err_p = sc_handle_exception();
314            simcontext()->set_error( err_p );
315            return false;
316        }
317    } while( restart );
318
319    return true;
320}
321
322//------------------------------------------------------------------------------
323//"sc_method_process::trigger_static"
324//
325// This inline method adds the current method to the queue of runnable
326// processes, if required.  This is the case if the following criteria
327// are met:
328//   (1) The process is in a runnable state.
329//   (2) The process is not already on the run queue.
330//   (3) The process is expecting a static trigger,
331//       dynamic event waits take priority.
332//
333//
334// If the triggering process is the same process, the trigger is
335// ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS
336// is defined.
337//------------------------------------------------------------------------------
338inline
339void
340sc_method_process::trigger_static()
341{
342    if ( (m_state & ps_bit_disabled) || is_runnable() ||
343          m_trigger_type != STATIC )
344        return;
345
346#if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS )
347    if( SC_UNLIKELY_( sc_get_current_process_b() == this ) )
348    {
349        report_immediate_self_notification();
350        return;
351    }
352#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS
353
354    // If we get here then the method is has satisfied its wait, if its
355    // suspended mark its state as ready to run. If its not suspended then
356    // push it onto the runnable queue.
357
358    if ( m_state & ps_bit_suspended )
359    {
360        m_state = m_state | ps_bit_ready_to_run;
361    }
362    else
363    {
364        simcontext()->push_runnable_method(this);
365    }
366}
367
368#undef DEBUG_MSG
369
370} // namespace sc_core
371
372// Revision 1.20  2011/08/24 22:05:50  acg
373//  Torsten Maehne: initialization changes to remove warnings.
374//
375// Revision 1.19  2011/07/29 22:43:15  acg
376//  Andy Goodrich: addition of check_for_throws() method.
377//
378// Revision 1.18  2011/07/24 11:18:09  acg
379//  Philipp A. Hartmann: add code to restart a method process after a
380//  self-reset.
381//
382// Revision 1.17  2011/05/09 04:07:48  acg
383//  Philipp A. Hartmann:
384//    (1) Restore hierarchy in all phase callbacks.
385//    (2) Ensure calls to before_end_of_elaboration.
386//
387// Revision 1.16  2011/04/13 02:41:34  acg
388//  Andy Goodrich: eliminate warning messages generated when the DEBUG_MSG
389//  macro is used.
390//
391// Revision 1.15  2011/04/10 22:12:32  acg
392//  Andy Goodrich: adding debugging macros.
393//
394// Revision 1.14  2011/04/08 22:31:21  acg
395//  Andy Goodrich: added new inline method run_process() to hide the process
396//  implementation for sc_simcontext.
397//
398// Revision 1.13  2011/04/05 20:50:56  acg
399//  Andy Goodrich:
400//    (1) changes to make sure that event(), posedge() and negedge() only
401//        return true if the clock has not moved.
402//    (2) fixes for method self-resumes.
403//    (3) added SC_PRERELEASE_VERSION
404//    (4) removed kernel events from the object hierarchy, added
405//        sc_hierarchy_name_exists().
406//
407// Revision 1.12  2011/04/01 21:24:57  acg
408//  Andy Goodrich: removed unused code.
409//
410// Revision 1.11  2011/02/19 08:30:53  acg
411//  Andy Goodrich: Moved process queueing into trigger_static from
412//  sc_event::notify.
413//
414// Revision 1.10  2011/02/18 20:27:14  acg
415//  Andy Goodrich: Updated Copyrights.
416//
417// Revision 1.9  2011/02/17 19:51:34  acg
418//  Andy Goodrich:
419//    (1) Changed the signature of trigger_dynamic back to a bool.
420//    (2) Removed ready_to_run().
421//    (3) Simplified process control usage.
422//
423// Revision 1.8  2011/02/16 22:37:30  acg
424//  Andy Goodrich: clean up to remove need for ps_disable_pending.
425//
426// Revision 1.7  2011/02/13 21:47:37  acg
427//  Andy Goodrich: update copyright notice.
428//
429// Revision 1.6  2011/02/01 21:05:05  acg
430//  Andy Goodrich: Changes in trigger_dynamic methods to handle new
431//  process control rules about event sensitivity.
432//
433// Revision 1.5  2011/01/18 20:10:44  acg
434//  Andy Goodrich: changes for IEEE1666_2011 semantics.
435//
436// Revision 1.4  2009/07/28 01:10:53  acg
437//  Andy Goodrich: updates for 2.3 release candidate.
438//
439// Revision 1.3  2009/05/22 16:06:29  acg
440//  Andy Goodrich: process control updates.
441//
442// Revision 1.2  2008/05/22 17:06:25  acg
443//  Andy Goodrich: updated copyright notice to include 2008.
444//
445// Revision 1.1.1.1  2006/12/15 20:20:05  acg
446// SystemC 2.3
447//
448// Revision 1.7  2006/05/08 17:57:13  acg
449//  Andy Goodrich: Added David Long's forward declarations for friend functions
450//  to keep the Microsoft C++ compiler happy.
451//
452// Revision 1.6  2006/04/20 17:08:17  acg
453//  Andy Goodrich: 3.0 style process changes.
454//
455// Revision 1.5  2006/04/11 23:13:21  acg
456//   Andy Goodrich: Changes for reduced reset support that only includes
457//   sc_cthread, but has preliminary hooks for expanding to method and thread
458//   processes also.
459//
460// Revision 1.4  2006/01/24 20:49:05  acg
461// Andy Goodrich: changes to remove the use of deprecated features within the
462// simulator, and to issue warning messages when deprecated features are used.
463//
464// Revision 1.3  2006/01/13 18:44:29  acg
465// Added $Log to record CVS changes into the source.
466
467#endif // !defined(sc_method_process_h_INCLUDED)
468