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