instance_specific_extensions.cc revision 13523
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> 2413514Sgabeblack@google.com#include <systemc> 2513514Sgabeblack@google.com#include <tlm> 2613523Sgabeblack@google.com#include <typeindex> 2713514Sgabeblack@google.com 2813514Sgabeblack@google.comnamespace tlm 2913514Sgabeblack@google.com{ 3013514Sgabeblack@google.com 3113514Sgabeblack@google.comtemplate class tlm_array<tlm_utils::ispex_base *>; 3213514Sgabeblack@google.com 3313514Sgabeblack@google.com} // namespace tlm 3413514Sgabeblack@google.com 3513514Sgabeblack@google.comnamespace tlm_utils 3613514Sgabeblack@google.com{ 3713514Sgabeblack@google.com 3813514Sgabeblack@google.comnamespace 3913514Sgabeblack@google.com{ 4013514Sgabeblack@google.com 4113514Sgabeblack@google.comclass ispex_registry // Copied from tlm_gp.cpp. 4213514Sgabeblack@google.com{ 4313514Sgabeblack@google.com typedef unsigned int key_type; 4413523Sgabeblack@google.com typedef std::map<std::type_index, key_type> type_map; 4513514Sgabeblack@google.com 4613514Sgabeblack@google.com public: 4713514Sgabeblack@google.com static ispex_registry & 4813514Sgabeblack@google.com instance() 4913514Sgabeblack@google.com { 5013514Sgabeblack@google.com if (!instance_) { 5113514Sgabeblack@google.com // Don't cleanup registry. 5213514Sgabeblack@google.com instance_ = new ispex_registry(); 5313514Sgabeblack@google.com } 5413514Sgabeblack@google.com return *instance_; 5513514Sgabeblack@google.com } 5613514Sgabeblack@google.com 5713514Sgabeblack@google.com unsigned int 5813523Sgabeblack@google.com register_extension(std::type_index type) 5913514Sgabeblack@google.com { 6013514Sgabeblack@google.com type_map::const_iterator it = ids_.find(type); 6113514Sgabeblack@google.com 6213514Sgabeblack@google.com if (it == ids_.end()) { 6313514Sgabeblack@google.com // New extension - generate/store ID. 6413514Sgabeblack@google.com type_map::value_type v(type, static_cast<key_type>(ids_.size())); 6513514Sgabeblack@google.com ids_.insert(v); 6613514Sgabeblack@google.com return v.second; 6713514Sgabeblack@google.com } 6813514Sgabeblack@google.com return it->second; 6913514Sgabeblack@google.com } 7013514Sgabeblack@google.com 7113514Sgabeblack@google.com static unsigned int 7213514Sgabeblack@google.com max_num_extensions() 7313514Sgabeblack@google.com { 7413514Sgabeblack@google.com return (instance_) ? instance().ids_.size() : 0; 7513514Sgabeblack@google.com } 7613514Sgabeblack@google.com 7713514Sgabeblack@google.com private: 7813514Sgabeblack@google.com static ispex_registry *instance_; 7913514Sgabeblack@google.com type_map ids_; 8013514Sgabeblack@google.com ispex_registry() {} 8113514Sgabeblack@google.com}; 8213514Sgabeblack@google.com 8313514Sgabeblack@google.comispex_registry *ispex_registry::instance_ = nullptr; 8413514Sgabeblack@google.com 8513514Sgabeblack@google.com} // anonymous namespace 8613514Sgabeblack@google.com 8713514Sgabeblack@google.comunsigned int 8813514Sgabeblack@google.comispex_base::register_private_extension(const std::type_info &type) 8913514Sgabeblack@google.com{ 9013514Sgabeblack@google.com return ispex_registry::instance().register_extension(type); 9113514Sgabeblack@google.com} 9213514Sgabeblack@google.com 9313514Sgabeblack@google.com// Helper to do the numbering of private extension accessors. 9413514Sgabeblack@google.comstatic unsigned int 9513514Sgabeblack@google.commax_num_ispex_accessors(bool increment=false) 9613514Sgabeblack@google.com{ 9713514Sgabeblack@google.com static unsigned int max_num = 0; 9813514Sgabeblack@google.com if (increment) 9913514Sgabeblack@google.com ++max_num; 10013514Sgabeblack@google.com return max_num; 10113514Sgabeblack@google.com} 10213514Sgabeblack@google.com 10313514Sgabeblack@google.com// ---------------------------------------------------------------------------- 10413514Sgabeblack@google.com 10513514Sgabeblack@google.com// The pool for the container, plain as can be. 10613514Sgabeblack@google.comclass instance_specific_extension_container_pool 10713514Sgabeblack@google.com{ 10813514Sgabeblack@google.com instance_specific_extension_container_pool() : unused(nullptr) {} 10913514Sgabeblack@google.com ~instance_specific_extension_container_pool(); 11013514Sgabeblack@google.com 11113514Sgabeblack@google.com public: 11213514Sgabeblack@google.com static instance_specific_extension_container_pool & 11313514Sgabeblack@google.com instance() 11413514Sgabeblack@google.com { 11513514Sgabeblack@google.com static instance_specific_extension_container_pool inst; 11613514Sgabeblack@google.com return inst; 11713514Sgabeblack@google.com } 11813514Sgabeblack@google.com 11913514Sgabeblack@google.com instance_specific_extension_container *create(); 12013514Sgabeblack@google.com void free(instance_specific_extension_container *); 12113514Sgabeblack@google.com 12213514Sgabeblack@google.com private: 12313514Sgabeblack@google.com instance_specific_extension_container *unused; 12413514Sgabeblack@google.com}; 12513514Sgabeblack@google.com 12613514Sgabeblack@google.cominstance_specific_extension_container * 12713514Sgabeblack@google.cominstance_specific_extension_container_pool::create() 12813514Sgabeblack@google.com{ 12913514Sgabeblack@google.com if (!unused) { 13013514Sgabeblack@google.com unused = new instance_specific_extension_container(); 13113514Sgabeblack@google.com } 13213514Sgabeblack@google.com instance_specific_extension_container *tmp = unused; 13313514Sgabeblack@google.com unused = unused->next; 13413514Sgabeblack@google.com return tmp; 13513514Sgabeblack@google.com} 13613514Sgabeblack@google.com 13713514Sgabeblack@google.comvoid 13813514Sgabeblack@google.cominstance_specific_extension_container_pool::free( 13913514Sgabeblack@google.com instance_specific_extension_container *cont) 14013514Sgabeblack@google.com{ 14113514Sgabeblack@google.com cont->next = unused; 14213514Sgabeblack@google.com unused = cont; 14313514Sgabeblack@google.com} 14413514Sgabeblack@google.com 14513514Sgabeblack@google.cominstance_specific_extension_container_pool:: 14613514Sgabeblack@google.com ~instance_specific_extension_container_pool() 14713514Sgabeblack@google.com{ 14813514Sgabeblack@google.com while (unused) { 14913514Sgabeblack@google.com instance_specific_extension_container *tmp = unused; 15013514Sgabeblack@google.com unused = unused->next; 15113514Sgabeblack@google.com delete tmp; 15213514Sgabeblack@google.com } 15313514Sgabeblack@google.com} 15413514Sgabeblack@google.com 15513514Sgabeblack@google.com// ---------------------------------------------------------------------------- 15613514Sgabeblack@google.com 15713514Sgabeblack@google.cominstance_specific_extension_container * 15813514Sgabeblack@google.cominstance_specific_extension_container::create() 15913514Sgabeblack@google.com{ 16013514Sgabeblack@google.com return instance_specific_extension_container_pool::instance().create(); 16113514Sgabeblack@google.com} 16213514Sgabeblack@google.com 16313514Sgabeblack@google.cominstance_specific_extension_container:: 16413514Sgabeblack@google.com instance_specific_extension_container() : 16513514Sgabeblack@google.com use_count(0), m_txn(NULL), m_release_fn(NULL), m_carrier(NULL), next(NULL) 16613514Sgabeblack@google.com{ 16713514Sgabeblack@google.com resize(); 16813514Sgabeblack@google.com} 16913514Sgabeblack@google.com 17013514Sgabeblack@google.comvoid 17113514Sgabeblack@google.cominstance_specific_extension_container:: 17213514Sgabeblack@google.com attach_carrier(instance_specific_extension_carrier *carrier, 17313514Sgabeblack@google.com void *txn, release_fn *rel_fn) 17413514Sgabeblack@google.com{ 17513514Sgabeblack@google.com m_txn = txn; 17613514Sgabeblack@google.com m_release_fn = rel_fn; 17713514Sgabeblack@google.com m_carrier = carrier; 17813514Sgabeblack@google.com} 17913514Sgabeblack@google.com 18013514Sgabeblack@google.comvoid 18113514Sgabeblack@google.cominstance_specific_extension_container::resize() 18213514Sgabeblack@google.com{ 18313514Sgabeblack@google.com m_ispex_per_accessor.resize(max_num_ispex_accessors()); 18413514Sgabeblack@google.com 18513514Sgabeblack@google.com for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) { 18613514Sgabeblack@google.com m_ispex_per_accessor[i] = 18713514Sgabeblack@google.com new instance_specific_extensions_per_accessor(this); 18813514Sgabeblack@google.com m_ispex_per_accessor[i]->resize_extensions(); 18913514Sgabeblack@google.com } 19013514Sgabeblack@google.com} 19113514Sgabeblack@google.com 19213514Sgabeblack@google.cominstance_specific_extension_container:: 19313514Sgabeblack@google.com ~instance_specific_extension_container() 19413514Sgabeblack@google.com{ 19513514Sgabeblack@google.com for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) 19613514Sgabeblack@google.com delete m_ispex_per_accessor[i]; 19713514Sgabeblack@google.com} 19813514Sgabeblack@google.com 19913514Sgabeblack@google.comvoid 20013514Sgabeblack@google.cominstance_specific_extension_container::inc_use_count() 20113514Sgabeblack@google.com{ 20213514Sgabeblack@google.com use_count++; 20313514Sgabeblack@google.com} 20413514Sgabeblack@google.com 20513514Sgabeblack@google.comvoid 20613514Sgabeblack@google.cominstance_specific_extension_container::dec_use_count() 20713514Sgabeblack@google.com{ 20813514Sgabeblack@google.com if ((--use_count) == 0) { 20913514Sgabeblack@google.com // If this container isn't used any more we release the carrier 21013514Sgabeblack@google.com // extension. 21113514Sgabeblack@google.com m_release_fn(m_carrier, m_txn); 21213514Sgabeblack@google.com // We send it back to our pool. 21313514Sgabeblack@google.com instance_specific_extension_container_pool::instance().free(this); 21413514Sgabeblack@google.com } 21513514Sgabeblack@google.com} 21613514Sgabeblack@google.com 21713514Sgabeblack@google.cominstance_specific_extensions_per_accessor * 21813514Sgabeblack@google.cominstance_specific_extension_container::get_accessor(unsigned int idx) 21913514Sgabeblack@google.com{ 22013514Sgabeblack@google.com return m_ispex_per_accessor[idx]; 22113514Sgabeblack@google.com} 22213514Sgabeblack@google.com 22313514Sgabeblack@google.com// ---------------------------------------------------------------------------- 22413514Sgabeblack@google.com 22513514Sgabeblack@google.com// non-templatized version with manual index: 22613514Sgabeblack@google.comispex_base * 22713514Sgabeblack@google.cominstance_specific_extensions_per_accessor::set_extension( 22813514Sgabeblack@google.com unsigned int index, ispex_base *ext) 22913514Sgabeblack@google.com{ 23013514Sgabeblack@google.com resize_extensions(); 23113514Sgabeblack@google.com ispex_base *tmp = m_extensions[index]; 23213514Sgabeblack@google.com m_extensions[index] = ext; 23313514Sgabeblack@google.com if (!tmp && ext) 23413514Sgabeblack@google.com m_container->inc_use_count(); 23513514Sgabeblack@google.com return tmp; 23613514Sgabeblack@google.com} 23713514Sgabeblack@google.com 23813514Sgabeblack@google.comispex_base * 23913514Sgabeblack@google.cominstance_specific_extensions_per_accessor::get_extension( 24013514Sgabeblack@google.com unsigned int index) const 24113514Sgabeblack@google.com{ 24213514Sgabeblack@google.com return (index < m_extensions.size()) ? m_extensions[index] : nullptr; 24313514Sgabeblack@google.com} 24413514Sgabeblack@google.com 24513514Sgabeblack@google.comvoid 24613514Sgabeblack@google.cominstance_specific_extensions_per_accessor::clear_extension(unsigned int index) 24713514Sgabeblack@google.com{ 24813514Sgabeblack@google.com if (index < m_extensions.size()) { 24913514Sgabeblack@google.com if (m_extensions[index]) 25013514Sgabeblack@google.com m_container->dec_use_count(); 25113514Sgabeblack@google.com m_extensions[index] = static_cast<ispex_base *>(nullptr); 25213514Sgabeblack@google.com } 25313514Sgabeblack@google.com} 25413514Sgabeblack@google.com 25513514Sgabeblack@google.comvoid 25613514Sgabeblack@google.cominstance_specific_extensions_per_accessor::resize_extensions() 25713514Sgabeblack@google.com{ 25813514Sgabeblack@google.com m_extensions.expand(ispex_registry::max_num_extensions()); 25913514Sgabeblack@google.com} 26013514Sgabeblack@google.com 26113514Sgabeblack@google.com// ---------------------------------------------------------------------------- 26213514Sgabeblack@google.com 26313514Sgabeblack@google.cominstance_specific_extension_accessor::instance_specific_extension_accessor() : 26413514Sgabeblack@google.com m_index(max_num_ispex_accessors(true) - 1) 26513514Sgabeblack@google.com{} 26613514Sgabeblack@google.com 26713514Sgabeblack@google.com} // namespace tlm_utils 268