| /***************************************************************************** |
| |
| 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_object.cpp -- Abstract base class of all SystemC objects. |
| |
| Original Author: Stan Y. Liao, Synopsys, Inc. |
| |
| CHANGE LOG AT THE END OF THE FILE |
| *****************************************************************************/ |
| |
| |
| #include <cstdlib> |
| #include <cassert> |
| #include <stddef.h> |
| #include <cstdio> |
| #include <string.h> |
| #include <ctype.h> |
| |
| #include "sysc/kernel/sc_externs.h" |
| #include "sysc/kernel/sc_kernel_ids.h" |
| #include "sysc/kernel/sc_module.h" |
| #include "sysc/kernel/sc_object.h" |
| #include "sysc/kernel/sc_object_manager.h" |
| #include "sysc/kernel/sc_phase_callback_registry.h" |
| #include "sysc/kernel/sc_process_handle.h" |
| #include "sysc/kernel/sc_simcontext.h" |
| #include "sysc/kernel/sc_event.h" |
| #include "sysc/utils/sc_hash.h" |
| #include "sysc/utils/sc_iostream.h" |
| #include "sysc/utils/sc_list.h" |
| #include "sysc/utils/sc_utils_ids.h" |
| #include "sysc/utils/sc_mempool.h" |
| |
| namespace sc_core { |
| |
| typedef int (*STRCMP)(const void*, const void*); |
| |
| const char SC_HIERARCHY_CHAR = '.'; |
| |
| /* This will be gotten rid after multiple-processes |
| are implemented. This is to fix some regression |
| problems. */ |
| bool sc_enable_name_checking = true; |
| |
| |
| // ---------------------------------------------------------------------------- |
| // CLASS : sc_object |
| // |
| // Abstract base class of all SystemC `simulation' objects. |
| // ---------------------------------------------------------------------------- |
| |
| void |
| sc_object::add_child_event( sc_event* event_p ) |
| { |
| // no check if event_p is already in the set |
| m_child_events.push_back( event_p ); |
| } |
| |
| void |
| sc_object::add_child_object( sc_object* object_ ) |
| { |
| // no check if object_ is already in the set |
| m_child_objects.push_back( object_ ); |
| } |
| |
| const char* |
| sc_object::basename() const |
| { |
| size_t pos; // position of last SC_HIERARCHY_CHAR. |
| pos = m_name.rfind( (char)SC_HIERARCHY_CHAR ); |
| return ( pos == m_name.npos ) ? m_name.c_str() : &(m_name.c_str()[pos+1]); |
| } |
| |
| void |
| sc_object::print(::std::ostream& os) const |
| { |
| os << name(); |
| } |
| |
| void |
| sc_object::dump(::std::ostream& os) const |
| { |
| os << "name = " << name() << "\n"; |
| os << "kind = " << kind() << "\n"; |
| } |
| |
| static int sc_object_num = 0; |
| |
| static std::string |
| sc_object_newname() |
| { |
| char buffer[64]; |
| std::string result; |
| |
| std::sprintf(buffer, "{%d}", sc_object_num); |
| sc_object_num++; |
| result = buffer; |
| |
| return result; |
| } |
| |
| // +---------------------------------------------------------------------------- |
| // |"sc_object::remove_child_event" |
| // | |
| // | This virtual method removes the supplied event from the list of child |
| // | events if it is present. |
| // | |
| // | Arguments: |
| // | event_p -> event to be removed. |
| // | Returns true if the event was present, false if not. |
| // +---------------------------------------------------------------------------- |
| bool |
| sc_object::remove_child_event( sc_event* event_p ) |
| { |
| int size = m_child_events.size(); |
| for( int i = 0; i < size; ++ i ) { |
| if( event_p == m_child_events[i] ) { |
| m_child_events[i] = m_child_events[size - 1]; |
| m_child_events.pop_back(); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| // +---------------------------------------------------------------------------- |
| // |"sc_object::remove_child_object" |
| // | |
| // | This virtual method removes the supplied object from the list of child |
| // | objects if it is present. |
| // | |
| // | Arguments: |
| // | object_p -> object to be removed. |
| // | Returns true if the object was present, false if not. |
| // +---------------------------------------------------------------------------- |
| bool |
| sc_object::remove_child_object( sc_object* object_p ) |
| { |
| int size = m_child_objects.size(); |
| for( int i = 0; i < size; ++ i ) { |
| if( object_p == m_child_objects[i] ) { |
| m_child_objects[i] = m_child_objects[size - 1]; |
| m_child_objects.pop_back(); |
| object_p->m_parent = NULL; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| // +---------------------------------------------------------------------------- |
| // |"sc_object::sc_object_init" |
| // | |
| // | This method initializes this object instance and places it in to the |
| // | object hierarchy if the supplied name is not NULL. |
| // | |
| // | Arguments: |
| // | nm = leaf name for the object. |
| // +---------------------------------------------------------------------------- |
| void |
| sc_object::sc_object_init(const char* nm) |
| { |
| // SET UP POINTERS TO OBJECT MANAGER, PARENT, AND SIMULATION CONTEXT: |
| // |
| // Make the current simcontext the simcontext for this object |
| |
| m_simc = sc_get_curr_simcontext(); |
| m_attr_cltn_p = 0; |
| sc_object_manager* object_manager = m_simc->get_object_manager(); |
| m_parent = m_simc->active_object(); |
| |
| // CONSTRUCT PATHNAME TO OBJECT BEING CREATED: |
| // |
| // If there is not a leaf name generate one. |
| |
| m_name = object_manager->create_name(nm ? nm : sc_object_newname().c_str()); |
| |
| |
| // PLACE THE OBJECT INTO THE HIERARCHY |
| |
| object_manager->insert_object(m_name, this); |
| if ( m_parent ) |
| m_parent->add_child_object( this ); |
| else |
| m_simc->add_child_object( this ); |
| } |
| |
| sc_object::sc_object() : |
| m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), |
| m_parent(0), m_simc(0) |
| { |
| sc_object_init( sc_gen_unique_name("object") ); |
| } |
| |
| sc_object::sc_object( const sc_object& that ) : |
| m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), |
| m_parent(0), m_simc(0) |
| { |
| sc_object_init( sc_gen_unique_name( that.basename() ) ); |
| } |
| |
| |
| static bool |
| object_name_illegal_char(char ch) |
| { |
| return (ch == SC_HIERARCHY_CHAR) || isspace(ch); |
| } |
| |
| sc_object::sc_object(const char* nm) : |
| m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), |
| m_parent(0), m_simc(0) |
| { |
| int namebuf_alloc = 0; |
| char* namebuf = 0; |
| const char* p; |
| |
| // null name or "" uses machine generated name. |
| |
| if ( !nm || !*nm ) |
| nm = sc_gen_unique_name("object"); |
| p = nm; |
| |
| if (nm && sc_enable_name_checking) { |
| namebuf_alloc = 1 + strlen(nm); |
| namebuf = (char*) sc_mempool::allocate(namebuf_alloc); |
| char* q = namebuf; |
| const char* r = nm; |
| bool has_illegal_char = false; |
| while (*r) { |
| if (object_name_illegal_char(*r)) { |
| has_illegal_char = true; |
| *q = '_'; |
| } else { |
| *q = *r; |
| } |
| r++; |
| q++; |
| } |
| *q = '\0'; |
| p = namebuf; |
| if (has_illegal_char) |
| { |
| std::string message = nm; |
| message += " substituted by "; |
| message += namebuf; |
| SC_REPORT_WARNING( SC_ID_ILLEGAL_CHARACTERS_, message.c_str()); |
| } |
| } |
| sc_object_init(p); |
| sc_mempool::release( namebuf, namebuf_alloc ); |
| } |
| |
| sc_object::~sc_object() |
| { |
| #if SC_HAS_PHASE_CALLBACKS_ |
| unregister_simulation_phase_callback( SC_STATUS_ANY ); |
| #endif |
| detach(); |
| delete m_attr_cltn_p; |
| } |
| |
| //------------------------------------------------------------------------------ |
| //"sc_object::detach" |
| // |
| // This method detaches this object instance from the object hierarchy. |
| // It is called in two places: ~sc_object() and sc_process_b::kill_process(). |
| //------------------------------------------------------------------------------ |
| void sc_object::detach() |
| { |
| if (m_simc) { |
| |
| // REMOVE OBJECT FROM THE OBJECT MANAGER: |
| |
| sc_object_manager* object_manager = m_simc->get_object_manager(); |
| object_manager->remove_object(m_name); |
| |
| // REMOVE OBJECT FROM PARENT'S LIST OF OBJECTS: |
| |
| if ( m_parent ) |
| m_parent->remove_child_object( this ); |
| else |
| m_simc->remove_child_object( this ); |
| |
| // ORPHAN THIS OBJECT'S CHILDREN: |
| |
| #if 0 // #### |
| ::std::<sc_object*> children_p = &get_child_objects(); |
| int child_n = children_p->size(); |
| sc_object* parent_p; |
| |
| for ( int child_i = 0; child_i < child_n; child_i++ ) |
| { |
| (*children_p)[child_i]->m_parent = 0; |
| } |
| #endif |
| |
| } |
| } |
| |
| // +---------------------------------------------------------------------------- |
| // |"sc_object::orphan_child_events" |
| // | |
| // | This method moves the children of this object instance to be children |
| // | of the simulator. |
| // +---------------------------------------------------------------------------- |
| void sc_object::orphan_child_events() |
| { |
| std::vector< sc_event* > const & events = get_child_events(); |
| |
| std::vector< sc_event* >::const_iterator |
| it = events.begin(), end = events.end(); |
| |
| for( ; it != end; ++it ) |
| { |
| (*it)->m_parent_p = NULL; |
| simcontext()->add_child_event(*it); |
| } |
| } |
| |
| // +---------------------------------------------------------------------------- |
| // |"sc_object::orphan_child_objects" |
| // | |
| // | This method moves the children of this object instance to be children |
| // | of the simulator. |
| // +---------------------------------------------------------------------------- |
| void sc_object::orphan_child_objects() |
| { |
| std::vector< sc_object* > const & children = get_child_objects(); |
| |
| std::vector< sc_object* >::const_iterator |
| it = children.begin(), end = children.end(); |
| |
| for( ; it != end; ++it ) |
| { |
| (*it)->m_parent = NULL; |
| simcontext()->add_child_object(*it); |
| } |
| } |
| |
| void |
| sc_object::trace( sc_trace_file * /* unused */) const |
| { |
| /* This space is intentionally left blank */ |
| } |
| |
| |
| // add attribute |
| |
| bool |
| sc_object::add_attribute( sc_attr_base& attribute_ ) |
| { |
| if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; |
| return ( m_attr_cltn_p->push_back( &attribute_ ) ); |
| } |
| |
| |
| // get attribute by name |
| |
| sc_attr_base* |
| sc_object::get_attribute( const std::string& name_ ) |
| { |
| if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; |
| return ( (*m_attr_cltn_p)[name_] ); |
| } |
| |
| const sc_attr_base* |
| sc_object::get_attribute( const std::string& name_ ) const |
| { |
| if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; |
| return ( (*m_attr_cltn_p)[name_] ); |
| } |
| |
| |
| // remove attribute by name |
| |
| sc_attr_base* |
| sc_object::remove_attribute( const std::string& name_ ) |
| { |
| if ( m_attr_cltn_p ) |
| return ( m_attr_cltn_p->remove( name_ ) ); |
| else |
| return 0; |
| } |
| |
| |
| // remove all attributes |
| |
| void |
| sc_object::remove_all_attributes() |
| { |
| if ( m_attr_cltn_p ) |
| m_attr_cltn_p->remove_all(); |
| } |
| |
| |
| // get the number of attributes |
| |
| int |
| sc_object::num_attributes() const |
| { |
| if ( m_attr_cltn_p ) |
| return ( m_attr_cltn_p->size() ); |
| else |
| return 0; |
| } |
| |
| |
| // get the attribute collection |
| |
| sc_attr_cltn& |
| sc_object::attr_cltn() |
| { |
| if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; |
| return *m_attr_cltn_p; |
| } |
| |
| const sc_attr_cltn& |
| sc_object::attr_cltn() const |
| { |
| if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; |
| return *m_attr_cltn_p; |
| } |
| |
| sc_object* |
| sc_object::get_parent() const |
| { |
| static bool warn_sc_get_parent_deprecated=true; |
| if ( warn_sc_get_parent_deprecated ) |
| { |
| warn_sc_get_parent_deprecated=false; |
| SC_REPORT_INFO(sc_core::SC_ID_IEEE_1666_DEPRECATION_, |
| "sc_object::get_parent() is deprecated, " |
| "use get_parent_object() instead"); |
| } |
| return get_parent_object(); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // simulation phase callbacks |
| |
| |
| sc_object::phase_cb_mask |
| sc_object::register_simulation_phase_callback( phase_cb_mask mask ) |
| { |
| mask = simcontext()->m_phase_cb_registry |
| ->register_callback(*this, mask); |
| return mask; |
| } |
| |
| |
| sc_object::phase_cb_mask |
| sc_object::unregister_simulation_phase_callback( phase_cb_mask mask ) |
| { |
| mask = simcontext()->m_phase_cb_registry |
| ->unregister_callback(*this, mask); |
| return mask; |
| } |
| |
| |
| void |
| sc_object::simulation_phase_callback() |
| { |
| SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_NOT_IMPLEMENTED_, name() ); |
| } |
| |
| |
| } // namespace sc_core |
| |
| /***************************************************************************** |
| |
| MODIFICATION LOG - modifiers, enter your name, affiliation, date and |
| changes you are making here. |
| |
| Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, |
| 25 August, 2003 |
| Description of Modification: if module name hierarchy is empty, sc_object |
| ctor assumes the currently executing process |
| as the parent object to support dynamic process |
| creation similar to other sc_objects |
| |
| Name, Affiliation, Date: Andy Goodrich, Forte Design Systems |
| 5 September 2003 |
| Description of Modification: - Made creation of attributes structure |
| conditional on its being used. This eliminates |
| 100 bytes of storage for each normal sc_object. |
| |
| *****************************************************************************/ |
| |
| |
| // $Log: sc_object.cpp,v $ |
| // Revision 1.16 2011/08/29 18:04:32 acg |
| // Philipp A. Hartmann: miscellaneous clean ups. |
| // |
| // Revision 1.15 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. |
| // |
| // Revision 1.14 2011/08/24 22:05:51 acg |
| // Torsten Maehne: initialization changes to remove warnings. |
| // |
| // Revision 1.13 2011/04/01 21:24:57 acg |
| // Andy Goodrich: removed unused code. |
| // |
| // Revision 1.12 2011/03/06 15:55:11 acg |
| // Andy Goodrich: Changes for named events. |
| // |
| // Revision 1.11 2011/03/05 19:44:20 acg |
| // Andy Goodrich: changes for object and event naming and structures. |
| // |
| // Revision 1.10 2011/03/05 04:45:16 acg |
| // Andy Goodrich: moved active process calculation to the sc_simcontext class. |
| // |
| // 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/01/25 20:50:37 acg |
| // Andy Goodrich: changes for IEEE 1666 2011. |
| // |
| // Revision 1.5 2011/01/18 20:10:44 acg |
| // Andy Goodrich: changes for IEEE1666_2011 semantics. |
| // |
| // Revision 1.4 2010/08/03 17:02:39 acg |
| // Andy Goodrich: formatting changes. |
| // |
| // Revision 1.3 2009/02/28 00:26:58 acg |
| // Andy Goodrich: changed boost name space to sc_boost to allow use with |
| // full boost library applications. |
| // |
| // Revision 1.2 2008/05/22 17:06:26 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.5 2006/04/20 17:08:17 acg |
| // Andy Goodrich: 3.0 style process changes. |
| // |
| // Revision 1.4 2006/03/21 00:00:34 acg |
| // Andy Goodrich: changed name of sc_get_current_process_base() to be |
| // sc_get_current_process_b() since its returning an sc_process_b instance. |
| // |
| // Revision 1.3 2006/01/13 18:44:30 acg |
| // Added $Log to record CVS changes into the source. |
| // |