diff options
Diffstat (limited to 'ext/systemc/src/sysc/kernel/sc_object.cpp')
-rw-r--r-- | ext/systemc/src/sysc/kernel/sc_object.cpp | 568 |
1 files changed, 568 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/kernel/sc_object.cpp b/ext/systemc/src/sysc/kernel/sc_object.cpp new file mode 100644 index 000000000..e624d12b5 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object.cpp @@ -0,0 +1,568 @@ +/***************************************************************************** + + 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. +// |