| /***************************************************************************** |
| |
| 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_module.cpp -- Base class of all sequential and combinational processes. |
| |
| Original Author: Stan Y. Liao, Synopsys, Inc. |
| |
| CHANGE LOG AT THE END OF THE FILE |
| *****************************************************************************/ |
| |
| |
| #include <cassert> |
| #include <math.h> |
| #include <stddef.h> |
| #include <stdio.h> |
| |
| #include "sysc/kernel/sc_event.h" |
| #include "sysc/kernel/sc_kernel_ids.h" |
| #include "sysc/kernel/sc_module.h" |
| #include "sysc/kernel/sc_module_registry.h" |
| #include "sysc/kernel/sc_name_gen.h" |
| #include "sysc/kernel/sc_object_manager.h" |
| #include "sysc/kernel/sc_process.h" |
| #include "sysc/kernel/sc_process_handle.h" |
| #include "sysc/kernel/sc_simcontext.h" |
| #include "sysc/kernel/sc_simcontext_int.h" |
| #include "sysc/kernel/sc_object_int.h" |
| #include "sysc/kernel/sc_reset.h" |
| #include "sysc/communication/sc_communication_ids.h" |
| #include "sysc/communication/sc_interface.h" |
| #include "sysc/communication/sc_port.h" |
| #include "sysc/communication/sc_signal.h" |
| #include "sysc/communication/sc_signal_ports.h" |
| #include "sysc/utils/sc_utils_ids.h" |
| #include "sysc/utils/sc_iostream.h" |
| |
| namespace sc_core { |
| |
| // ---------------------------------------------------------------------------- |
| // CLASS : sc_module_dynalloc_list |
| // |
| // Garbage collection for modules dynamically allocated with SC_NEW. |
| // ---------------------------------------------------------------------------- |
| |
| class sc_module_dynalloc_list |
| { |
| public: |
| |
| sc_module_dynalloc_list() : m_list() |
| {} |
| |
| ~sc_module_dynalloc_list(); |
| |
| void add( sc_module* p ) |
| { m_list.push_back( p ); } |
| |
| private: |
| |
| sc_plist<sc_module*> m_list; |
| }; |
| |
| |
| //------------------------------------------------------------------------------ |
| //"~sc_module_dynalloc_list" |
| // |
| // Note we clear the m_parent field for the module being deleted. This because |
| // we process the list front to back so the parent has already been deleted, |
| // and we don't want ~sc_object() to try to access the parent which may |
| // contain garbage. |
| //------------------------------------------------------------------------------ |
| sc_module_dynalloc_list::~sc_module_dynalloc_list() |
| { |
| sc_plist<sc_module*>::iterator it( m_list ); |
| while( ! it.empty() ) { |
| (*it)->m_parent = 0; |
| delete *it; |
| it ++; |
| } |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| |
| sc_module* |
| sc_module_dynalloc( sc_module* module_ ) |
| { |
| static sc_module_dynalloc_list dynalloc_list; |
| dynalloc_list.add( module_ ); |
| return module_; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // STRUCT : sc_bind_proxy |
| // |
| // Struct for temporarily storing a pointer to an interface or port. |
| // Used for positional binding. |
| // ---------------------------------------------------------------------------- |
| |
| sc_bind_proxy::sc_bind_proxy() |
| : iface( 0 ), |
| port( 0 ) |
| {} |
| |
| sc_bind_proxy::sc_bind_proxy( sc_interface& iface_ ) |
| : iface( &iface_ ), |
| port( 0 ) |
| {} |
| |
| sc_bind_proxy::sc_bind_proxy( sc_port_base& port_ ) |
| : iface( 0 ), |
| port( &port_ ) |
| {} |
| |
| |
| const sc_bind_proxy SC_BIND_PROXY_NIL; |
| |
| |
| // ---------------------------------------------------------------------------- |
| // CLASS : sc_module |
| // |
| // Base class for all structural entities. |
| // ---------------------------------------------------------------------------- |
| |
| void |
| sc_module::sc_module_init() |
| { |
| simcontext()->get_module_registry()->insert( *this ); |
| simcontext()->hierarchy_push( this ); |
| m_end_module_called = false; |
| m_module_name_p = 0; |
| m_port_vec = new std::vector<sc_port_base*>; |
| m_port_index = 0; |
| m_name_gen = new sc_name_gen; |
| } |
| |
| /* |
| * This form of the constructor assumes that the user has |
| * used an sc_module_name parameter for his/her constructor. |
| * That parameter object has been pushed onto the stack, |
| * and can be looked up by calling the |
| * top_of_module_name_stack() function of the object manager. |
| * This technique has two advantages: |
| * |
| * 1) The user no longer has to write sc_module(name) in the |
| * constructor initializer. |
| * 2) The user no longer has to call end_module() at the end |
| * of the constructor -- a common negligence. |
| * |
| * But it is important to note that sc_module_name may be used |
| * in the user's constructor's parameter. If it is used anywhere |
| * else, unexpected things will happen. The error-checking |
| * mechanism builtin here cannot hope to catch all misuses. |
| * |
| */ |
| |
| sc_module::sc_module() |
| : sc_object(::sc_core::sc_get_curr_simcontext() |
| ->get_object_manager() |
| ->top_of_module_name_stack() |
| ->operator const char*()), |
| sensitive(this), |
| sensitive_pos(this), |
| sensitive_neg(this), |
| m_end_module_called(false), |
| m_port_vec(), |
| m_port_index(0), |
| m_name_gen(0), |
| m_module_name_p(0) |
| { |
| /* When this form is used, we better have a fresh sc_module_name |
| on the top of the stack */ |
| sc_module_name* mod_name = |
| simcontext()->get_object_manager()->top_of_module_name_stack(); |
| if (0 == mod_name || 0 != mod_name->m_module_p) |
| SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_REQUIRED_, 0 ); |
| sc_module_init(); |
| mod_name->set_module( this ); |
| m_module_name_p = mod_name; // must come after sc_module_init call. |
| } |
| |
| sc_module::sc_module( const sc_module_name& ) |
| : sc_object(::sc_core::sc_get_curr_simcontext() |
| ->get_object_manager() |
| ->top_of_module_name_stack() |
| ->operator const char*()), |
| sensitive(this), |
| sensitive_pos(this), |
| sensitive_neg(this), |
| m_end_module_called(false), |
| m_port_vec(), |
| m_port_index(0), |
| m_name_gen(0), |
| m_module_name_p(0) |
| { |
| /* For those used to the old style of passing a name to sc_module, |
| this constructor will reduce the chance of making a mistake */ |
| |
| /* When this form is used, we better have a fresh sc_module_name |
| on the top of the stack */ |
| sc_module_name* mod_name = |
| simcontext()->get_object_manager()->top_of_module_name_stack(); |
| if (0 == mod_name || 0 != mod_name->m_module_p) |
| SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_REQUIRED_, 0 ); |
| sc_module_init(); |
| mod_name->set_module( this ); |
| m_module_name_p = mod_name; // must come after sc_module_init call. |
| } |
| |
| /* -------------------------------------------------------------------- |
| * |
| * Deprecated constructors: |
| * sc_module( const char* ) |
| * sc_module( const std::string& ) |
| */ |
| sc_module::sc_module( const char* nm ) |
| : sc_object(nm), |
| sensitive(this), |
| sensitive_pos(this), |
| sensitive_neg(this), |
| m_end_module_called(false), |
| m_port_vec(), |
| m_port_index(0), |
| m_name_gen(0), |
| m_module_name_p(0) |
| { |
| SC_REPORT_WARNING( SC_ID_BAD_SC_MODULE_CONSTRUCTOR_, nm ); |
| sc_module_init(); |
| } |
| |
| sc_module::sc_module( const std::string& s ) |
| : sc_object( s.c_str() ), |
| sensitive(this), |
| sensitive_pos(this), |
| sensitive_neg(this), |
| m_end_module_called(false), |
| m_port_vec(), |
| m_port_index(0), |
| m_name_gen(0), |
| m_module_name_p(0) |
| { |
| SC_REPORT_WARNING( SC_ID_BAD_SC_MODULE_CONSTRUCTOR_, s.c_str() ); |
| sc_module_init(); |
| } |
| |
| /* -------------------------------------------------------------------- */ |
| |
| sc_module::~sc_module() |
| { |
| delete m_port_vec; |
| delete m_name_gen; |
| orphan_child_objects(); |
| if ( m_module_name_p ) |
| { |
| m_module_name_p->clear_module( this ); // must be before end_module() |
| end_module(); |
| } |
| simcontext()->get_module_registry()->remove( *this ); |
| } |
| |
| |
| const ::std::vector<sc_object*>& |
| sc_module::get_child_objects() const |
| { |
| return m_child_objects; |
| } |
| |
| // set SC_THREAD asynchronous reset sensitivity |
| |
| void |
| sc_module::async_reset_signal_is( const sc_in<bool>& port, bool level ) |
| { |
| sc_reset::reset_signal_is(true, port, level); |
| } |
| |
| void |
| sc_module::async_reset_signal_is( const sc_inout<bool>& port, bool level ) |
| { |
| sc_reset::reset_signal_is(true, port, level); |
| } |
| |
| void |
| sc_module::async_reset_signal_is( const sc_out<bool>& port, bool level ) |
| { |
| sc_reset::reset_signal_is(true, port, level); |
| } |
| |
| void |
| sc_module::async_reset_signal_is(const sc_signal_in_if<bool>& iface, bool level) |
| { |
| sc_reset::reset_signal_is(true, iface, level); |
| } |
| |
| void |
| sc_module::end_module() |
| { |
| if( ! m_end_module_called ) { |
| /* TBD: Can check here to alert the user that end_module |
| was not called for a previous module. */ |
| (void)sc_get_curr_simcontext()->hierarchy_pop(); |
| sc_get_curr_simcontext()->reset_curr_proc(); |
| sensitive.reset(); |
| sensitive_pos.reset(); |
| sensitive_neg.reset(); |
| m_end_module_called = true; |
| m_module_name_p = 0; // make sure we are not called in ~sc_module(). |
| } |
| } |
| |
| |
| // to prevent initialization for SC_METHODs and SC_THREADs |
| |
| void |
| sc_module::dont_initialize() |
| { |
| sc_process_handle last_proc = sc_get_last_created_process_handle(); |
| last_proc.dont_initialize( true ); |
| } |
| |
| // set SC_THREAD synchronous reset sensitivity |
| |
| void |
| sc_module::reset_signal_is( const sc_in<bool>& port, bool level ) |
| { |
| sc_reset::reset_signal_is(false, port, level); |
| } |
| |
| void |
| sc_module::reset_signal_is( const sc_inout<bool>& port, bool level ) |
| { |
| sc_reset::reset_signal_is(false, port, level); |
| } |
| |
| void |
| sc_module::reset_signal_is( const sc_out<bool>& port, bool level ) |
| { |
| sc_reset::reset_signal_is(false, port, level); |
| } |
| |
| void |
| sc_module::reset_signal_is( const sc_signal_in_if<bool>& iface, bool level ) |
| { |
| sc_reset::reset_signal_is(false, iface, level); |
| } |
| |
| // to generate unique names for objects in an MT-Safe way |
| |
| const char* |
| sc_module::gen_unique_name( const char* basename_, bool preserve_first ) |
| { |
| return m_name_gen->gen_unique_name( basename_, preserve_first ); |
| } |
| |
| |
| // called by construction_done |
| |
| void |
| sc_module::before_end_of_elaboration() |
| {} |
| |
| // We push the sc_module instance onto the stack of open objects so |
| // that any objects that are created in before_end_of_elaboration have |
| // the proper parent. After the call we pop the hierarchy. |
| void |
| sc_module::construction_done() |
| { |
| hierarchy_scope scope(this); |
| before_end_of_elaboration(); |
| } |
| |
| // called by elaboration_done (does nothing by default) |
| |
| void |
| sc_module::end_of_elaboration() |
| {} |
| |
| |
| // We push the sc_module instance onto the stack of open objects so |
| // that any objects that are created in end_of_elaboration have |
| // the proper parent. After the call we pop the hierarchy. |
| void |
| sc_module::elaboration_done( bool& error_ ) |
| { |
| if( ! m_end_module_called ) { |
| char msg[BUFSIZ]; |
| std::sprintf( msg, "module '%s'", name() ); |
| SC_REPORT_WARNING( SC_ID_END_MODULE_NOT_CALLED_, msg ); |
| if( error_ ) { |
| SC_REPORT_WARNING( SC_ID_HIER_NAME_INCORRECT_, 0 ); |
| } |
| error_ = true; |
| } |
| hierarchy_scope scope(this); |
| end_of_elaboration(); |
| } |
| |
| // called by start_simulation (does nothing by default) |
| |
| void |
| sc_module::start_of_simulation() |
| {} |
| |
| void |
| sc_module::start_simulation() |
| { |
| hierarchy_scope scope(this); |
| start_of_simulation(); |
| } |
| |
| // called by simulation_done (does nothing by default) |
| |
| void |
| sc_module::end_of_simulation() |
| {} |
| |
| void |
| sc_module::simulation_done() |
| { |
| hierarchy_scope scope(this); |
| end_of_simulation(); |
| } |
| |
| void |
| sc_module::set_stack_size( std::size_t size ) |
| { |
| sc_process_handle proc_h( |
| sc_is_running() ? |
| sc_get_current_process_handle() : |
| sc_get_last_created_process_handle() |
| ); |
| sc_thread_handle thread_h; // Current process as thread. |
| |
| |
| thread_h = (sc_thread_handle)proc_h; |
| if ( thread_h ) |
| { |
| thread_h->set_stack_size( size ); |
| } |
| else |
| { |
| SC_REPORT_WARNING( SC_ID_SET_STACK_SIZE_, 0 ); |
| } |
| } |
| |
| |
| int |
| sc_module::append_port( sc_port_base* port_ ) |
| { |
| int index = m_port_vec->size(); |
| m_port_vec->push_back( port_ ); |
| return index; |
| } |
| |
| |
| // positional binding methods |
| |
| static void sc_warn_arrow_arrow_bind() |
| { |
| static bool warn_arrow_arrow_bind=true; |
| if ( warn_arrow_arrow_bind ) |
| { |
| warn_arrow_arrow_bind = false; |
| SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, |
| "positional binding using << or , is deprecated, use () instead."); |
| } |
| } |
| |
| sc_module& |
| sc_module::operator << ( sc_interface& interface_ ) |
| { |
| sc_warn_arrow_arrow_bind(); |
| positional_bind(interface_); |
| return *this; |
| } |
| |
| sc_module& |
| sc_module::operator << ( sc_port_base& port_ ) |
| { |
| sc_warn_arrow_arrow_bind(); |
| positional_bind(port_); |
| return *this; |
| } |
| |
| |
| void |
| sc_module::positional_bind( sc_interface& interface_ ) |
| { |
| if( m_port_index == (int)m_port_vec->size() ) { |
| char msg[BUFSIZ]; |
| if( m_port_index == 0 ) { |
| std::sprintf( msg, "module `%s' has no ports", name() ); |
| } else { |
| std::sprintf( msg, "all ports of module `%s' are bound", name() ); |
| } |
| SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, msg ); |
| } |
| int status = (*m_port_vec)[m_port_index]->pbind( interface_ ); |
| if( status != 0 ) { |
| char msg[BUFSIZ]; |
| switch( status ) { |
| case 1: |
| std::sprintf( msg, "port %d of module `%s' is already bound", |
| m_port_index, name() ); |
| break; |
| case 2: |
| std::sprintf( msg, "type mismatch on port %d of module `%s'", |
| m_port_index, name() ); |
| break; |
| default: |
| std::sprintf( msg, "unknown error" ); |
| break; |
| } |
| SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, msg ); |
| } |
| ++ m_port_index; |
| } |
| |
| void |
| sc_module::positional_bind( sc_port_base& port_ ) |
| { |
| if( m_port_index == (int)m_port_vec->size() ) { |
| char msg[BUFSIZ]; |
| if( m_port_index == 0 ) { |
| std::sprintf( msg, "module `%s' has no ports", name() ); |
| } else { |
| std::sprintf( msg, "all ports of module `%s' are bound", name() ); |
| } |
| SC_REPORT_ERROR( SC_ID_BIND_PORT_TO_PORT_, msg ); |
| } |
| int status = (*m_port_vec)[m_port_index]->pbind( port_ ); |
| if( status != 0 ) { |
| char msg[BUFSIZ]; |
| switch( status ) { |
| case 1: |
| std::sprintf( msg, "port %d of module `%s' is already bound", |
| m_port_index, name() ); |
| break; |
| case 2: |
| std::sprintf( msg, "type mismatch on port %d of module `%s'", |
| m_port_index, name() ); |
| break; |
| default: |
| std::sprintf( msg, "unknown error" ); |
| break; |
| } |
| SC_REPORT_ERROR( SC_ID_BIND_PORT_TO_PORT_, msg ); |
| } |
| ++ m_port_index; |
| } |
| |
| |
| #define TRY_BIND( p ) \ |
| if( (p).iface != 0 ) { \ |
| positional_bind( *(p).iface ); \ |
| } else if( (p).port != 0 ) { \ |
| positional_bind( *(p).port ); \ |
| } else { \ |
| return; \ |
| } |
| |
| |
| void |
| sc_module::operator () ( const sc_bind_proxy& p001, |
| const sc_bind_proxy& p002, |
| const sc_bind_proxy& p003, |
| const sc_bind_proxy& p004, |
| const sc_bind_proxy& p005, |
| const sc_bind_proxy& p006, |
| const sc_bind_proxy& p007, |
| const sc_bind_proxy& p008, |
| const sc_bind_proxy& p009, |
| const sc_bind_proxy& p010, |
| const sc_bind_proxy& p011, |
| const sc_bind_proxy& p012, |
| const sc_bind_proxy& p013, |
| const sc_bind_proxy& p014, |
| const sc_bind_proxy& p015, |
| const sc_bind_proxy& p016, |
| const sc_bind_proxy& p017, |
| const sc_bind_proxy& p018, |
| const sc_bind_proxy& p019, |
| const sc_bind_proxy& p020, |
| const sc_bind_proxy& p021, |
| const sc_bind_proxy& p022, |
| const sc_bind_proxy& p023, |
| const sc_bind_proxy& p024, |
| const sc_bind_proxy& p025, |
| const sc_bind_proxy& p026, |
| const sc_bind_proxy& p027, |
| const sc_bind_proxy& p028, |
| const sc_bind_proxy& p029, |
| const sc_bind_proxy& p030, |
| const sc_bind_proxy& p031, |
| const sc_bind_proxy& p032, |
| const sc_bind_proxy& p033, |
| const sc_bind_proxy& p034, |
| const sc_bind_proxy& p035, |
| const sc_bind_proxy& p036, |
| const sc_bind_proxy& p037, |
| const sc_bind_proxy& p038, |
| const sc_bind_proxy& p039, |
| const sc_bind_proxy& p040, |
| const sc_bind_proxy& p041, |
| const sc_bind_proxy& p042, |
| const sc_bind_proxy& p043, |
| const sc_bind_proxy& p044, |
| const sc_bind_proxy& p045, |
| const sc_bind_proxy& p046, |
| const sc_bind_proxy& p047, |
| const sc_bind_proxy& p048, |
| const sc_bind_proxy& p049, |
| const sc_bind_proxy& p050, |
| const sc_bind_proxy& p051, |
| const sc_bind_proxy& p052, |
| const sc_bind_proxy& p053, |
| const sc_bind_proxy& p054, |
| const sc_bind_proxy& p055, |
| const sc_bind_proxy& p056, |
| const sc_bind_proxy& p057, |
| const sc_bind_proxy& p058, |
| const sc_bind_proxy& p059, |
| const sc_bind_proxy& p060, |
| const sc_bind_proxy& p061, |
| const sc_bind_proxy& p062, |
| const sc_bind_proxy& p063, |
| const sc_bind_proxy& p064 ) |
| { |
| static bool warn_only_once=true; |
| if ( m_port_index > 0 && warn_only_once ) |
| { |
| warn_only_once = false; |
| SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, |
| "multiple () binding deprecated, use explicit port binding instead." ); |
| } |
| |
| TRY_BIND( p001 ); |
| TRY_BIND( p002 ); |
| TRY_BIND( p003 ); |
| TRY_BIND( p004 ); |
| TRY_BIND( p005 ); |
| TRY_BIND( p006 ); |
| TRY_BIND( p007 ); |
| TRY_BIND( p008 ); |
| TRY_BIND( p009 ); |
| TRY_BIND( p010 ); |
| TRY_BIND( p011 ); |
| TRY_BIND( p012 ); |
| TRY_BIND( p013 ); |
| TRY_BIND( p014 ); |
| TRY_BIND( p015 ); |
| TRY_BIND( p016 ); |
| TRY_BIND( p017 ); |
| TRY_BIND( p018 ); |
| TRY_BIND( p019 ); |
| TRY_BIND( p020 ); |
| TRY_BIND( p021 ); |
| TRY_BIND( p022 ); |
| TRY_BIND( p023 ); |
| TRY_BIND( p024 ); |
| TRY_BIND( p025 ); |
| TRY_BIND( p026 ); |
| TRY_BIND( p027 ); |
| TRY_BIND( p028 ); |
| TRY_BIND( p029 ); |
| TRY_BIND( p030 ); |
| TRY_BIND( p031 ); |
| TRY_BIND( p032 ); |
| TRY_BIND( p033 ); |
| TRY_BIND( p034 ); |
| TRY_BIND( p035 ); |
| TRY_BIND( p036 ); |
| TRY_BIND( p037 ); |
| TRY_BIND( p038 ); |
| TRY_BIND( p039 ); |
| TRY_BIND( p040 ); |
| TRY_BIND( p041 ); |
| TRY_BIND( p042 ); |
| TRY_BIND( p043 ); |
| TRY_BIND( p044 ); |
| TRY_BIND( p045 ); |
| TRY_BIND( p046 ); |
| TRY_BIND( p047 ); |
| TRY_BIND( p048 ); |
| TRY_BIND( p049 ); |
| TRY_BIND( p050 ); |
| TRY_BIND( p051 ); |
| TRY_BIND( p052 ); |
| TRY_BIND( p053 ); |
| TRY_BIND( p054 ); |
| TRY_BIND( p055 ); |
| TRY_BIND( p056 ); |
| TRY_BIND( p057 ); |
| TRY_BIND( p058 ); |
| TRY_BIND( p059 ); |
| TRY_BIND( p060 ); |
| TRY_BIND( p061 ); |
| TRY_BIND( p062 ); |
| TRY_BIND( p063 ); |
| TRY_BIND( p064 ); |
| } |
| |
| } // namespace sc_core |
| |
| /***************************************************************************** |
| |
| MODIFICATION LOG - modifiers, enter your name, affiliation, date and |
| changes you are making here. |
| |
| Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. |
| Description of Modification: - Implementation of operator() and operator, |
| positional connection method. |
| - Implementation of error checking in |
| operator<<'s. |
| - Implementation of the function test_module_prm. |
| - Implementation of set_stack_size(). |
| |
| Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 |
| Description of Modification: Inherit from sc_process_host |
| |
| Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, |
| 25 August, 2003 |
| Description of Modification: dont_initialize() uses |
| sc_get_last_created_process_handle() instead of |
| sc_get_current_process_b() |
| |
| Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 25 Mar 2003 |
| Description of Modification: Fixed bug in SC_NEW, see comments on |
| ~sc_module_dynalloc_list below. |
| |
| |
| *****************************************************************************/ |
| |
| |
| // $Log: sc_module.cpp,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: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.12 2011/08/24 22:05:51 acg |
| // Torsten Maehne: initialization changes to remove warnings. |
| // |
| // Revision 1.11 2011/03/05 19:44:20 acg |
| // Andy Goodrich: changes for object and event naming and structures. |
| // |
| // Revision 1.10 2011/02/18 20:27:14 acg |
| // Andy Goodrich: Updated Copyrights. |
| // |
| // Revision 1.9 2011/02/16 22:37:30 acg |
| // Andy Goodrich: clean up to remove need for ps_disable_pending. |
| // |
| // Revision 1.8 2011/02/14 17:51:40 acg |
| // Andy Goodrich: proper pushing an poppping of the module hierarchy for |
| // start_of_simulation() and end_of_simulation. |
| // |
| // 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 2009/05/22 16:06:29 acg |
| // Andy Goodrich: process control updates. |
| // |
| // Revision 1.4 2008/11/17 15:57:15 acg |
| // Andy Goodrich: added deprecation message for sc_module(const char*) |
| // |
| // Revision 1.3 2008/05/22 17:06:25 acg |
| // Andy Goodrich: updated copyright notice to include 2008. |
| // |
| // Revision 1.2 2007/05/17 20:16:33 acg |
| // Andy Goodrich: changes for beta release to LWG. |
| // |
| // Revision 1.1.1.1 2006/12/15 20:20:05 acg |
| // SystemC 2.3 |
| // |
| // Revision 1.9 2006/12/02 20:58:18 acg |
| // Andy Goodrich: updates from 2.2 for IEEE 1666 support. |
| // |
| // Revision 1.8 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.7 2006/03/14 23:56:58 acg |
| // Andy Goodrich: This fixes a bug when an exception is thrown in |
| // sc_module::sc_module() for a dynamically allocated sc_module |
| // object. We are calling sc_module::end_module() on a module that has |
| // already been deleted. The scenario runs like this: |
| // |
| // a) the sc_module constructor is entered |
| // b) the exception is thrown |
| // c) the exception processor deletes the storage for the sc_module |
| // d) the stack is unrolled causing the sc_module_name instance to be deleted |
| // e) ~sc_module_name() calls end_module() with its pointer to the sc_module |
| // f) because the sc_module has been deleted its storage is corrupted, |
| // either by linking it to a free space chain, or by reuse of some sort |
| // g) the m_simc field is garbage |
| // h) the m_object_manager field is also garbage |
| // i) an exception occurs |
| // |
| // This does not happen for automatic sc_module instances since the |
| // storage for the module is not reclaimed its just part of the stack. |
| // |
| // I am fixing this by having the destructor for sc_module clear the |
| // module pointer in its sc_module_name instance. That cuts things at |
| // step (e) above, since the pointer will be null if the module has |
| // already been deleted. To make sure the module stack is okay, I call |
| // end-module() in ~sc_module in the case where there is an |
| // sc_module_name pointer lying around. |
| // |
| // Revision 1.6 2006/01/26 21:04:54 acg |
| // Andy Goodrich: deprecation message changes and additional messages. |
| // |
| // Revision 1.5 2006/01/25 00:31:19 acg |
| // Andy Goodrich: Changed over to use a standard message id of |
| // SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. |
| // |
| // Revision 1.4 2006/01/24 20:49:05 acg |
| // Andy Goodrich: changes to remove the use of deprecated features within the |
| // simulator, and to issue warning messages when deprecated features are used. |
| // |
| // Revision 1.3 2006/01/13 18:44:29 acg |
| // Added $Log to record CVS changes into the source. |
| // |
| |
| // Taf! |