sc_process.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2006 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 Version 2.4 (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.systemc.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_process.h -- Process base class support.
00021 
00022   Original Author: Andy Goodrich, Forte Design Systems, 04 August 2005
00023 
00024 
00025  *****************************************************************************/
00026 
00027 /*****************************************************************************
00028 
00029   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00030   changes you are making here.
00031 
00032       Name, Affiliation, Date: Andy Goodrich, Forte Design Systems, 12 Aug 05
00033   Description of Modification: This is the rewrite of process support. It
00034                                contains some code from the original
00035                                sc_process.h by Stan Liao, and the now-defunct
00036                                sc_process_b.h by Stan Liao and Martin
00037                                Janssen, all of Synopsys, Inc., It also contains
00038                                code from the original sc_process_b.h by
00039                                Andy Goodrich of Forte Design Systems and
00040                                Bishnupriya Bhattacharya of Cadence Design
00041                                Systems.
00042 
00043       Name, Affiliation, Date:
00044   Description of Modification:
00045 
00046  *****************************************************************************/
00047 
00048 // $Log: sc_process.h,v $
00049 // Revision 1.1.1.1  2006/12/15 20:31:37  acg
00050 // SystemC 2.2
00051 //
00052 // Revision 1.7  2006/04/11 23:13:21  acg
00053 //   Andy Goodrich: Changes for reduced reset support that only includes
00054 //   sc_cthread, but has preliminary hooks for expanding to method and thread
00055 //   processes also.
00056 //
00057 // Revision 1.6  2006/03/13 20:26:50  acg
00058 //  Andy Goodrich: Addition of forward class declarations, e.g.,
00059 //  sc_reset, to keep gcc 4.x happy.
00060 //
00061 // Revision 1.5  2006/01/31 20:09:10  acg
00062 //  Andy Goodrich: added explaination of static vs dynamic waits to
00063 //  sc_process_b::trigger_static.
00064 //
00065 // Revision 1.4  2006/01/24 20:49:05  acg
00066 // Andy Goodrich: changes to remove the use of deprecated features within the
00067 // simulator, and to issue warning messages when deprecated features are used.
00068 //
00069 // Revision 1.3  2006/01/13 18:44:30  acg
00070 // Added $Log to record CVS changes into the source.
00071 //
00072 
00073 #if !defined(sc_process_h_INCLUDED)
00074 #define sc_process_h_INCLUDED
00075 
00076 #include <cassert>
00077 #include "sysc/utils/sc_iostream.h"
00078 #include "sysc/kernel/sc_constants.h"
00079 #include "sysc/kernel/sc_object.h"
00080 #include "sysc/kernel/sc_kernel_ids.h"
00081 #include "sysc/kernel/sc_reset.h"
00082 #include "sysc/communication/sc_export.h"
00083 
00084 namespace sc_core {
00085 
00086 // Forward declarations:
00087 class sc_process_handle;
00088 class sc_reset;
00089 
00090 // friend function declarations
00091     const char* sc_gen_unique_name( const char*, bool preserve_first );
00092     sc_process_handle sc_get_current_process_handle();
00093     void sc_thread_cor_fn( void* arg );
00094     void sc_cthread_cor_fn( void* arg );
00095     bool timed_out( sc_simcontext* );
00096 
00097 
00098 // Process handles as forward references:
00099 
00100 typedef class sc_cthread_process* sc_cthread_handle;
00101 typedef class sc_method_process*  sc_method_handle;
00102 typedef class sc_thread_process*  sc_thread_handle;
00103 
00104 
00105 // Standard process types:
00106 
00107 enum sc_curr_proc_kind
00108 {
00109     SC_NO_PROC_,
00110     SC_METHOD_PROC_,
00111     SC_THREAD_PROC_,
00112     SC_CTHREAD_PROC_
00113 };
00114 
00115 //==============================================================================
00116 // CLASS sc_process_host
00117 //
00118 // This is the base class for objects which may have processes defined for
00119 // their methods (e.g., sc_module)
00120 //==============================================================================
00121 
00122 class sc_process_host
00123 {
00124   public:
00125     sc_process_host() {}
00126     virtual ~sc_process_host() { } // Needed for cast check for sc_module.
00127     void defunct() {}
00128 };
00129 
00130 
00131 //==============================================================================
00132 // CLASS sc_process_monitor
00133 //
00134 // This class provides a way of monitoring a process' status (e.g., waiting
00135 // for a thread to complete its execution.) This class is intended to be a base
00136 // class for classes which need to monitor a process or processes (e.g.,
00137 // sc_join.) Its methods should be overloaded where notifications are desired.
00138 //==============================================================================
00139 
00140 class sc_process_monitor {
00141   public:
00142     enum {
00143         spm_exit = 0
00144     };
00145     virtual ~sc_process_monitor() {}
00146     virtual void signal(sc_thread_handle thread_p, int type) {}
00147 };
00148 
00149 //------------------------------------------------------------------------------
00150 // PROCESS INVOCATION METHOD OR FUNCTION:
00151 //
00152 //  Define SC_USE_MEMBER_FUNC_PTR if we want to use member function pointers
00153 //  to implement process dispatch. Otherwise, we'll use a hack that involves
00154 //  creating a templated invocation object which will invoke the member
00155 //  function. This should not be necessary, but some compilers (e.g., VC++)
00156 //  do not allow the conversion from `void (callback_tag::*)()' to
00157 //  `void (sc_process_host::*)()'. This is supposed to be OK as long as the
00158 //  dynamic type is correct.  C++ Standard 5.4 "Explicit type conversion",
00159 //  clause 7: a pointer to member of derived class type may be explicitly
00160 //  converted to a pointer to member of an unambiguous non-virtual base class
00161 //  type.
00162 //-----------------------------------------------------------------------------
00163 
00164 #if defined(_MSC_VER)
00165 #if ( _MSC_VER > 1200 )
00166 #   define SC_USE_MEMBER_FUNC_PTR
00167 #endif
00168 #else
00169 #   define SC_USE_MEMBER_FUNC_PTR
00170 #endif
00171 
00172 
00173 // COMPILER DOES SUPPORT CAST TO void (sc_process_host::*)() from (T::*)():
00174 
00175 #if defined(SC_USE_MEMBER_FUNC_PTR)
00176 
00177     typedef void (sc_process_host::*SC_ENTRY_FUNC)();
00178 #   define SC_DECL_HELPER_STRUCT(callback_tag, func) /*EMPTY*/
00179 #   define SC_MAKE_FUNC_PTR(callback_tag, func) \
00180         static_cast<sc_core::SC_ENTRY_FUNC>(&callback_tag::func)
00181 
00182 
00183 // COMPILER NOT DOES SUPPORT CAST TO void (sc_process_host::*)() from (T::*)():
00184 
00185 #else // !defined(SC_USE_MEMBER_FUNC_PTR)
00186     class sc_process_call_base {
00187       public:
00188         inline sc_process_call_base()
00189         {
00190         }
00191 
00192         virtual ~sc_process_call_base()
00193         {
00194         }
00195 
00196         virtual void invoke(sc_process_host* host_p)
00197         {
00198         }
00199     };
00200     extern sc_process_call_base sc_process_defunct;
00201 
00202     template<class T>
00203     class sc_process_call : public sc_process_call_base {
00204       public:
00205         sc_process_call( void (T::*method_p)() ) :
00206             sc_process_call_base()
00207         {
00208              m_method_p = method_p;
00209         }
00210 
00211         virtual ~sc_process_call()
00212         {
00213         }
00214 
00215         virtual void invoke(sc_process_host* host_p)
00216         {
00217             (((T*)host_p)->*m_method_p)();
00218         }
00219 
00220       protected:
00221         void (T::*m_method_p)();  // Method implementing the process.
00222     };
00223 
00224     typedef sc_process_call_base* SC_ENTRY_FUNC;
00225 #   define SC_DECL_HELPER_STRUCT(callback_tag, func) /*EMPTY*/
00226 #   define SC_MAKE_FUNC_PTR(callback_tag, func) \
00227         (::sc_core::SC_ENTRY_FUNC) (new \
00228         ::sc_core::sc_process_call<callback_tag>(&callback_tag::func))
00229 
00230 #endif // !defined(SC_USE_MEMBER_FUNC_PTR)
00231 
00232 
00233 extern void sc_set_stack_size( sc_thread_handle, std::size_t );
00234 
00235 class sc_event;
00236 class sc_event_list;
00237 class sc_name_gen;
00238 class sc_spawn_options;
00239 
00240 //==============================================================================
00241 // CLASS sc_process_b - USER INITIATED DYNAMIC PROCESS SUPPORT:
00242 //
00243 // This class implements the base class for a threaded process_base process
00244 // whose semantics are provided by the true virtual method semantics().
00245 // Classes derived from this one will provide a version of semantics which
00246 // implements the desired semantics. See the sc_spawn_xxx classes below.
00247 //
00248 // Notes:
00249 //   (1) Object instances of this class maintain a reference count of
00250 //       outstanding handles. When the handle count goes to zero the
00251 //       object will be deleted.
00252 //   (2) Descriptions of the methods and operators in this class appear with
00253 //       their implementations.
00254 //==============================================================================
00255 class sc_process_b : public sc_object {
00256     friend class sc_process_handle; // Allow handles to modify ref. count.
00257     friend class sc_simcontext;     // Allow static processes to have base.
00258 
00259     friend class sc_object;
00260     friend class sc_port_base;
00261     friend class sc_runnable;
00262     friend class sc_sensitive;
00263     friend class sc_sensitive_pos;
00264     friend class sc_sensitive_neg;
00265     friend class sc_module;
00266     friend class sc_report_handler;
00267     friend class sc_reset;
00268     friend class sc_reset_finder;
00269     friend const char* sc_gen_unique_name( const char*, bool preserve_first );
00270     friend sc_process_handle sc_get_current_process_handle();
00271     friend void sc_thread_cor_fn( void* arg );
00272     friend void sc_cthread_cor_fn( void* arg );
00273     friend bool timed_out( sc_simcontext* );
00274 
00275   public:
00276     enum process_throw_type {
00277         THROW_NONE = 0,
00278         THROW_RESET
00279     };
00280     enum trigger_t
00281     {
00282         STATIC,
00283         EVENT,
00284         OR_LIST,
00285         AND_LIST,
00286         TIMEOUT,
00287         EVENT_TIMEOUT,
00288         OR_LIST_TIMEOUT,
00289         AND_LIST_TIMEOUT
00290     };
00291 
00292   public:
00293     sc_process_b( const char* name_p, bool free_host,
00294         SC_ENTRY_FUNC method_p, sc_process_host* host_p,
00295         const sc_spawn_options* opt_p );
00296     virtual ~sc_process_b();
00297 
00298   public:
00299     bool dont_initialize() const { return m_dont_init; }
00300     virtual void dont_initialize( bool dont );
00301     const ::std::vector<sc_object*>& get_child_objects() const;
00302     inline sc_curr_proc_kind proc_kind() const;
00303     sc_event& terminated_event();
00304 
00305   public:
00306     static inline sc_process_handle last_created_process_handle();
00307 
00308   protected:
00309     void add_static_event( const sc_event& );
00310     bool dynamic() const { return m_dynamic_proc; }
00311     const char* gen_unique_name( const char* basename_, bool preserve_first );
00312     inline sc_report* get_last_report() { return m_last_report_p; }
00313     inline bool is_runnable();
00314     static inline sc_process_b* last_created_process_base();
00315     inline void set_last_report( sc_report* last_p )
00316         {
00317             if ( m_last_report_p ) delete m_last_report_p;
00318             m_last_report_p = last_p;
00319         }
00320     void remove_static_events();
00321     bool trigger_static();
00322     inline bool timed_out() const;
00323 
00324   private: // structure support:
00325     void add_child_object( sc_object* );
00326     void remove_child_object( sc_object* );
00327 
00328 
00329   protected: // process control methods:
00330     virtual void kill_process();
00331     inline void reset_changed();
00332     virtual bool terminated() const;
00333 
00334   private:
00335     inline void reference_decrement();
00336     inline void reference_increment();
00337 
00338   protected:
00339     inline void semantics();
00340 
00341     // debugging stuff:
00342 
00343   public:
00344     const char*                 file;
00345     int                         lineno;
00346     int                         proc_id;
00347 
00348   protected:
00349     std::vector<sc_object*>      m_child_objects;  // Child processes.
00350     bool                         m_dont_init;      // True: no initialize call.
00351     bool                         m_dynamic_proc;   // True: after elaboration.
00352     const sc_event*              m_event_p;        // Dynamic event waiting on.
00353     int                          m_event_count;    // Number of events.
00354     sc_event_list*               m_event_list_p;   // Event list waiting on.
00355     sc_process_b*                m_exist_p;        // Process existence link.
00356     bool                         m_free_host;      // Free sc_semantic_host_p.
00357     sc_report*                   m_last_report_p;  // Last report this process.
00358     sc_name_gen*                 m_name_gen_p;     // Subprocess name generator.
00359     sc_curr_proc_kind            m_process_kind;   // Type of process.
00360     int                          m_references_n;   // Outstanding handles.
00361     bool                         m_reset_level;    // Level for reset.
00362     sc_reset*                    m_reset_p;        // Reset object.
00363     sc_process_b*                m_runnable_p;     // sc_runnable link
00364     sc_process_host*             m_semantics_host_p;   // Host for semantics.
00365     SC_ENTRY_FUNC                m_semantics_method_p; // Method for semantics.
00366     std::vector<const sc_event*> m_static_events;   // Static events waiting on.
00367     sc_event*                    m_term_event_p;    // Terminated event.
00368     process_throw_type           m_throw_type;      // Throw type.
00369     bool                         m_timed_out;       // True if we timed out.
00370     sc_event*                    m_timeout_event_p; // Timeout event.
00371     trigger_t                    m_trigger_type;    // Type of trigger using.
00372     bool                         m_zombie;          // True if terminated.
00373 
00374   protected:
00375     static sc_process_b* m_delete_next_p;          // Next process to delete.
00376     static sc_process_b* m_last_created_process_p; // Last process created.
00377 };
00378 
00379 typedef sc_process_b sc_process_b;  // For compatibility.
00380 
00381 
00382 //------------------------------------------------------------------------------
00383 //"sc_process_b::XXXX_child_YYYYY"
00384 //
00385 // These methods provide child object support.
00386 //------------------------------------------------------------------------------
00387 inline void
00388 sc_process_b::add_child_object( sc_object* object_ )
00389 {
00390     // no check if object_ is already in the set
00391     m_child_objects.push_back( object_ );
00392 }
00393 
00394 inline void
00395 sc_process_b::remove_child_object( sc_object* object_ )
00396 {
00397     int size = m_child_objects.size();
00398     for( int i = 0; i < size; ++ i ) {
00399         if( object_ == m_child_objects[i] ) {
00400             m_child_objects[i] = m_child_objects[size - 1];
00401             m_child_objects.resize(size-1);
00402             return;
00403         }
00404     }
00405     // no check if object_ is really in the set
00406 }
00407 
00408 inline const ::std::vector<sc_object*>&
00409 sc_process_b::get_child_objects() const
00410 {
00411     return m_child_objects;
00412 }
00413 
00414 
00415 //------------------------------------------------------------------------------
00416 //"sc_process_b::is_runnable"
00417 //
00418 // This method returns true if this process is runnable. That is indicated
00419 // by a non-zero m_runnable_p field.
00420 //------------------------------------------------------------------------------
00421 inline bool sc_process_b::is_runnable()
00422 {
00423     return m_runnable_p != 0;
00424 }
00425 
00426 
00427 //------------------------------------------------------------------------------
00428 //"sc_process_b::last_created_process_base"
00429 //
00430 // This virtual method returns the sc_process_b pointer for the last
00431 // created process. It is only used internally by the simulator.
00432 //------------------------------------------------------------------------------
00433 inline sc_process_b* sc_process_b::last_created_process_base()
00434 {
00435     return m_last_created_process_p;
00436 }
00437 
00438 
00439 
00440 //------------------------------------------------------------------------------
00441 //"sc_process_b::proc_kind"
00442 //
00443 // This method returns the kind of this process.
00444 //------------------------------------------------------------------------------
00445 inline sc_curr_proc_kind sc_process_b::proc_kind() const
00446 {
00447     return m_process_kind;
00448 }
00449 
00450 
00451 //------------------------------------------------------------------------------
00452 //"sc_process_b::reference_decrement"
00453 //
00454 // This inline method decrements the number of outstanding references to this
00455 // object instance. If the number of references goes to zero, this object
00456 // instance is placed on the deletion queue, after deleting any process that
00457 // is already there. The reason for the two step deletion process is that the
00458 // process from which reference_decrement() is called is likely to be the
00459 // running process, so we have to wait until it goes idle.
00460 //------------------------------------------------------------------------------
00461 inline void sc_process_b::reference_decrement()
00462 {
00463     m_references_n--;
00464     if ( m_references_n == 0 )
00465     {
00466         if ( m_delete_next_p ) delete m_delete_next_p;
00467         assert(m_delete_next_p != this);
00468         m_delete_next_p = this;
00469     }
00470 }
00471 
00472 
00473 //------------------------------------------------------------------------------
00474 //"sc_process_b::reference_increment"
00475 //
00476 // This inline method increments the number of outstanding references to this
00477 // object instance.
00478 //------------------------------------------------------------------------------
00479 inline void sc_process_b::reference_increment()
00480 {
00481     assert(m_references_n != 0);
00482     m_references_n++;
00483 }
00484 
00485 //------------------------------------------------------------------------------
00486 //"sc_process_b::reset_changed"
00487 //
00488 // This method is called when there is a change in the value of the
00489 // signal specified via reset_signal_is. If reset_signal_is was not
00490 // called this method won't be either.
00491 //------------------------------------------------------------------------------
00492 inline void sc_process_b::reset_changed()
00493 {
00494     m_throw_type = ( m_reset_p->read() == m_reset_level ) ?
00495         THROW_RESET : THROW_NONE;
00496 }
00497 
00498 
00499 //------------------------------------------------------------------------------
00500 //"sc_process_b::semantics"
00501 //
00502 // This inline method invokes the semantics for this object instance.
00503 // We check to see if we are initially in reset and then invoke the
00504 // process semantics.
00505 //------------------------------------------------------------------------------
00506 inline void sc_process_b::semantics()
00507 {
00508     assert( m_process_kind != SC_NO_PROC_ );
00509     m_throw_type = ( m_reset_p && m_reset_p->read() == m_reset_level ) ?
00510         THROW_RESET : THROW_NONE;
00511 #   ifndef SC_USE_MEMBER_FUNC_PTR
00512         m_semantics_method_p->invoke( m_semantics_host_p );
00513 #   else
00514         (m_semantics_host_p->*m_semantics_method_p)();
00515 #   endif
00516 }
00517 
00518 
00519 //------------------------------------------------------------------------------
00520 //"sc_process_b::terminated"
00521 //
00522 // This inline method returns true if this object has terminated.
00523 //------------------------------------------------------------------------------
00524 inline bool sc_process_b::terminated() const
00525 {
00526     return m_zombie;
00527 }
00528 
00529 
00530 //------------------------------------------------------------------------------
00531 //"sc_process_b::timed_out"
00532 //
00533 // This inline method returns true if this object instance timed out.
00534 //------------------------------------------------------------------------------
00535 inline bool sc_process_b::timed_out() const
00536 {
00537     return m_timed_out;
00538 }
00539 
00540 
00541 //------------------------------------------------------------------------------
00542 //"sc_process_b::trigger_static"
00543 //
00544 // This inline method returns true if this object instance is waiting on
00545 // a static trigger and is not runnable. If there trigger is not static
00546 // then the process is waiting on a dynamically specified event, so the
00547 // static trigger should be ignored until that dynamic event occurs.
00548 //------------------------------------------------------------------------------
00549 inline
00550 bool
00551 sc_process_b::trigger_static()
00552 {
00553     return ( !is_runnable() && m_trigger_type == STATIC );
00554 }
00555 
00556 
00557 } // namespace sc_core
00558 
00559 #endif // !defined(sc_process_h_INCLUDED)

Generated on Wed Jan 21 15:32:09 2009 for SystemC by  doxygen 1.5.5