| /***************************************************************************** | |
| Licensed to Accellera Systems Initiative Inc. (Accellera) under one or | |
| more contributor license agreements. See the NOTICE file distributed | |
| with this work for additional information regarding copyright ownership. | |
| Accellera licenses this file to you under the Apache License, Version 2.0 | |
| (the "License"); you may not use this file except in compliance with the | |
| License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |
| implied. See the License for the specific language governing | |
| permissions and limitations under the License. | |
| *****************************************************************************/ | |
| /***************************************************************************** | |
| sc_method_process.h -- Method process declarations | |
| Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 | |
| CHANGE LOG AT THE END OF THE FILE | |
| *****************************************************************************/ | |
| // $Log: sc_method_process.h,v $ | |
| // Revision 1.23 2011/09/05 21:20:22 acg | |
| // Andy Goodrich: result of automake invocation. | |
| // | |
| // Revision 1.22 2011/08/29 18:04:32 acg | |
| // Philipp A. Hartmann: miscellaneous clean ups. | |
| // | |
| // Revision 1.21 2011/08/26 20:46:10 acg | |
| // Andy Goodrich: moved the modification log to the end of the file to | |
| // eliminate source line number skew when check-ins are done. | |
| // | |
| #if !defined(sc_method_process_h_INCLUDED) | |
| #define sc_method_process_h_INCLUDED | |
| #include "sysc/kernel/sc_process.h" | |
| #include "sysc/kernel/sc_spawn_options.h" | |
| #include "sysc/kernel/sc_cor.h" | |
| #include "sysc/kernel/sc_event.h" | |
| #include "sysc/kernel/sc_except.h" | |
| // DEBUGGING MACROS: | |
| // | |
| // DEBUG_MSG(NAME,P,MSG) | |
| // MSG = message to print | |
| // NAME = name that must match the process for the message to print, or | |
| // null if the message should be printed unconditionally. | |
| // P = pointer to process message is for, or NULL in which case the | |
| // message will not print. | |
| #if 0 | |
| # define DEBUG_NAME "" | |
| # define DEBUG_MSG(NAME,P,MSG) \ | |
| { \ | |
| if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ | |
| std::cout << "**** " << sc_time_stamp() << " (" \ | |
| << sc_get_current_process_name() << "): " << MSG \ | |
| << " - " << P->name() << std::endl; \ | |
| } | |
| #else | |
| # define DEBUG_MSG(NAME,P,MSG) | |
| #endif | |
| namespace sc_core { | |
| // forward function and class declarations: | |
| void sc_method_cor_fn( void* ); | |
| void sc_cmethod_cor_fn( void* ); | |
| void sc_set_stack_size( sc_method_handle, std::size_t ); | |
| class sc_event; | |
| class sc_module; | |
| class sc_process_table; | |
| class sc_process_handle; | |
| class sc_simcontext; | |
| class sc_runnable; | |
| void next_trigger( sc_simcontext* ); | |
| void next_trigger( const sc_event&, sc_simcontext* ); | |
| void next_trigger( const sc_event_or_list&, sc_simcontext* ); | |
| void next_trigger( const sc_event_and_list&, sc_simcontext* ); | |
| void next_trigger( const sc_time&, sc_simcontext* ); | |
| void next_trigger( const sc_time&, const sc_event&, sc_simcontext* ); | |
| void next_trigger( const sc_time&, const sc_event_or_list&, sc_simcontext* ); | |
| void next_trigger( const sc_time&, const sc_event_and_list&, sc_simcontext* ); | |
| struct sc_invoke_method; | |
| //============================================================================== | |
| // sc_method_process - | |
| // | |
| //============================================================================== | |
| class sc_method_process : public sc_process_b { | |
| friend struct sc_invoke_method; | |
| friend void sc_method_cor_fn( void* ); | |
| friend void sc_cmethod_cor_fn( void* ); | |
| friend void sc_set_stack_size( sc_method_handle, std::size_t ); | |
| friend class sc_event; | |
| friend class sc_module; | |
| friend class sc_process_table; | |
| friend class sc_process_handle; | |
| friend class sc_simcontext; | |
| friend class sc_runnable; | |
| friend void next_trigger( sc_simcontext* ); | |
| friend void next_trigger( const sc_event&, | |
| sc_simcontext* ); | |
| friend void next_trigger( const sc_event_or_list&, | |
| sc_simcontext* ); | |
| friend void next_trigger( const sc_event_and_list&, | |
| sc_simcontext* ); | |
| friend void next_trigger( const sc_time&, | |
| sc_simcontext* ); | |
| friend void next_trigger( const sc_time&, const sc_event&, | |
| sc_simcontext* ); | |
| friend void next_trigger( const sc_time&, const sc_event_or_list&, | |
| sc_simcontext* ); | |
| friend void next_trigger( const sc_time&, const sc_event_and_list&, | |
| sc_simcontext* ); | |
| public: | |
| sc_method_process( const char* name_p, bool free_host, | |
| SC_ENTRY_FUNC method_p, sc_process_host* host_p, | |
| const sc_spawn_options* opt_p ); | |
| virtual const char* kind() const | |
| { return "sc_method_process"; } | |
| protected: | |
| void check_for_throws(); | |
| virtual void disable_process( | |
| sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); | |
| virtual void enable_process( | |
| sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); | |
| inline bool run_process(); | |
| virtual void kill_process( | |
| sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); | |
| sc_method_handle next_exist(); | |
| sc_method_handle next_runnable(); | |
| void clear_trigger(); | |
| void next_trigger( const sc_event& ); | |
| void next_trigger( const sc_event_or_list& ); | |
| void next_trigger( const sc_event_and_list& ); | |
| void next_trigger( const sc_time& ); | |
| void next_trigger( const sc_time&, const sc_event& ); | |
| void next_trigger( const sc_time&, const sc_event_or_list& ); | |
| void next_trigger( const sc_time&, const sc_event_and_list& ); | |
| virtual void resume_process( | |
| sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); | |
| void set_next_exist( sc_method_handle next_p ); | |
| void set_next_runnable( sc_method_handle next_p ); | |
| void set_stack_size( std::size_t size ); | |
| virtual void suspend_process( | |
| sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); | |
| virtual void throw_reset( bool async ); | |
| virtual void throw_user( const sc_throw_it_helper& helper, | |
| sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); | |
| bool trigger_dynamic( sc_event* ); | |
| inline void trigger_static(); | |
| protected: | |
| sc_cor* m_cor; // Thread's coroutine. | |
| std::size_t m_stack_size; // Thread stack size. | |
| std::vector<sc_process_monitor*> m_monitor_q; // Thread monitors. | |
| private: | |
| // may not be deleted manually (called from sc_process_b) | |
| virtual ~sc_method_process(); | |
| private: // disabled | |
| sc_method_process( const sc_method_process& ); | |
| const sc_method_process& operator = ( const sc_method_process& ); | |
| }; | |
| inline | |
| void | |
| sc_method_process::next_trigger( const sc_event& e ) | |
| { | |
| clear_trigger(); | |
| e.add_dynamic( this ); | |
| m_event_p = &e; | |
| m_trigger_type = EVENT; | |
| } | |
| inline | |
| void | |
| sc_method_process::next_trigger( const sc_event_or_list& el ) | |
| { | |
| clear_trigger(); | |
| el.add_dynamic( this ); | |
| m_event_list_p = ⪙ | |
| m_trigger_type = OR_LIST; | |
| } | |
| inline | |
| void | |
| sc_method_process::next_trigger( const sc_event_and_list& el ) | |
| { | |
| clear_trigger(); | |
| el.add_dynamic( this ); | |
| m_event_list_p = ⪙ | |
| m_event_count = el.size(); | |
| m_trigger_type = AND_LIST; | |
| } | |
| inline | |
| void | |
| sc_method_process::next_trigger( const sc_time& t ) | |
| { | |
| clear_trigger(); | |
| m_timeout_event_p->notify_internal( t ); | |
| m_timeout_event_p->add_dynamic( this ); | |
| m_trigger_type = TIMEOUT; | |
| } | |
| inline | |
| void | |
| sc_method_process::next_trigger( const sc_time& t, const sc_event& e ) | |
| { | |
| clear_trigger(); | |
| m_timeout_event_p->notify_internal( t ); | |
| m_timeout_event_p->add_dynamic( this ); | |
| e.add_dynamic( this ); | |
| m_event_p = &e; | |
| m_trigger_type = EVENT_TIMEOUT; | |
| } | |
| inline | |
| void | |
| sc_method_process::next_trigger( const sc_time& t, const sc_event_or_list& el ) | |
| { | |
| clear_trigger(); | |
| m_timeout_event_p->notify_internal( t ); | |
| m_timeout_event_p->add_dynamic( this ); | |
| el.add_dynamic( this ); | |
| m_event_list_p = ⪙ | |
| m_trigger_type = OR_LIST_TIMEOUT; | |
| } | |
| inline | |
| void | |
| sc_method_process::next_trigger( const sc_time& t, const sc_event_and_list& el ) | |
| { | |
| clear_trigger(); | |
| m_timeout_event_p->notify_internal( t ); | |
| m_timeout_event_p->add_dynamic( this ); | |
| el.add_dynamic( this ); | |
| m_event_list_p = ⪙ | |
| m_event_count = el.size(); | |
| m_trigger_type = AND_LIST_TIMEOUT; | |
| } | |
| inline | |
| void sc_method_process::set_next_exist(sc_method_handle next_p) | |
| { | |
| m_exist_p = next_p; | |
| } | |
| inline | |
| sc_method_handle sc_method_process::next_exist() | |
| { | |
| return (sc_method_handle)m_exist_p; | |
| } | |
| inline | |
| void sc_method_process::set_next_runnable(sc_method_handle next_p) | |
| { | |
| m_runnable_p = next_p; | |
| } | |
| inline | |
| sc_method_handle sc_method_process::next_runnable() | |
| { | |
| return (sc_method_handle)m_runnable_p; | |
| } | |
| // +---------------------------------------------------------------------------- | |
| // |"sc_method_process::run_process" | |
| // | | |
| // | This method executes this object instance, including fielding exceptions. | |
| // | | |
| // | Result is false if an unfielded exception occurred, true if not. | |
| // +---------------------------------------------------------------------------- | |
| inline bool sc_method_process::run_process() | |
| { | |
| // Execute this object instance's semantics and catch any exceptions that | |
| // are generated: | |
| bool restart = false; | |
| do { | |
| try { | |
| DEBUG_MSG(DEBUG_NAME,this,"executing method semantics"); | |
| semantics(); | |
| restart = false; | |
| } | |
| catch( sc_unwind_exception& ex ) { | |
| DEBUG_MSG(DEBUG_NAME,this,"caught unwind exception"); | |
| ex.clear(); | |
| restart = ex.is_reset(); | |
| } | |
| catch( ... ) { | |
| sc_report* err_p = sc_handle_exception(); | |
| simcontext()->set_error( err_p ); | |
| return false; | |
| } | |
| } while( restart ); | |
| return true; | |
| } | |
| //------------------------------------------------------------------------------ | |
| //"sc_method_process::trigger_static" | |
| // | |
| // This inline method adds the current method to the queue of runnable | |
| // processes, if required. This is the case if the following criteria | |
| // are met: | |
| // (1) The process is in a runnable state. | |
| // (2) The process is not already on the run queue. | |
| // (3) The process is expecting a static trigger, | |
| // dynamic event waits take priority. | |
| // | |
| // | |
| // If the triggering process is the same process, the trigger is | |
| // ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS | |
| // is defined. | |
| //------------------------------------------------------------------------------ | |
| inline | |
| void | |
| sc_method_process::trigger_static() | |
| { | |
| if ( (m_state & ps_bit_disabled) || is_runnable() || | |
| m_trigger_type != STATIC ) | |
| return; | |
| #if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) | |
| if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) | |
| { | |
| report_immediate_self_notification(); | |
| return; | |
| } | |
| #endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS | |
| // If we get here then the method is has satisfied its wait, if its | |
| // suspended mark its state as ready to run. If its not suspended then | |
| // push it onto the runnable queue. | |
| if ( m_state & ps_bit_suspended ) | |
| { | |
| m_state = m_state | ps_bit_ready_to_run; | |
| } | |
| else | |
| { | |
| simcontext()->push_runnable_method(this); | |
| } | |
| } | |
| #undef DEBUG_MSG | |
| } // namespace sc_core | |
| // Revision 1.20 2011/08/24 22:05:50 acg | |
| // Torsten Maehne: initialization changes to remove warnings. | |
| // | |
| // Revision 1.19 2011/07/29 22:43:15 acg | |
| // Andy Goodrich: addition of check_for_throws() method. | |
| // | |
| // Revision 1.18 2011/07/24 11:18:09 acg | |
| // Philipp A. Hartmann: add code to restart a method process after a | |
| // self-reset. | |
| // | |
| // Revision 1.17 2011/05/09 04:07:48 acg | |
| // Philipp A. Hartmann: | |
| // (1) Restore hierarchy in all phase callbacks. | |
| // (2) Ensure calls to before_end_of_elaboration. | |
| // | |
| // Revision 1.16 2011/04/13 02:41:34 acg | |
| // Andy Goodrich: eliminate warning messages generated when the DEBUG_MSG | |
| // macro is used. | |
| // | |
| // Revision 1.15 2011/04/10 22:12:32 acg | |
| // Andy Goodrich: adding debugging macros. | |
| // | |
| // Revision 1.14 2011/04/08 22:31:21 acg | |
| // Andy Goodrich: added new inline method run_process() to hide the process | |
| // implementation for sc_simcontext. | |
| // | |
| // Revision 1.13 2011/04/05 20:50:56 acg | |
| // Andy Goodrich: | |
| // (1) changes to make sure that event(), posedge() and negedge() only | |
| // return true if the clock has not moved. | |
| // (2) fixes for method self-resumes. | |
| // (3) added SC_PRERELEASE_VERSION | |
| // (4) removed kernel events from the object hierarchy, added | |
| // sc_hierarchy_name_exists(). | |
| // | |
| // Revision 1.12 2011/04/01 21:24:57 acg | |
| // Andy Goodrich: removed unused code. | |
| // | |
| // Revision 1.11 2011/02/19 08:30:53 acg | |
| // Andy Goodrich: Moved process queueing into trigger_static from | |
| // sc_event::notify. | |
| // | |
| // Revision 1.10 2011/02/18 20:27:14 acg | |
| // Andy Goodrich: Updated Copyrights. | |
| // | |
| // Revision 1.9 2011/02/17 19:51:34 acg | |
| // Andy Goodrich: | |
| // (1) Changed the signature of trigger_dynamic back to a bool. | |
| // (2) Removed ready_to_run(). | |
| // (3) Simplified process control usage. | |
| // | |
| // Revision 1.8 2011/02/16 22:37:30 acg | |
| // Andy Goodrich: clean up to remove need for ps_disable_pending. | |
| // | |
| // Revision 1.7 2011/02/13 21:47:37 acg | |
| // Andy Goodrich: update copyright notice. | |
| // | |
| // Revision 1.6 2011/02/01 21:05:05 acg | |
| // Andy Goodrich: Changes in trigger_dynamic methods to handle new | |
| // process control rules about event sensitivity. | |
| // | |
| // Revision 1.5 2011/01/18 20:10:44 acg | |
| // Andy Goodrich: changes for IEEE1666_2011 semantics. | |
| // | |
| // Revision 1.4 2009/07/28 01:10:53 acg | |
| // Andy Goodrich: updates for 2.3 release candidate. | |
| // | |
| // Revision 1.3 2009/05/22 16:06:29 acg | |
| // Andy Goodrich: process control updates. | |
| // | |
| // Revision 1.2 2008/05/22 17:06:25 acg | |
| // Andy Goodrich: updated copyright notice to include 2008. | |
| // | |
| // Revision 1.1.1.1 2006/12/15 20:20:05 acg | |
| // SystemC 2.3 | |
| // | |
| // Revision 1.7 2006/05/08 17:57:13 acg | |
| // Andy Goodrich: Added David Long's forward declarations for friend functions | |
| // to keep the Microsoft C++ compiler happy. | |
| // | |
| // Revision 1.6 2006/04/20 17:08:17 acg | |
| // Andy Goodrich: 3.0 style process changes. | |
| // | |
| // Revision 1.5 2006/04/11 23:13:21 acg | |
| // Andy Goodrich: Changes for reduced reset support that only includes | |
| // sc_cthread, but has preliminary hooks for expanding to method and thread | |
| // processes also. | |
| // | |
| // Revision 1.4 2006/01/24 20:49:05 acg | |
| // Andy Goodrich: changes to remove the use of deprecated features within the | |
| // simulator, and to issue warning messages when deprecated features are used. | |
| // | |
| // Revision 1.3 2006/01/13 18:44:29 acg | |
| // Added $Log to record CVS changes into the source. | |
| #endif // !defined(sc_method_process_h_INCLUDED) |