| /***************************************************************************** |
| |
| 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. |
| |
| *****************************************************************************/ |
| |
| #include "tlm_utils/instance_specific_extensions_int.h" |
| #include "sysc/utils/sc_typeindex.h" // sc_typeindex |
| |
| #include <map> |
| #include <iostream> |
| |
| namespace tlm { |
| template class SC_API tlm_array<tlm_utils::ispex_base*>; |
| } // namespace tlm |
| |
| namespace tlm_utils { |
| /* anonymous */ namespace { |
| class ispex_registry // copied from tlm_gp.cpp |
| { |
| typedef unsigned int key_type; |
| typedef std::map<sc_core::sc_type_index, key_type> type_map; |
| public: |
| static ispex_registry& instance() |
| { |
| if (!instance_) // don't cleanup registry |
| instance_ = new ispex_registry(); |
| return *instance_; |
| } |
| |
| unsigned int register_extension(sc_core::sc_type_index type) |
| { |
| type_map::const_iterator it = ids_.find( type ); |
| |
| if( it == ids_.end() ) { // new extension - generate/store ID |
| type_map::value_type v( type, static_cast<key_type>(ids_.size()) ); |
| ids_.insert( v ); |
| return v.second; |
| } |
| return it->second; |
| } |
| |
| static unsigned int max_num_extensions() |
| { return (instance_) ? instance().ids_.size() : 0; } |
| |
| private: |
| static ispex_registry* instance_; |
| type_map ids_; |
| ispex_registry() /* = default */ {} |
| |
| }; // class ispex_registry |
| |
| ispex_registry* ispex_registry::instance_ = NULL; |
| } // anonymous namespace |
| |
| unsigned int |
| ispex_base::register_private_extension(const std::type_info& type) |
| { |
| return ispex_registry::instance().register_extension(type); |
| } |
| |
| //Helper to do the numbering of private extension accessors |
| static unsigned int max_num_ispex_accessors(bool increment=false) |
| { |
| static unsigned int max_num = 0; |
| if (increment) ++max_num; |
| return max_num; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| //the pool for the container, plain as can be |
| class instance_specific_extension_container_pool |
| { |
| instance_specific_extension_container_pool() |
| : unused(NULL){} |
| |
| ~instance_specific_extension_container_pool(); |
| |
| public: |
| static instance_specific_extension_container_pool& instance() |
| { |
| static instance_specific_extension_container_pool inst; |
| return inst; |
| } |
| |
| instance_specific_extension_container* create(); |
| void free(instance_specific_extension_container*); |
| |
| private: |
| instance_specific_extension_container* unused; |
| }; // class instance_specific_extension_container_pool |
| |
| instance_specific_extension_container* |
| instance_specific_extension_container_pool::create() |
| { |
| if (!unused) { |
| unused =new instance_specific_extension_container(); |
| } |
| instance_specific_extension_container* tmp = unused; |
| unused = unused->next; |
| return tmp; |
| } |
| |
| void |
| instance_specific_extension_container_pool:: |
| free(instance_specific_extension_container* cont) |
| { |
| cont->next=unused; |
| unused=cont; |
| } |
| |
| instance_specific_extension_container_pool:: |
| ~instance_specific_extension_container_pool() |
| { |
| while(unused) { |
| instance_specific_extension_container* tmp = unused; |
| unused=unused->next; |
| delete tmp; |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| instance_specific_extension_container* |
| instance_specific_extension_container::create() |
| { |
| return instance_specific_extension_container_pool::instance().create(); |
| } |
| |
| instance_specific_extension_container::instance_specific_extension_container() |
| : use_count(0) |
| , m_txn(NULL) |
| , m_release_fn(NULL) |
| , m_carrier(NULL) |
| , next(NULL) |
| { |
| resize(); |
| } |
| |
| void |
| instance_specific_extension_container:: |
| attach_carrier(instance_specific_extension_carrier* carrier, |
| void* txn, release_fn* rel_fn) |
| { |
| m_txn = txn; |
| m_release_fn = rel_fn; |
| m_carrier = carrier; |
| } |
| |
| void |
| instance_specific_extension_container::resize() |
| { |
| m_ispex_per_accessor.resize( max_num_ispex_accessors() ); |
| |
| for (unsigned int i=0; i < m_ispex_per_accessor.size(); ++i) { |
| m_ispex_per_accessor[i] = new instance_specific_extensions_per_accessor(this); |
| m_ispex_per_accessor[i]->resize_extensions(); |
| } |
| } |
| |
| instance_specific_extension_container:: |
| ~instance_specific_extension_container() |
| { |
| for (unsigned int i=0; i<m_ispex_per_accessor.size(); ++i) |
| delete m_ispex_per_accessor[i]; |
| } |
| |
| void |
| instance_specific_extension_container::inc_use_count() |
| { |
| use_count++; |
| } |
| |
| void |
| instance_specific_extension_container::dec_use_count() |
| { |
| if ((--use_count)==0) { // if this container isn't used any more |
| // we release the carrier extension |
| m_release_fn(m_carrier, m_txn); |
| // we send it back to our pool |
| instance_specific_extension_container_pool::instance().free(this); |
| } |
| } |
| |
| instance_specific_extensions_per_accessor* |
| instance_specific_extension_container::get_accessor(unsigned int idx) |
| { |
| return m_ispex_per_accessor[idx]; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| // non-templatized version with manual index: |
| ispex_base* |
| instance_specific_extensions_per_accessor:: |
| set_extension(unsigned int index, ispex_base* ext) |
| { |
| resize_extensions(); |
| ispex_base* tmp = m_extensions[index]; |
| m_extensions[index] = ext; |
| if (!tmp && ext) m_container->inc_use_count(); |
| return tmp; |
| } |
| |
| ispex_base* |
| instance_specific_extensions_per_accessor:: |
| get_extension(unsigned int index) const |
| { |
| return (index < m_extensions.size()) ? m_extensions[index] : NULL; |
| } |
| |
| void |
| instance_specific_extensions_per_accessor:: |
| clear_extension(unsigned int index) |
| { |
| if (index < m_extensions.size()) |
| { |
| if (m_extensions[index]) m_container->dec_use_count(); |
| m_extensions[index] = static_cast<ispex_base*>(0); |
| } |
| } |
| |
| void |
| instance_specific_extensions_per_accessor::resize_extensions() |
| { |
| m_extensions.expand(ispex_registry::max_num_extensions()); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| instance_specific_extension_accessor::instance_specific_extension_accessor() |
| : m_index(max_num_ispex_accessors(true)-1) |
| {} |
| |
| } // namespace tlm_utils |