instance_specific_extensions.cc (13514:75569a60a0be) instance_specific_extensions.cc (13523:de27641700bb)
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>
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>
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;
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;
43 typedef std::map<sc_core::sc_type_index, key_type> type_map;
44 typedef std::map<std::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
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
57 register_extension(sc_core::sc_type_index type)
58 register_extension(std::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
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