diff options
Diffstat (limited to 'ext/systemc/src/sysc/kernel/sc_event.h')
-rw-r--r-- | ext/systemc/src/sysc/kernel/sc_event.h | 884 |
1 files changed, 884 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/kernel/sc_event.h b/ext/systemc/src/sysc/kernel/sc_event.h new file mode 100644 index 000000000..9633752ce --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_event.h @@ -0,0 +1,884 @@ +/***************************************************************************** + + 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_event.h -- + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_EVENT_H +#define SC_EVENT_H + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/communication/sc_writer_policy.h" + +namespace sc_core { + +// forward declarations +class sc_event; +class sc_event_timed; +class sc_event_list; +class sc_event_or_list; +class sc_event_and_list; +class sc_object; + +// friend function declarations + int sc_notify_time_compare( const void*, const void* ); + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_expr +// +// The event expression class. +// ---------------------------------------------------------------------------- + +template< typename T > +class sc_event_expr +{ + friend class sc_event; + friend class sc_event_and_list; + friend class sc_event_or_list; + + typedef T type; + + inline sc_event_expr() + : m_expr( new T(true) ) + {} + +public: + + inline sc_event_expr( sc_event_expr const & e) // move semantics + : m_expr(e.m_expr) + { + e.m_expr = 0; + } + + T const & release() const + { + sc_assert( m_expr ); + T* expr = m_expr; + m_expr=0; + return *expr; + } + + void push_back( sc_event const & e) const + { + sc_assert( m_expr ); + m_expr->push_back(e); + } + + void push_back( type const & el) const + { + sc_assert( m_expr ); + m_expr->push_back(el); + } + operator T const &() const + { + return release(); + } + + ~sc_event_expr() + { + delete m_expr; + } + +private: + mutable type * m_expr; + + // disabled + void operator=( sc_event_expr const & ); +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_list +// +// Base class for lists of events. +// ---------------------------------------------------------------------------- + +class sc_event_list +{ + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + friend void sc_thread_cor_fn( void* arg ); + +public: + sc_event_list( const sc_event_list& ); + sc_event_list& operator = ( const sc_event_list& ); + + int size() const; + +protected: + + void push_back( const sc_event& ); + void push_back( const sc_event_list& ); + + explicit + sc_event_list( bool and_list_, bool auto_delete_ = false ); + + sc_event_list( const sc_event&, + bool and_list_, + bool auto_delete_ = false ); + + ~sc_event_list(); + + void swap( sc_event_list& ); + void move_from( const sc_event_list& ); + + bool and_list() const; + + void add_dynamic( sc_method_handle ) const; + void add_dynamic( sc_thread_handle ) const; + void remove_dynamic( sc_method_handle, const sc_event* ) const; + void remove_dynamic( sc_thread_handle, const sc_event* ) const; + + bool busy() const; + bool temporary() const; + void auto_delete() const; + + void report_premature_destruction() const; + void report_invalid_modification() const; + +private: + + std::vector<const sc_event*> m_events; + bool m_and_list; + bool m_auto_delete; + mutable unsigned m_busy; +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_and_list +// +// AND list of events. +// ---------------------------------------------------------------------------- + +class sc_event_and_list +: public sc_event_list +{ + friend class sc_event; + friend class sc_event_expr<sc_event_and_list>; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + +protected: + + explicit + sc_event_and_list( bool auto_delete_ ); + +public: + + sc_event_and_list(); + sc_event_and_list( const sc_event& ); + + void swap( sc_event_and_list& ); + sc_event_and_list& operator &= ( const sc_event& ); + sc_event_and_list& operator &= ( const sc_event_and_list & ); + + sc_event_expr<sc_event_and_list> operator & ( const sc_event& ); + sc_event_expr<sc_event_and_list> operator & ( const sc_event_and_list& ); +}; + +typedef sc_event_expr<sc_event_and_list> sc_event_and_expr; + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_or_list +// +// OR list of events. +// ---------------------------------------------------------------------------- + +class sc_event_or_list +: public sc_event_list +{ + friend class sc_event; + friend class sc_event_expr<sc_event_or_list>; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + +protected: + + explicit + sc_event_or_list( bool auto_delete_ ); + +public: + sc_event_or_list(); + sc_event_or_list( const sc_event& ); + void swap( sc_event_or_list& ); + sc_event_or_list& operator |= ( const sc_event& ); + sc_event_or_list& operator |= ( const sc_event_or_list & ); + sc_event_expr<sc_event_or_list> operator | ( const sc_event& ) const; + sc_event_expr<sc_event_or_list> operator | ( const sc_event_or_list& ) const; +}; + +typedef sc_event_expr<sc_event_or_list> sc_event_or_expr; + +// ---------------------------------------------------------------------------- +// CLASS : sc_event +// +// The event class. +// ---------------------------------------------------------------------------- + +class sc_event +{ + friend class sc_clock; + friend class sc_event_list; + friend class sc_event_timed; + friend class sc_simcontext; + friend class sc_object; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + template<typename IF, sc_writer_policy POL> friend class sc_signal; + friend void sc_thread_cor_fn( void* arg ); + +public: + + sc_event(); + sc_event( const char* name ); + ~sc_event(); + + void cancel(); + + const char* name() const { return m_name.c_str(); } + const char* basename() const; + sc_object* get_parent_object() const { return m_parent_p; } + bool in_hierarchy() const { return m_name.length() != 0; } + + void notify(); + void notify( const sc_time& ); + void notify( double, sc_time_unit ); + + void notify_delayed(); + void notify_delayed( const sc_time& ); + void notify_delayed( double, sc_time_unit ); + + sc_event_or_expr operator | ( const sc_event& ) const; + sc_event_or_expr operator | ( const sc_event_or_list& ) const; + sc_event_and_expr operator & ( const sc_event& ) const; + sc_event_and_expr operator & ( const sc_event_and_list& ) const; + + +private: + + void add_static( sc_method_handle ) const; + void add_static( sc_thread_handle ) const; + void add_dynamic( sc_method_handle ) const; + void add_dynamic( sc_thread_handle ) const; + + void notify_internal( const sc_time& ); + void notify_next_delta(); + + bool remove_static( sc_method_handle ) const; + bool remove_static( sc_thread_handle ) const; + bool remove_dynamic( sc_method_handle ) const; + bool remove_dynamic( sc_thread_handle ) const; + + void register_event( const char* name ); + void reset(); + + void trigger(); + +private: + + enum notify_t { NONE, DELTA, TIMED }; + + std::string m_name; // name of object. + sc_object* m_parent_p; // parent sc_object for this event. + sc_simcontext* m_simc; + notify_t m_notify_type; + int m_delta_event_index; + sc_event_timed* m_timed; + + mutable std::vector<sc_method_handle> m_methods_static; + mutable std::vector<sc_method_handle> m_methods_dynamic; + mutable std::vector<sc_thread_handle> m_threads_static; + mutable std::vector<sc_thread_handle> m_threads_dynamic; + +private: + + // disabled + sc_event( const sc_event& ); + sc_event& operator = ( const sc_event& ); +}; + +#define SC_KERNEL_EVENT_PREFIX "$$$$kernel_event$$$$_" + +extern sc_event sc_non_event; // Event that never happens. + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_timed +// +// Class for storing the time to notify a timed event. +// ---------------------------------------------------------------------------- + +class sc_event_timed +{ + friend class sc_event; + friend class sc_simcontext; + + friend int sc_notify_time_compare( const void*, const void* ); + +private: + + sc_event_timed( sc_event* e, const sc_time& t ) + : m_event( e ), m_notify_time( t ) + {} + + ~sc_event_timed() + { if( m_event != 0 ) { m_event->m_timed = 0; } } + + sc_event* event() const + { return m_event; } + + const sc_time& notify_time() const + { return m_notify_time; } + + static void* operator new( std::size_t ) + { return allocate(); } + + static void operator delete( void* p, std::size_t ) + { deallocate( p ); } + +private: + + // dedicated memory management + static void* allocate(); + static void deallocate( void* ); + +private: + + sc_event* m_event; + sc_time m_notify_time; + +private: + + // disabled + sc_event_timed(); + sc_event_timed( const sc_event_timed& ); + sc_event_timed& operator = ( const sc_event_timed& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +void +sc_event::notify( double v, sc_time_unit tu ) +{ + notify( sc_time( v, tu, m_simc ) ); +} + + +inline +void +sc_event::notify_internal( const sc_time& t ) +{ + if( t == SC_ZERO_TIME ) { + // add this event to the delta events set + m_delta_event_index = m_simc->add_delta_event( this ); + m_notify_type = DELTA; + } else { + sc_event_timed* et = + new sc_event_timed( this, m_simc->time_stamp() + t ); + m_simc->add_timed_event( et ); + m_timed = et; + m_notify_type = TIMED; + } +} + +inline +void +sc_event::notify_next_delta() +{ + if( m_notify_type != NONE ) { + SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 ); + } + // add this event to the delta events set + m_delta_event_index = m_simc->add_delta_event( this ); + m_notify_type = DELTA; +} + +inline +void +sc_event::notify_delayed( double v, sc_time_unit tu ) +{ + notify_delayed( sc_time( v, tu, m_simc ) ); +} + + +inline +void +sc_event::add_static( sc_method_handle method_h ) const +{ + m_methods_static.push_back( method_h ); +} + +inline +void +sc_event::add_static( sc_thread_handle thread_h ) const +{ + m_threads_static.push_back( thread_h ); +} + +inline +void +sc_event::add_dynamic( sc_method_handle method_h ) const +{ + m_methods_dynamic.push_back( method_h ); +} + +inline +void +sc_event::add_dynamic( sc_thread_handle thread_h ) const +{ + m_threads_dynamic.push_back( thread_h ); +} + + +// ---------------------------------------------------------------------------- +// Deprecated functional notation for notifying events. +// ---------------------------------------------------------------------------- + +extern void notify( sc_event& e ); +extern void notify( const sc_time& t, sc_event& e ); +extern void notify( double v, sc_time_unit tu, sc_event& e ); + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_event_list::sc_event_list( bool and_list_, bool auto_delete_ ) + : m_events() + , m_and_list( and_list_ ) + , m_auto_delete( auto_delete_ ) + , m_busy( 0 ) +{ +} + +inline +sc_event_list::sc_event_list( const sc_event& e, + bool and_list_, + bool auto_delete_ ) + : m_events() + , m_and_list( and_list_ ) + , m_auto_delete( auto_delete_ ) + , m_busy(0) +{ + m_events.push_back( &e ); +} + +inline +sc_event_list::sc_event_list( sc_event_list const & that ) + : m_events() + , m_and_list( that.m_and_list ) + , m_auto_delete( false ) + , m_busy( 0 ) +{ + move_from( that ); + that.auto_delete(); // free automatic lists +} + +inline +sc_event_list& +sc_event_list::operator=( sc_event_list const & that ) +{ + if( m_busy ) + report_invalid_modification(); + + move_from( that ); + that.auto_delete(); // free automatic lists + + return *this; +} + +inline +sc_event_list::~sc_event_list() +{ + if( m_busy ) + report_premature_destruction(); +} + +inline +void +sc_event_list::swap( sc_event_list& that ) +{ + if( busy() || that.busy() ) + report_invalid_modification(); + m_events.swap( that.m_events ); +} + +inline +void +sc_event_list::move_from( sc_event_list const& that ) +{ + if( that.temporary() ) { + swap( const_cast<sc_event_list&>(that) ); // move from source + } else { + m_events = that.m_events; // copy from source + } +} + +inline +int +sc_event_list::size() const +{ + return m_events.size(); +} + +inline +bool +sc_event_list::and_list() const +{ + return m_and_list; +} + + +inline +bool +sc_event_list::busy() const +{ + return m_busy != 0; +} + + +inline +bool +sc_event_list::temporary() const +{ + return m_auto_delete && ! m_busy; +} + +inline +void +sc_event_list::auto_delete() const +{ + if( m_busy ) { + --m_busy; + } + if( ! m_busy && m_auto_delete ) { + delete this; + } +} + + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_event_or_list::sc_event_or_list() + : sc_event_list( false ) +{} + +inline +sc_event_or_list::sc_event_or_list( const sc_event& e ) +: sc_event_list( false ) +{ + push_back( e ); +} + +inline +sc_event_or_list::sc_event_or_list( bool auto_delete_ ) +: sc_event_list( false, auto_delete_ ) +{} + +inline +sc_event_or_list& +sc_event_or_list::operator |= ( const sc_event& e ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( e ); + return *this; +} + +inline +sc_event_or_list& +sc_event_or_list::operator |= ( const sc_event_or_list& el ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( el ); + return *this; +} + +inline +sc_event_or_expr +sc_event_or_list::operator | ( const sc_event& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +inline +sc_event_or_expr +sc_event_or_list::operator | ( const sc_event_or_list& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + + +// sc_event + +inline +sc_event_or_expr +sc_event::operator | ( const sc_event& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +inline +sc_event_or_expr +sc_event::operator | ( const sc_event_or_list& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +// sc_event_expr + +inline +sc_event_or_expr +operator | ( sc_event_or_expr expr, sc_event const & e ) +{ + expr.push_back( e ); + return expr; +} + +inline +sc_event_or_expr +operator | ( sc_event_or_expr expr, sc_event_or_list const & el ) +{ + expr.push_back( el ); + return expr; +} + +inline +void +sc_event_or_list::swap( sc_event_or_list & that ) +{ + sc_event_list::swap( that ); +} + + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_event_and_list::sc_event_and_list() + : sc_event_list( true ) +{} + +inline +sc_event_and_list::sc_event_and_list( const sc_event& e ) +: sc_event_list( true ) +{ + push_back( e ); +} + +inline +sc_event_and_list::sc_event_and_list( bool auto_delete_ ) +: sc_event_list( true, auto_delete_ ) +{} + +inline +void +sc_event_and_list::swap( sc_event_and_list & that ) +{ + sc_event_list::swap( that ); +} + + +inline +sc_event_and_list& +sc_event_and_list::operator &= ( const sc_event& e ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( e ); + return *this; +} + +inline +sc_event_and_list& +sc_event_and_list::operator &= ( const sc_event_and_list& el ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( el ); + return *this; +} + +inline +sc_event_and_expr +sc_event_and_list::operator & ( const sc_event& e ) +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( e ); + return expr; +} + +inline +sc_event_and_expr +sc_event_and_list::operator & ( const sc_event_and_list& el ) +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( el ); + return expr; +} + +// sc_event + +inline +sc_event_and_expr +sc_event::operator & ( const sc_event& e2 ) const +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +inline +sc_event_and_expr +sc_event::operator & ( const sc_event_and_list& e2 ) const +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +// sc_event_expr + +inline +sc_event_and_expr +operator & ( sc_event_and_expr expr, sc_event const & e ) +{ + expr.push_back( e ); + return expr; +} + +inline +sc_event_and_expr +operator & ( sc_event_and_expr expr, sc_event_and_list const & el ) +{ + expr.push_back( el ); + return expr; +} + +} // namespace sc_core + +// $Log: sc_event.h,v $ +// Revision 1.14 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.13 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.12 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.11 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.10 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.9 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/02/01 21:03:23 acg +// Andy Goodrich: new return codes for trigger_dynamic calls. +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2010/12/07 20:09:11 acg +// Andy Goodrich: writer policy fix. +// +// 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.8 2006/05/26 20:33:16 acg +// Andy Goodrich: changes required by additional platform compilers (i.e., +// Microsoft VC++, Sun Forte, HP aCC). +// +// Revision 1.7 2006/05/08 17:57:51 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.6 2006/04/11 23:13:20 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.5 2006/01/24 20:56:00 acg +// Andy Goodrich: fixed up CVS comment. +// +// Revision 1.4 2006/01/24 20:48:14 acg +// Andy Goodrich: added deprecation warnings for notify_delayed(). Added two +// new implementation-dependent methods, notify_next_delta() & notify_internal() +// to replace calls to notify_delayed() from within the simulator. These two +// new methods are simpler than notify_delayed() and should speed up simulations +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! |