113514Sgabeblack@google.com/***************************************************************************** 213514Sgabeblack@google.com 313514Sgabeblack@google.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 413514Sgabeblack@google.com more contributor license agreements. See the NOTICE file distributed 513514Sgabeblack@google.com with this work for additional information regarding copyright ownership. 613514Sgabeblack@google.com Accellera licenses this file to you under the Apache License, Version 2.0 713514Sgabeblack@google.com (the "License"); you may not use this file except in compliance with the 813514Sgabeblack@google.com License. You may obtain a copy of the License at 913514Sgabeblack@google.com 1013514Sgabeblack@google.com http://www.apache.org/licenses/LICENSE-2.0 1113514Sgabeblack@google.com 1213514Sgabeblack@google.com Unless required by applicable law or agreed to in writing, software 1313514Sgabeblack@google.com distributed under the License is distributed on an "AS IS" BASIS, 1413514Sgabeblack@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1513514Sgabeblack@google.com implied. See the License for the specific language governing 1613514Sgabeblack@google.com permissions and limitations under the License. 1713514Sgabeblack@google.com 1813514Sgabeblack@google.com *****************************************************************************/ 1913514Sgabeblack@google.com 2013514Sgabeblack@google.com#include <tlm_utils/instance_specific_extensions_int.h> 2113514Sgabeblack@google.com 2213514Sgabeblack@google.com#include <iostream> 2313514Sgabeblack@google.com#include <map> 2413523Sgabeblack@google.com#include <typeindex> 2513514Sgabeblack@google.com 2613514Sgabeblack@google.comnamespace tlm 2713514Sgabeblack@google.com{ 2813514Sgabeblack@google.com 2913514Sgabeblack@google.comtemplate class tlm_array<tlm_utils::ispex_base *>; 3013514Sgabeblack@google.com 3113514Sgabeblack@google.com} // namespace tlm 3213514Sgabeblack@google.com 3313514Sgabeblack@google.comnamespace tlm_utils 3413514Sgabeblack@google.com{ 3513514Sgabeblack@google.com 3613514Sgabeblack@google.comnamespace 3713514Sgabeblack@google.com{ 3813514Sgabeblack@google.com 3913514Sgabeblack@google.comclass ispex_registry // Copied from tlm_gp.cpp. 4013514Sgabeblack@google.com{ 4113514Sgabeblack@google.com typedef unsigned int key_type; 4213523Sgabeblack@google.com typedef std::map<std::type_index, key_type> type_map; 4313514Sgabeblack@google.com 4413514Sgabeblack@google.com public: 4513514Sgabeblack@google.com static ispex_registry & 4613514Sgabeblack@google.com instance() 4713514Sgabeblack@google.com { 4813514Sgabeblack@google.com if (!instance_) { 4913514Sgabeblack@google.com // Don't cleanup registry. 5013514Sgabeblack@google.com instance_ = new ispex_registry(); 5113514Sgabeblack@google.com } 5213514Sgabeblack@google.com return *instance_; 5313514Sgabeblack@google.com } 5413514Sgabeblack@google.com 5513514Sgabeblack@google.com unsigned int 5613523Sgabeblack@google.com register_extension(std::type_index type) 5713514Sgabeblack@google.com { 5813514Sgabeblack@google.com type_map::const_iterator it = ids_.find(type); 5913514Sgabeblack@google.com 6013514Sgabeblack@google.com if (it == ids_.end()) { 6113514Sgabeblack@google.com // New extension - generate/store ID. 6213514Sgabeblack@google.com type_map::value_type v(type, static_cast<key_type>(ids_.size())); 6313514Sgabeblack@google.com ids_.insert(v); 6413514Sgabeblack@google.com return v.second; 6513514Sgabeblack@google.com } 6613514Sgabeblack@google.com return it->second; 6713514Sgabeblack@google.com } 6813514Sgabeblack@google.com 6913514Sgabeblack@google.com static unsigned int 7013514Sgabeblack@google.com max_num_extensions() 7113514Sgabeblack@google.com { 7213514Sgabeblack@google.com return (instance_) ? instance().ids_.size() : 0; 7313514Sgabeblack@google.com } 7413514Sgabeblack@google.com 7513514Sgabeblack@google.com private: 7613514Sgabeblack@google.com static ispex_registry *instance_; 7713514Sgabeblack@google.com type_map ids_; 7813514Sgabeblack@google.com ispex_registry() {} 7913514Sgabeblack@google.com}; 8013514Sgabeblack@google.com 8113514Sgabeblack@google.comispex_registry *ispex_registry::instance_ = nullptr; 8213514Sgabeblack@google.com 8313514Sgabeblack@google.com} // anonymous namespace 8413514Sgabeblack@google.com 8513514Sgabeblack@google.comunsigned int 8613514Sgabeblack@google.comispex_base::register_private_extension(const std::type_info &type) 8713514Sgabeblack@google.com{ 8813514Sgabeblack@google.com return ispex_registry::instance().register_extension(type); 8913514Sgabeblack@google.com} 9013514Sgabeblack@google.com 9113514Sgabeblack@google.com// Helper to do the numbering of private extension accessors. 9213514Sgabeblack@google.comstatic unsigned int 9313514Sgabeblack@google.commax_num_ispex_accessors(bool increment=false) 9413514Sgabeblack@google.com{ 9513514Sgabeblack@google.com static unsigned int max_num = 0; 9613514Sgabeblack@google.com if (increment) 9713514Sgabeblack@google.com ++max_num; 9813514Sgabeblack@google.com return max_num; 9913514Sgabeblack@google.com} 10013514Sgabeblack@google.com 10113514Sgabeblack@google.com// ---------------------------------------------------------------------------- 10213514Sgabeblack@google.com 10313514Sgabeblack@google.com// The pool for the container, plain as can be. 10413514Sgabeblack@google.comclass instance_specific_extension_container_pool 10513514Sgabeblack@google.com{ 10613514Sgabeblack@google.com instance_specific_extension_container_pool() : unused(nullptr) {} 10713514Sgabeblack@google.com ~instance_specific_extension_container_pool(); 10813514Sgabeblack@google.com 10913514Sgabeblack@google.com public: 11013514Sgabeblack@google.com static instance_specific_extension_container_pool & 11113514Sgabeblack@google.com instance() 11213514Sgabeblack@google.com { 11313514Sgabeblack@google.com static instance_specific_extension_container_pool inst; 11413514Sgabeblack@google.com return inst; 11513514Sgabeblack@google.com } 11613514Sgabeblack@google.com 11713514Sgabeblack@google.com instance_specific_extension_container *create(); 11813514Sgabeblack@google.com void free(instance_specific_extension_container *); 11913514Sgabeblack@google.com 12013514Sgabeblack@google.com private: 12113514Sgabeblack@google.com instance_specific_extension_container *unused; 12213514Sgabeblack@google.com}; 12313514Sgabeblack@google.com 12413514Sgabeblack@google.cominstance_specific_extension_container * 12513514Sgabeblack@google.cominstance_specific_extension_container_pool::create() 12613514Sgabeblack@google.com{ 12713514Sgabeblack@google.com if (!unused) { 12813514Sgabeblack@google.com unused = new instance_specific_extension_container(); 12913514Sgabeblack@google.com } 13013514Sgabeblack@google.com instance_specific_extension_container *tmp = unused; 13113514Sgabeblack@google.com unused = unused->next; 13213514Sgabeblack@google.com return tmp; 13313514Sgabeblack@google.com} 13413514Sgabeblack@google.com 13513514Sgabeblack@google.comvoid 13613514Sgabeblack@google.cominstance_specific_extension_container_pool::free( 13713514Sgabeblack@google.com instance_specific_extension_container *cont) 13813514Sgabeblack@google.com{ 13913514Sgabeblack@google.com cont->next = unused; 14013514Sgabeblack@google.com unused = cont; 14113514Sgabeblack@google.com} 14213514Sgabeblack@google.com 14313514Sgabeblack@google.cominstance_specific_extension_container_pool:: 14413514Sgabeblack@google.com ~instance_specific_extension_container_pool() 14513514Sgabeblack@google.com{ 14613514Sgabeblack@google.com while (unused) { 14713514Sgabeblack@google.com instance_specific_extension_container *tmp = unused; 14813514Sgabeblack@google.com unused = unused->next; 14913514Sgabeblack@google.com delete tmp; 15013514Sgabeblack@google.com } 15113514Sgabeblack@google.com} 15213514Sgabeblack@google.com 15313514Sgabeblack@google.com// ---------------------------------------------------------------------------- 15413514Sgabeblack@google.com 15513514Sgabeblack@google.cominstance_specific_extension_container * 15613514Sgabeblack@google.cominstance_specific_extension_container::create() 15713514Sgabeblack@google.com{ 15813514Sgabeblack@google.com return instance_specific_extension_container_pool::instance().create(); 15913514Sgabeblack@google.com} 16013514Sgabeblack@google.com 16113514Sgabeblack@google.cominstance_specific_extension_container:: 16213514Sgabeblack@google.com instance_specific_extension_container() : 16313514Sgabeblack@google.com use_count(0), m_txn(NULL), m_release_fn(NULL), m_carrier(NULL), next(NULL) 16413514Sgabeblack@google.com{ 16513514Sgabeblack@google.com resize(); 16613514Sgabeblack@google.com} 16713514Sgabeblack@google.com 16813514Sgabeblack@google.comvoid 16913514Sgabeblack@google.cominstance_specific_extension_container:: 17013514Sgabeblack@google.com attach_carrier(instance_specific_extension_carrier *carrier, 17113514Sgabeblack@google.com void *txn, release_fn *rel_fn) 17213514Sgabeblack@google.com{ 17313514Sgabeblack@google.com m_txn = txn; 17413514Sgabeblack@google.com m_release_fn = rel_fn; 17513514Sgabeblack@google.com m_carrier = carrier; 17613514Sgabeblack@google.com} 17713514Sgabeblack@google.com 17813514Sgabeblack@google.comvoid 17913514Sgabeblack@google.cominstance_specific_extension_container::resize() 18013514Sgabeblack@google.com{ 18113514Sgabeblack@google.com m_ispex_per_accessor.resize(max_num_ispex_accessors()); 18213514Sgabeblack@google.com 18313514Sgabeblack@google.com for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) { 18413514Sgabeblack@google.com m_ispex_per_accessor[i] = 18513514Sgabeblack@google.com new instance_specific_extensions_per_accessor(this); 18613514Sgabeblack@google.com m_ispex_per_accessor[i]->resize_extensions(); 18713514Sgabeblack@google.com } 18813514Sgabeblack@google.com} 18913514Sgabeblack@google.com 19013514Sgabeblack@google.cominstance_specific_extension_container:: 19113514Sgabeblack@google.com ~instance_specific_extension_container() 19213514Sgabeblack@google.com{ 19313514Sgabeblack@google.com for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) 19413514Sgabeblack@google.com delete m_ispex_per_accessor[i]; 19513514Sgabeblack@google.com} 19613514Sgabeblack@google.com 19713514Sgabeblack@google.comvoid 19813514Sgabeblack@google.cominstance_specific_extension_container::inc_use_count() 19913514Sgabeblack@google.com{ 20013514Sgabeblack@google.com use_count++; 20113514Sgabeblack@google.com} 20213514Sgabeblack@google.com 20313514Sgabeblack@google.comvoid 20413514Sgabeblack@google.cominstance_specific_extension_container::dec_use_count() 20513514Sgabeblack@google.com{ 20613514Sgabeblack@google.com if ((--use_count) == 0) { 20713514Sgabeblack@google.com // If this container isn't used any more we release the carrier 20813514Sgabeblack@google.com // extension. 20913514Sgabeblack@google.com m_release_fn(m_carrier, m_txn); 21013514Sgabeblack@google.com // We send it back to our pool. 21113514Sgabeblack@google.com instance_specific_extension_container_pool::instance().free(this); 21213514Sgabeblack@google.com } 21313514Sgabeblack@google.com} 21413514Sgabeblack@google.com 21513514Sgabeblack@google.cominstance_specific_extensions_per_accessor * 21613514Sgabeblack@google.cominstance_specific_extension_container::get_accessor(unsigned int idx) 21713514Sgabeblack@google.com{ 21813514Sgabeblack@google.com return m_ispex_per_accessor[idx]; 21913514Sgabeblack@google.com} 22013514Sgabeblack@google.com 22113514Sgabeblack@google.com// ---------------------------------------------------------------------------- 22213514Sgabeblack@google.com 22313514Sgabeblack@google.com// non-templatized version with manual index: 22413514Sgabeblack@google.comispex_base * 22513514Sgabeblack@google.cominstance_specific_extensions_per_accessor::set_extension( 22613514Sgabeblack@google.com unsigned int index, ispex_base *ext) 22713514Sgabeblack@google.com{ 22813514Sgabeblack@google.com resize_extensions(); 22913514Sgabeblack@google.com ispex_base *tmp = m_extensions[index]; 23013514Sgabeblack@google.com m_extensions[index] = ext; 23113514Sgabeblack@google.com if (!tmp && ext) 23213514Sgabeblack@google.com m_container->inc_use_count(); 23313514Sgabeblack@google.com return tmp; 23413514Sgabeblack@google.com} 23513514Sgabeblack@google.com 23613514Sgabeblack@google.comispex_base * 23713514Sgabeblack@google.cominstance_specific_extensions_per_accessor::get_extension( 23813514Sgabeblack@google.com unsigned int index) const 23913514Sgabeblack@google.com{ 24013514Sgabeblack@google.com return (index < m_extensions.size()) ? m_extensions[index] : nullptr; 24113514Sgabeblack@google.com} 24213514Sgabeblack@google.com 24313514Sgabeblack@google.comvoid 24413514Sgabeblack@google.cominstance_specific_extensions_per_accessor::clear_extension(unsigned int index) 24513514Sgabeblack@google.com{ 24613514Sgabeblack@google.com if (index < m_extensions.size()) { 24713514Sgabeblack@google.com if (m_extensions[index]) 24813514Sgabeblack@google.com m_container->dec_use_count(); 24913514Sgabeblack@google.com m_extensions[index] = static_cast<ispex_base *>(nullptr); 25013514Sgabeblack@google.com } 25113514Sgabeblack@google.com} 25213514Sgabeblack@google.com 25313514Sgabeblack@google.comvoid 25413514Sgabeblack@google.cominstance_specific_extensions_per_accessor::resize_extensions() 25513514Sgabeblack@google.com{ 25613514Sgabeblack@google.com m_extensions.expand(ispex_registry::max_num_extensions()); 25713514Sgabeblack@google.com} 25813514Sgabeblack@google.com 25913514Sgabeblack@google.com// ---------------------------------------------------------------------------- 26013514Sgabeblack@google.com 26113514Sgabeblack@google.cominstance_specific_extension_accessor::instance_specific_extension_accessor() : 26213514Sgabeblack@google.com m_index(max_num_ispex_accessors(true) - 1) 26313514Sgabeblack@google.com{} 26413514Sgabeblack@google.com 26513514Sgabeblack@google.com} // namespace tlm_utils 266