| /***************************************************************************** |
| |
| 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! |