diff options
Diffstat (limited to 'ext/systemc/src/sysc/communication/sc_port.h')
-rw-r--r-- | ext/systemc/src/sysc/communication/sc_port.h | 732 |
1 files changed, 732 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/communication/sc_port.h b/ext/systemc/src/sysc/communication/sc_port.h new file mode 100644 index 000000000..a126657e6 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_port.h @@ -0,0 +1,732 @@ +/***************************************************************************** + + 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_port.h -- Base classes of all port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_PORT_H +#define SC_PORT_H + + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_interface.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_process.h" +#include <typeinfo> + +#if ! defined( SC_DISABLE_VIRTUAL_BIND ) +# define SC_VIRTUAL_ virtual +#else +# define SC_VIRTUAL_ /* non-virtual */ +#endif + +namespace sc_core { + +class sc_event_finder; + +struct sc_bind_info; + +enum sc_port_policy +{ + SC_ONE_OR_MORE_BOUND, // Default + SC_ZERO_OR_MORE_BOUND, + SC_ALL_BOUND +}; + + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// BEWARE: Ports can only be created and bound during elaboration. +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_base +// +// Abstract base class for class sc_port_b. +// ---------------------------------------------------------------------------- + +class sc_port_base +: public sc_object +{ + friend class sc_module; + friend class sc_port_registry; + friend class sc_sensitive; + friend class sc_sensitive_pos; + friend class sc_sensitive_neg; + +public: + + // typedefs + + typedef sc_port_base this_type; + +public: + + int bind_count(); + + // get the first interface without checking for nil + virtual sc_interface* get_interface() = 0; + virtual const sc_interface* get_interface() const = 0; + + virtual const char* kind() const + { return "sc_port_base"; } + +protected: + + // constructors + explicit sc_port_base( int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ); + sc_port_base( const char* name_, int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ); + + // destructor + virtual ~sc_port_base(); + + // bind interface to this port + void bind( sc_interface& interface_ ); + + // bind parent port to this port + void bind( this_type& parent_ ); + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ) = 0; + virtual int vbind( sc_port_base& ) = 0; + + // called by complete_binding (for internal use only) + virtual void add_interface( sc_interface* ) = 0; + virtual int interface_count() = 0; + virtual const char* if_typename() const = 0; + + // called by construction_done (does nothing by default) + virtual void before_end_of_elaboration(); + + // called by elaboration_done (does nothing) + virtual void end_of_elaboration(); + + // called by start_simulation (does nothing by default) + virtual void start_of_simulation(); + + // called by simulation_done (does nothing by default) + virtual void end_of_simulation(); + + // error reporting + void report_error( const char* id, const char* add_msg = 0) const; + +protected: + // called by the sc_sensitive* classes + virtual void make_sensitive( sc_thread_handle, sc_event_finder* = 0 ) const; + virtual void make_sensitive( sc_method_handle, sc_event_finder* = 0 ) const; + void add_static_event( + sc_method_handle process_p, const sc_event& event) const; + void add_static_event( + sc_thread_handle process_p, const sc_event& event) const; + +private: + + // called by class sc_module for positional binding + int pbind( sc_interface& ); + int pbind( sc_port_base& ); + + + // support methods + int first_parent(); + void insert_parent( int ); + + // called when construction is done + void construction_done(); + + // called when elaboration is done + void complete_binding(); + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + +protected: + + sc_bind_info* m_bind_info; + +private: + + // disabled + sc_port_base(); + sc_port_base( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_registry +// +// Registry for all ports. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_port_registry +{ + friend class sc_simcontext; + +public: + + void insert( sc_port_base* ); + void remove( sc_port_base* ); + + int size() const + { return m_port_vec.size(); } + +private: + + // constructor + explicit sc_port_registry( sc_simcontext& simc_ ); + + // destructor + ~sc_port_registry(); + + // called when by construction_done and elaboration done + void complete_binding(); + + // called when construction is done + bool construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + + static void replace_port( sc_port_registry* ); + +private: + + int m_construction_done; + std::vector<sc_port_base*> m_port_vec; + sc_simcontext* m_simc; + +private: + + // disabled + sc_port_registry(); + sc_port_registry( const sc_port_registry& ); + sc_port_registry& operator = ( const sc_port_registry& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_b +// +// Abstract base class for class sc_port. +// ---------------------------------------------------------------------------- + +template <class IF> +class sc_port_b +: public sc_port_base +{ +public: + + friend class sc_sensitive; + friend class sc_sensitive_neg; + friend class sc_sensitive_pos; + + // typedefs + + typedef sc_port_base base_type; + typedef sc_port_b<IF> this_type; + typedef this_type port_type; + +public: + + // bind an interface of type IF to this port + + SC_VIRTUAL_ void bind( IF& interface_ ) + { base_type::bind( interface_ ); } + + void operator () ( IF& interface_ ) + { this->bind( interface_ ); } + + + // bind a parent port with type IF to this port + + SC_VIRTUAL_ void bind( port_type& parent_ ) + { base_type::bind( parent_ ); } + + void operator () ( port_type& parent_ ) + { this->bind( parent_ ); } + + + // number of connected interfaces + + int size() const + { return m_interface_vec.size(); } + + + // allow to call methods provided by the first interface + IF* operator -> (); + const IF* operator -> () const; + + + // allow to call methods provided by interface at index + inline const IF* get_interface( int iface_i ) const; + inline IF* get_interface( int iface_i ); + IF* operator [] ( int index_ ) + { return get_interface( index_ ); } + const IF* operator [] ( int index_ ) const + { return get_interface( index_ ); } + + + // get the first interface without checking for nil + + virtual sc_interface* get_interface() + { return m_interface; } + + virtual const sc_interface* get_interface() const + { return m_interface; } + +protected: + + // constructors + + explicit sc_port_b( int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ) : + base_type( max_size_, policy ), m_interface( 0 ), m_interface_vec() + {} + + sc_port_b( const char* name_, int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ) : + base_type( name_, max_size_, policy ), m_interface( 0 ), + m_interface_vec() + {} + + + // destructor (does nothing) + + virtual ~sc_port_b() + {} + + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ); + virtual int vbind( sc_port_base& ); + +protected: + + // called by the sc_sensitive* classes + virtual void make_sensitive( sc_thread_handle, sc_event_finder* = 0 ) const; + virtual void make_sensitive( sc_method_handle, sc_event_finder* = 0 ) const; + +private: + + // called by complete_binding (for internal use only) + virtual void add_interface( sc_interface* ); + virtual const char* if_typename() const; + virtual int interface_count(); + + // disabled + sc_port_b(); + sc_port_b( const this_type& ); + this_type& operator = ( const this_type& ); + +private: + + IF* m_interface; // first interface in interface vec + std::vector<IF*> m_interface_vec; +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port +// +// Generic port class and base class for other port classes. +// N is the maximum number of channels (with interface IF) that can be bound +// to this port. N <= 0 means no maximum. +// ---------------------------------------------------------------------------- + +extern void sc_warn_port_constructor(); + +template <class IF, int N = 1, sc_port_policy P=SC_ONE_OR_MORE_BOUND> +class sc_port +: public sc_port_b<IF> +{ + // typdefs + + typedef sc_port_b<IF> base_type; + typedef sc_port<IF,N,P> this_type; + +public: + + // constructors + + sc_port() + : base_type( N, P ) + {} + + explicit sc_port( const char* name_ ) + : base_type( name_, N, P ) + {} + + explicit sc_port( IF& interface_ ) + : base_type( N, P ) + { sc_warn_port_constructor(); base_type::bind( interface_ ); } + + sc_port( const char* name_, IF& interface_ ) + : base_type( name_, N, P ) + { sc_warn_port_constructor(); base_type::bind( interface_ ); } + + explicit sc_port( base_type& parent_ ) + : base_type( N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + sc_port( const char* name_, base_type& parent_ ) + : base_type( name_, N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + sc_port( this_type& parent_ ) + : base_type( N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + sc_port( const char* name_, this_type& parent_ ) + : base_type( name_, N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + + // destructor (does nothing) + + virtual ~sc_port() + {} + + virtual const char* kind() const + { return "sc_port"; } + +private: + + // disabled + sc_port( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_b +// +// Abstract base class for class sc_port. +// ---------------------------------------------------------------------------- + +// allow to call methods provided by the first interface + +template <class IF> +inline +IF* +sc_port_b<IF>::operator -> () +{ + if( m_interface == 0 ) { + report_error( SC_ID_GET_IF_, "port is not bound" ); + } + return m_interface; +} + +template <class IF> +inline +const IF* +sc_port_b<IF>::operator -> () const +{ + if( m_interface == 0 ) { + report_error( SC_ID_GET_IF_, "port is not bound" ); + } + return m_interface; +} + + +// allow to call methods provided by interface at index +// +// note that we special-case index of zero, since the method may be +// called before binding has occurred, and we need to return a zero +// in that case not an error. + +template <class IF> +inline +IF* +sc_port_b<IF>::get_interface( int index_ ) +{ + if ( index_ == 0 ) { + return m_interface; + } + else if( index_ < 0 || index_ >= size() ) { + report_error( SC_ID_GET_IF_, "index out of range" ); + } + return m_interface_vec[index_]; +} + +template <class IF> +inline +const IF* +sc_port_b<IF>::get_interface( int index_ ) const +{ + if ( index_ == 0 ) { + return m_interface; + } + else if( index_ < 0 || index_ >= size() ) { + report_error( SC_ID_GET_IF_, "index out of range" ); + } + return m_interface_vec[index_]; +} + + +// called by pbind (for internal use only) + +template <class IF> +inline +int +sc_port_b<IF>::vbind( sc_interface& interface_ ) +{ + IF* iface = DCAST<IF*>( &interface_ ); + if( iface == 0 ) { + // type mismatch + return 2; + } + base_type::bind( *iface ); + return 0; +} + +template <class IF> +inline +int +sc_port_b<IF>::vbind( sc_port_base& parent_ ) +{ + this_type* parent = DCAST<this_type*>( &parent_ ); + if( parent == 0 ) { + // type mismatch + return 2; + } + base_type::bind( *parent ); + return 0; +} + + +// called by complete_binding (for internal use only) + +template <class IF> +inline +void +sc_port_b<IF>::add_interface( sc_interface* interface_ ) +{ + IF* iface = DCAST<IF*>( interface_ ); + assert( iface != 0 ); + + // make sure that the interface is not already bound: + + int size = m_interface_vec.size(); + for ( int i = 0; i < size; i++ ) + { + if ( iface == m_interface_vec[i] ) + { + report_error( SC_ID_BIND_IF_TO_PORT_, + "interface already bound to port" ); + } + } + + // "bind" the interface and make sure our short cut for 0 is set up. + + m_interface_vec.push_back( iface ); + m_interface = m_interface_vec[0]; +} + +template <class IF> +inline +const char* +sc_port_b<IF>::if_typename() const +{ + return typeid( IF ).name(); +} + +template <class IF> +inline +int +sc_port_b<IF>::interface_count() +{ + return m_interface_vec.size(); +} + +template <class IF> +void +sc_port_b<IF>::make_sensitive( sc_thread_handle handle_p, + sc_event_finder* event_finder_ ) const +{ + if ( m_bind_info == 0 ) + { + int if_n = m_interface_vec.size(); + for ( int if_i = 0; if_i < if_n; if_i++ ) + { + IF* iface_p = m_interface_vec[if_i]; + assert( iface_p != 0 ); + add_static_event( handle_p, iface_p->default_event() ); + } + } + else + { + sc_port_base::make_sensitive( handle_p, event_finder_ ); + } +} + +template <class IF> +void +sc_port_b<IF>::make_sensitive( sc_method_handle handle_p, + sc_event_finder* event_finder_ ) const +{ + if ( m_bind_info == 0 ) + { + int if_n = m_interface_vec.size(); + for ( int if_i = 0; if_i < if_n; if_i++ ) + { + IF* iface_p = m_interface_vec[if_i]; + assert( iface_p != 0 ); + add_static_event( handle_p, iface_p->default_event() ); + } + } + else + { + sc_port_base::make_sensitive( handle_p, event_finder_ ); + } +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_port +// +// Generic port class and base class for other port classes. +// N is the maximum number of channels (with interface IF) that can be bound +// to this port. N <= 0 means no maximum. +// ---------------------------------------------------------------------------- + +} // namespace sc_core + +#undef SC_VIRTUAL_ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: phase callbacks + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + 12 December, 2005 + Description of Modification: multiport binding policy changes + + + *****************************************************************************/ + +/* +$Log: sc_port.h,v $ +Revision 1.10 2011/08/26 20:45:41 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.9 2011/08/24 22:05:36 acg + Torsten Maehne: initialization changes to remove warnings. + +Revision 1.8 2011/08/07 19:08:01 acg + Andy Goodrich: moved logs to end of file so line number synching works + better between versions. + +Revision 1.7 2011/08/07 18:53:09 acg + Philipp A. Hartmann: add virtual instances of the bind function for + base classes to eliminate warning messages for clang platforms. + +Revision 1.6 2011/05/09 04:07:37 acg + Philipp A. Hartmann: + (1) Restore hierarchy in all phase callbacks. + (2) Ensure calls to before_end_of_elaboration. + +Revision 1.5 2011/03/30 16:46:10 acg + Andy Goodrich: added a signature and removed a virtual specification + to eliminate warnings with certain compilers. + +Revision 1.4 2011/02/18 20:23:45 acg + Andy Goodrich: Copyright update. + +Revision 1.3 2011/01/20 16:52:15 acg + Andy Goodrich: changes for IEEE 1666 2011. + +Revision 1.2 2010/08/03 18:01:11 acg + Andy Goodrich: formatting. + +Revision 1.1.1.1 2006/12/15 20:20:04 acg +SystemC 2.3 + +Revision 1.5 2006/08/29 23:35:00 acg + Andy Goodrich: added bind_count() method to allow users to determine which + ports are connected in before_end_of_elaboration(). + +Revision 1.4 2006/05/08 17:52:47 acg + Andy Goodrich: + (1) added David Long's forward declarations for friend functions, + methods, and operators to keep the Microsoft compiler happy. + (2) Added delta_count() method to sc_prim_channel for use by + sc_signal so that the friend declaration in sc_simcontext.h + can be for a non-templated class (i.e., sc_prim_channel.) + +Revision 1.3 2006/01/24 20:46:31 acg +Andy Goodrich: changes to eliminate use of deprecated features. For instance, +using notify(SC_ZERO_TIME) in place of notify_delayed(). + +Revision 1.2 2006/01/03 23:18:26 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:43 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/09/15 23:01:51 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.9 2005/08/10 01:35:59 acg +Changes for 64-bit support. + +Revision 1.8 2005/04/03 22:52:51 acg +Namespace changes. + +Revision 1.7 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.6 2004/09/27 21:02:54 acg +Andy Goodrich - Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments will appear in + checked out source. + +*/ + +#endif + +// Taf! |