instance_specific_extensions.cc revision 13514
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20#include <tlm_utils/instance_specific_extensions_int.h> 21 22#include <iostream> 23#include <map> 24#include <systemc> 25#include <tlm> 26 27namespace tlm 28{ 29 30template class tlm_array<tlm_utils::ispex_base *>; 31 32} // namespace tlm 33 34namespace tlm_utils 35{ 36 37namespace 38{ 39 40class ispex_registry // Copied from tlm_gp.cpp. 41{ 42 typedef unsigned int key_type; 43 typedef std::map<sc_core::sc_type_index, key_type> type_map; 44 45 public: 46 static ispex_registry & 47 instance() 48 { 49 if (!instance_) { 50 // Don't cleanup registry. 51 instance_ = new ispex_registry(); 52 } 53 return *instance_; 54 } 55 56 unsigned int 57 register_extension(sc_core::sc_type_index type) 58 { 59 type_map::const_iterator it = ids_.find(type); 60 61 if (it == ids_.end()) { 62 // New extension - generate/store ID. 63 type_map::value_type v(type, static_cast<key_type>(ids_.size())); 64 ids_.insert(v); 65 return v.second; 66 } 67 return it->second; 68 } 69 70 static unsigned int 71 max_num_extensions() 72 { 73 return (instance_) ? instance().ids_.size() : 0; 74 } 75 76 private: 77 static ispex_registry *instance_; 78 type_map ids_; 79 ispex_registry() {} 80}; 81 82ispex_registry *ispex_registry::instance_ = nullptr; 83 84} // anonymous namespace 85 86unsigned int 87ispex_base::register_private_extension(const std::type_info &type) 88{ 89 return ispex_registry::instance().register_extension(type); 90} 91 92// Helper to do the numbering of private extension accessors. 93static unsigned int 94max_num_ispex_accessors(bool increment=false) 95{ 96 static unsigned int max_num = 0; 97 if (increment) 98 ++max_num; 99 return max_num; 100} 101 102// ---------------------------------------------------------------------------- 103 104// The pool for the container, plain as can be. 105class instance_specific_extension_container_pool 106{ 107 instance_specific_extension_container_pool() : unused(nullptr) {} 108 ~instance_specific_extension_container_pool(); 109 110 public: 111 static instance_specific_extension_container_pool & 112 instance() 113 { 114 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