instance_specific_extensions.cc (13523:de27641700bb) | instance_specific_extensions.cc (13586:008fe87c1ad4) |
---|---|
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> | 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#include <typeindex> 27 28namespace tlm 29{ 30 31template class tlm_array<tlm_utils::ispex_base *>; 32 33} // namespace tlm 34 35namespace tlm_utils 36{ 37 38namespace 39{ 40 41class ispex_registry // Copied from tlm_gp.cpp. 42{ 43 typedef unsigned int key_type; 44 typedef std::map<std::type_index, key_type> type_map; 45 46 public: 47 static ispex_registry & 48 instance() 49 { 50 if (!instance_) { 51 // Don't cleanup registry. 52 instance_ = new ispex_registry(); 53 } 54 return *instance_; 55 } 56 57 unsigned int 58 register_extension(std::type_index type) 59 { 60 type_map::const_iterator it = ids_.find(type); 61 62 if (it == ids_.end()) { 63 // New extension - generate/store ID. 64 type_map::value_type v(type, static_cast<key_type>(ids_.size())); 65 ids_.insert(v); 66 return v.second; 67 } 68 return it->second; 69 } 70 71 static unsigned int 72 max_num_extensions() 73 { 74 return (instance_) ? instance().ids_.size() : 0; 75 } 76 77 private: 78 static ispex_registry *instance_; 79 type_map ids_; 80 ispex_registry() {} 81}; 82 83ispex_registry *ispex_registry::instance_ = nullptr; 84 85} // anonymous namespace 86 87unsigned int 88ispex_base::register_private_extension(const std::type_info &type) 89{ 90 return ispex_registry::instance().register_extension(type); 91} 92 93// Helper to do the numbering of private extension accessors. 94static unsigned int 95max_num_ispex_accessors(bool increment=false) 96{ 97 static unsigned int max_num = 0; 98 if (increment) 99 ++max_num; 100 return max_num; 101} 102 103// ---------------------------------------------------------------------------- 104 105// The pool for the container, plain as can be. 106class instance_specific_extension_container_pool 107{ 108 instance_specific_extension_container_pool() : unused(nullptr) {} 109 ~instance_specific_extension_container_pool(); 110 111 public: 112 static instance_specific_extension_container_pool & 113 instance() 114 { 115 static instance_specific_extension_container_pool inst; 116 return inst; 117 } 118 119 instance_specific_extension_container *create(); 120 void free(instance_specific_extension_container *); 121 122 private: 123 instance_specific_extension_container *unused; 124}; 125 126instance_specific_extension_container * 127instance_specific_extension_container_pool::create() 128{ 129 if (!unused) { 130 unused = new instance_specific_extension_container(); 131 } 132 instance_specific_extension_container *tmp = unused; 133 unused = unused->next; 134 return tmp; 135} 136 137void 138instance_specific_extension_container_pool::free( 139 instance_specific_extension_container *cont) 140{ 141 cont->next = unused; 142 unused = cont; 143} 144 145instance_specific_extension_container_pool:: 146 ~instance_specific_extension_container_pool() 147{ 148 while (unused) { 149 instance_specific_extension_container *tmp = unused; 150 unused = unused->next; 151 delete tmp; 152 } 153} 154 155// ---------------------------------------------------------------------------- 156 157instance_specific_extension_container * 158instance_specific_extension_container::create() 159{ 160 return instance_specific_extension_container_pool::instance().create(); 161} 162 163instance_specific_extension_container:: 164 instance_specific_extension_container() : 165 use_count(0), m_txn(NULL), m_release_fn(NULL), m_carrier(NULL), next(NULL) 166{ 167 resize(); 168} 169 170void 171instance_specific_extension_container:: 172 attach_carrier(instance_specific_extension_carrier *carrier, 173 void *txn, release_fn *rel_fn) 174{ 175 m_txn = txn; 176 m_release_fn = rel_fn; 177 m_carrier = carrier; 178} 179 180void 181instance_specific_extension_container::resize() 182{ 183 m_ispex_per_accessor.resize(max_num_ispex_accessors()); 184 185 for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) { 186 m_ispex_per_accessor[i] = 187 new instance_specific_extensions_per_accessor(this); 188 m_ispex_per_accessor[i]->resize_extensions(); 189 } 190} 191 192instance_specific_extension_container:: 193 ~instance_specific_extension_container() 194{ 195 for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) 196 delete m_ispex_per_accessor[i]; 197} 198 199void 200instance_specific_extension_container::inc_use_count() 201{ 202 use_count++; 203} 204 205void 206instance_specific_extension_container::dec_use_count() 207{ 208 if ((--use_count) == 0) { 209 // If this container isn't used any more we release the carrier 210 // extension. 211 m_release_fn(m_carrier, m_txn); 212 // We send it back to our pool. 213 instance_specific_extension_container_pool::instance().free(this); 214 } 215} 216 217instance_specific_extensions_per_accessor * 218instance_specific_extension_container::get_accessor(unsigned int idx) 219{ 220 return m_ispex_per_accessor[idx]; 221} 222 223// ---------------------------------------------------------------------------- 224 225// non-templatized version with manual index: 226ispex_base * 227instance_specific_extensions_per_accessor::set_extension( 228 unsigned int index, ispex_base *ext) 229{ 230 resize_extensions(); 231 ispex_base *tmp = m_extensions[index]; 232 m_extensions[index] = ext; 233 if (!tmp && ext) 234 m_container->inc_use_count(); 235 return tmp; 236} 237 238ispex_base * 239instance_specific_extensions_per_accessor::get_extension( 240 unsigned int index) const 241{ 242 return (index < m_extensions.size()) ? m_extensions[index] : nullptr; 243} 244 245void 246instance_specific_extensions_per_accessor::clear_extension(unsigned int index) 247{ 248 if (index < m_extensions.size()) { 249 if (m_extensions[index]) 250 m_container->dec_use_count(); 251 m_extensions[index] = static_cast<ispex_base *>(nullptr); 252 } 253} 254 255void 256instance_specific_extensions_per_accessor::resize_extensions() 257{ 258 m_extensions.expand(ispex_registry::max_num_extensions()); 259} 260 261// ---------------------------------------------------------------------------- 262 263instance_specific_extension_accessor::instance_specific_extension_accessor() : 264 m_index(max_num_ispex_accessors(true) - 1) 265{} 266 267} // namespace tlm_utils | 24#include <typeindex> 25 26namespace tlm 27{ 28 29template class tlm_array<tlm_utils::ispex_base *>; 30 31} // namespace tlm 32 33namespace tlm_utils 34{ 35 36namespace 37{ 38 39class ispex_registry // Copied from tlm_gp.cpp. 40{ 41 typedef unsigned int key_type; 42 typedef std::map<std::type_index, key_type> type_map; 43 44 public: 45 static ispex_registry & 46 instance() 47 { 48 if (!instance_) { 49 // Don't cleanup registry. 50 instance_ = new ispex_registry(); 51 } 52 return *instance_; 53 } 54 55 unsigned int 56 register_extension(std::type_index type) 57 { 58 type_map::const_iterator it = ids_.find(type); 59 60 if (it == ids_.end()) { 61 // New extension - generate/store ID. 62 type_map::value_type v(type, static_cast<key_type>(ids_.size())); 63 ids_.insert(v); 64 return v.second; 65 } 66 return it->second; 67 } 68 69 static unsigned int 70 max_num_extensions() 71 { 72 return (instance_) ? instance().ids_.size() : 0; 73 } 74 75 private: 76 static ispex_registry *instance_; 77 type_map ids_; 78 ispex_registry() {} 79}; 80 81ispex_registry *ispex_registry::instance_ = nullptr; 82 83} // anonymous namespace 84 85unsigned int 86ispex_base::register_private_extension(const std::type_info &type) 87{ 88 return ispex_registry::instance().register_extension(type); 89} 90 91// Helper to do the numbering of private extension accessors. 92static unsigned int 93max_num_ispex_accessors(bool increment=false) 94{ 95 static unsigned int max_num = 0; 96 if (increment) 97 ++max_num; 98 return max_num; 99} 100 101// ---------------------------------------------------------------------------- 102 103// The pool for the container, plain as can be. 104class instance_specific_extension_container_pool 105{ 106 instance_specific_extension_container_pool() : unused(nullptr) {} 107 ~instance_specific_extension_container_pool(); 108 109 public: 110 static instance_specific_extension_container_pool & 111 instance() 112 { 113 static instance_specific_extension_container_pool inst; 114 return inst; 115 } 116 117 instance_specific_extension_container *create(); 118 void free(instance_specific_extension_container *); 119 120 private: 121 instance_specific_extension_container *unused; 122}; 123 124instance_specific_extension_container * 125instance_specific_extension_container_pool::create() 126{ 127 if (!unused) { 128 unused = new instance_specific_extension_container(); 129 } 130 instance_specific_extension_container *tmp = unused; 131 unused = unused->next; 132 return tmp; 133} 134 135void 136instance_specific_extension_container_pool::free( 137 instance_specific_extension_container *cont) 138{ 139 cont->next = unused; 140 unused = cont; 141} 142 143instance_specific_extension_container_pool:: 144 ~instance_specific_extension_container_pool() 145{ 146 while (unused) { 147 instance_specific_extension_container *tmp = unused; 148 unused = unused->next; 149 delete tmp; 150 } 151} 152 153// ---------------------------------------------------------------------------- 154 155instance_specific_extension_container * 156instance_specific_extension_container::create() 157{ 158 return instance_specific_extension_container_pool::instance().create(); 159} 160 161instance_specific_extension_container:: 162 instance_specific_extension_container() : 163 use_count(0), m_txn(NULL), m_release_fn(NULL), m_carrier(NULL), next(NULL) 164{ 165 resize(); 166} 167 168void 169instance_specific_extension_container:: 170 attach_carrier(instance_specific_extension_carrier *carrier, 171 void *txn, release_fn *rel_fn) 172{ 173 m_txn = txn; 174 m_release_fn = rel_fn; 175 m_carrier = carrier; 176} 177 178void 179instance_specific_extension_container::resize() 180{ 181 m_ispex_per_accessor.resize(max_num_ispex_accessors()); 182 183 for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) { 184 m_ispex_per_accessor[i] = 185 new instance_specific_extensions_per_accessor(this); 186 m_ispex_per_accessor[i]->resize_extensions(); 187 } 188} 189 190instance_specific_extension_container:: 191 ~instance_specific_extension_container() 192{ 193 for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) 194 delete m_ispex_per_accessor[i]; 195} 196 197void 198instance_specific_extension_container::inc_use_count() 199{ 200 use_count++; 201} 202 203void 204instance_specific_extension_container::dec_use_count() 205{ 206 if ((--use_count) == 0) { 207 // If this container isn't used any more we release the carrier 208 // extension. 209 m_release_fn(m_carrier, m_txn); 210 // We send it back to our pool. 211 instance_specific_extension_container_pool::instance().free(this); 212 } 213} 214 215instance_specific_extensions_per_accessor * 216instance_specific_extension_container::get_accessor(unsigned int idx) 217{ 218 return m_ispex_per_accessor[idx]; 219} 220 221// ---------------------------------------------------------------------------- 222 223// non-templatized version with manual index: 224ispex_base * 225instance_specific_extensions_per_accessor::set_extension( 226 unsigned int index, ispex_base *ext) 227{ 228 resize_extensions(); 229 ispex_base *tmp = m_extensions[index]; 230 m_extensions[index] = ext; 231 if (!tmp && ext) 232 m_container->inc_use_count(); 233 return tmp; 234} 235 236ispex_base * 237instance_specific_extensions_per_accessor::get_extension( 238 unsigned int index) const 239{ 240 return (index < m_extensions.size()) ? m_extensions[index] : nullptr; 241} 242 243void 244instance_specific_extensions_per_accessor::clear_extension(unsigned int index) 245{ 246 if (index < m_extensions.size()) { 247 if (m_extensions[index]) 248 m_container->dec_use_count(); 249 m_extensions[index] = static_cast<ispex_base *>(nullptr); 250 } 251} 252 253void 254instance_specific_extensions_per_accessor::resize_extensions() 255{ 256 m_extensions.expand(ispex_registry::max_num_extensions()); 257} 258 259// ---------------------------------------------------------------------------- 260 261instance_specific_extension_accessor::instance_specific_extension_accessor() : 262 m_index(max_num_ispex_accessors(true) - 1) 263{} 264 265} // namespace tlm_utils |