instance_specific_extensions.cc revision 13514:75569a60a0be
16145SN/A/***************************************************************************** 212065Snikos.nikoleris@arm.com 312065Snikos.nikoleris@arm.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 412065Snikos.nikoleris@arm.com more contributor license agreements. See the NOTICE file distributed 512065Snikos.nikoleris@arm.com with this work for additional information regarding copyright ownership. 612065Snikos.nikoleris@arm.com Accellera licenses this file to you under the Apache License, Version 2.0 712065Snikos.nikoleris@arm.com (the "License"); you may not use this file except in compliance with the 812065Snikos.nikoleris@arm.com License. You may obtain a copy of the License at 912065Snikos.nikoleris@arm.com 1012065Snikos.nikoleris@arm.com http://www.apache.org/licenses/LICENSE-2.0 1112065Snikos.nikoleris@arm.com 1212065Snikos.nikoleris@arm.com Unless required by applicable law or agreed to in writing, software 1312065Snikos.nikoleris@arm.com distributed under the License is distributed on an "AS IS" BASIS, 146145SN/A WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 156145SN/A implied. See the License for the specific language governing 166145SN/A permissions and limitations under the License. 176145SN/A 186145SN/A *****************************************************************************/ 196145SN/A 206145SN/A#include <tlm_utils/instance_specific_extensions_int.h> 216145SN/A 226145SN/A#include <iostream> 236145SN/A#include <map> 246145SN/A#include <systemc> 256145SN/A#include <tlm> 266145SN/A 276145SN/Anamespace tlm 286145SN/A{ 296145SN/A 306145SN/Atemplate class tlm_array<tlm_utils::ispex_base *>; 316145SN/A 326145SN/A} // namespace tlm 336145SN/A 346145SN/Anamespace tlm_utils 356145SN/A{ 366145SN/A 376145SN/Anamespace 386145SN/A{ 396145SN/A 406145SN/Aclass ispex_registry // Copied from tlm_gp.cpp. 4110441Snilay@cs.wisc.edu{ 4210441Snilay@cs.wisc.edu typedef unsigned int key_type; 436145SN/A typedef std::map<sc_core::sc_type_index, key_type> type_map; 447055SN/A 457055SN/A public: 467055SN/A static ispex_registry & 4712065Snikos.nikoleris@arm.com instance() 4810301Snilay@cs.wisc.edu { 497039SN/A if (!instance_) { 508644SN/A // Don't cleanup registry. 517039SN/A instance_ = new ispex_registry(); 527039SN/A } 536145SN/A return *instance_; 547039SN/A } 557039SN/A 567039SN/A unsigned int 576876SN/A register_extension(sc_core::sc_type_index type) 586876SN/A { 597039SN/A type_map::const_iterator it = ids_.find(type); 606145SN/A 617039SN/A if (it == ids_.end()) { 626145SN/A // New extension - generate/store ID. 6312065Snikos.nikoleris@arm.com type_map::value_type v(type, static_cast<key_type>(ids_.size())); 6412065Snikos.nikoleris@arm.com ids_.insert(v); 6512065Snikos.nikoleris@arm.com return v.second; 6612065Snikos.nikoleris@arm.com } 6712065Snikos.nikoleris@arm.com return it->second; 6812065Snikos.nikoleris@arm.com } 6912065Snikos.nikoleris@arm.com 7012065Snikos.nikoleris@arm.com static unsigned int 7112065Snikos.nikoleris@arm.com max_num_extensions() 7212065Snikos.nikoleris@arm.com { 7312065Snikos.nikoleris@arm.com return (instance_) ? instance().ids_.size() : 0; 7411025Snilay@cs.wisc.edu } 756285SN/A 7611025Snilay@cs.wisc.edu private: 776285SN/A static ispex_registry *instance_; 7811025Snilay@cs.wisc.edu type_map ids_; 7911025Snilay@cs.wisc.edu ispex_registry() {} 8011025Snilay@cs.wisc.edu}; 816145SN/A 827055SN/Aispex_registry *ispex_registry::instance_ = nullptr; 839104SN/A 849104SN/A} // anonymous namespace 857039SN/A 867039SN/Aunsigned int 877039SN/Aispex_base::register_private_extension(const std::type_info &type) 887039SN/A{ 896145SN/A return ispex_registry::instance().register_extension(type); 907039SN/A} 917055SN/A 928644SN/A// Helper to do the numbering of private extension accessors. 937039SN/Astatic unsigned int 947039SN/Amax_num_ispex_accessors(bool increment=false) 9511025Snilay@cs.wisc.edu{ 9611025Snilay@cs.wisc.edu static unsigned int max_num = 0; 9711025Snilay@cs.wisc.edu if (increment) 986145SN/A ++max_num; 9912065Snikos.nikoleris@arm.com return max_num; 10012065Snikos.nikoleris@arm.com} 10112065Snikos.nikoleris@arm.com 10212065Snikos.nikoleris@arm.com// ---------------------------------------------------------------------------- 10312065Snikos.nikoleris@arm.com 1046145SN/A// The pool for the container, plain as can be. 1056145SN/Aclass instance_specific_extension_container_pool 1067055SN/A{ 1077055SN/A instance_specific_extension_container_pool() : unused(nullptr) {} 1086145SN/A ~instance_specific_extension_container_pool(); 1097039SN/A 1107055SN/A public: 1117039SN/A static instance_specific_extension_container_pool & 1126145SN/A instance() 1136145SN/A { 11410441Snilay@cs.wisc.edu static instance_specific_extension_container_pool inst; 115 return inst; 116 } 117 118 instance_specific_extension_container *create(); 119 void free(instance_specific_extension_container *); 120 121 private: 122 instance_specific_extension_container *unused; 123}; 124 125instance_specific_extension_container * 126instance_specific_extension_container_pool::create() 127{ 128 if (!unused) { 129 unused = new instance_specific_extension_container(); 130 } 131 instance_specific_extension_container *tmp = unused; 132 unused = unused->next; 133 return tmp; 134} 135 136void 137instance_specific_extension_container_pool::free( 138 instance_specific_extension_container *cont) 139{ 140 cont->next = unused; 141 unused = cont; 142} 143 144instance_specific_extension_container_pool:: 145 ~instance_specific_extension_container_pool() 146{ 147 while (unused) { 148 instance_specific_extension_container *tmp = unused; 149 unused = unused->next; 150 delete tmp; 151 } 152} 153 154// ---------------------------------------------------------------------------- 155 156instance_specific_extension_container * 157instance_specific_extension_container::create() 158{ 159 return instance_specific_extension_container_pool::instance().create(); 160} 161 162instance_specific_extension_container:: 163 instance_specific_extension_container() : 164 use_count(0), m_txn(NULL), m_release_fn(NULL), m_carrier(NULL), next(NULL) 165{ 166 resize(); 167} 168 169void 170instance_specific_extension_container:: 171 attach_carrier(instance_specific_extension_carrier *carrier, 172 void *txn, release_fn *rel_fn) 173{ 174 m_txn = txn; 175 m_release_fn = rel_fn; 176 m_carrier = carrier; 177} 178 179void 180instance_specific_extension_container::resize() 181{ 182 m_ispex_per_accessor.resize(max_num_ispex_accessors()); 183 184 for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) { 185 m_ispex_per_accessor[i] = 186 new instance_specific_extensions_per_accessor(this); 187 m_ispex_per_accessor[i]->resize_extensions(); 188 } 189} 190 191instance_specific_extension_container:: 192 ~instance_specific_extension_container() 193{ 194 for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) 195 delete m_ispex_per_accessor[i]; 196} 197 198void 199instance_specific_extension_container::inc_use_count() 200{ 201 use_count++; 202} 203 204void 205instance_specific_extension_container::dec_use_count() 206{ 207 if ((--use_count) == 0) { 208 // If this container isn't used any more we release the carrier 209 // extension. 210 m_release_fn(m_carrier, m_txn); 211 // We send it back to our pool. 212 instance_specific_extension_container_pool::instance().free(this); 213 } 214} 215 216instance_specific_extensions_per_accessor * 217instance_specific_extension_container::get_accessor(unsigned int idx) 218{ 219 return m_ispex_per_accessor[idx]; 220} 221 222// ---------------------------------------------------------------------------- 223 224// non-templatized version with manual index: 225ispex_base * 226instance_specific_extensions_per_accessor::set_extension( 227 unsigned int index, ispex_base *ext) 228{ 229 resize_extensions(); 230 ispex_base *tmp = m_extensions[index]; 231 m_extensions[index] = ext; 232 if (!tmp && ext) 233 m_container->inc_use_count(); 234 return tmp; 235} 236 237ispex_base * 238instance_specific_extensions_per_accessor::get_extension( 239 unsigned int index) const 240{ 241 return (index < m_extensions.size()) ? m_extensions[index] : nullptr; 242} 243 244void 245instance_specific_extensions_per_accessor::clear_extension(unsigned int index) 246{ 247 if (index < m_extensions.size()) { 248 if (m_extensions[index]) 249 m_container->dec_use_count(); 250 m_extensions[index] = static_cast<ispex_base *>(nullptr); 251 } 252} 253 254void 255instance_specific_extensions_per_accessor::resize_extensions() 256{ 257 m_extensions.expand(ispex_registry::max_num_extensions()); 258} 259 260// ---------------------------------------------------------------------------- 261 262instance_specific_extension_accessor::instance_specific_extension_accessor() : 263 m_index(max_num_ispex_accessors(true) - 1) 264{} 265 266} // namespace tlm_utils 267