instance_specific_extensions.cc revision 13523
113514Sgabeblack@google.com/*****************************************************************************
213514Sgabeblack@google.com
313514Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
413514Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
513514Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
613514Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
713514Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
813514Sgabeblack@google.com  License.  You may obtain a copy of the License at
913514Sgabeblack@google.com
1013514Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1113514Sgabeblack@google.com
1213514Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1313514Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1413514Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1513514Sgabeblack@google.com  implied.  See the License for the specific language governing
1613514Sgabeblack@google.com  permissions and limitations under the License.
1713514Sgabeblack@google.com
1813514Sgabeblack@google.com *****************************************************************************/
1913514Sgabeblack@google.com
2013514Sgabeblack@google.com#include <tlm_utils/instance_specific_extensions_int.h>
2113514Sgabeblack@google.com
2213514Sgabeblack@google.com#include <iostream>
2313514Sgabeblack@google.com#include <map>
2413514Sgabeblack@google.com#include <systemc>
2513514Sgabeblack@google.com#include <tlm>
2613523Sgabeblack@google.com#include <typeindex>
2713514Sgabeblack@google.com
2813514Sgabeblack@google.comnamespace tlm
2913514Sgabeblack@google.com{
3013514Sgabeblack@google.com
3113514Sgabeblack@google.comtemplate class tlm_array<tlm_utils::ispex_base *>;
3213514Sgabeblack@google.com
3313514Sgabeblack@google.com} // namespace tlm
3413514Sgabeblack@google.com
3513514Sgabeblack@google.comnamespace tlm_utils
3613514Sgabeblack@google.com{
3713514Sgabeblack@google.com
3813514Sgabeblack@google.comnamespace
3913514Sgabeblack@google.com{
4013514Sgabeblack@google.com
4113514Sgabeblack@google.comclass ispex_registry // Copied from tlm_gp.cpp.
4213514Sgabeblack@google.com{
4313514Sgabeblack@google.com    typedef unsigned int key_type;
4413523Sgabeblack@google.com    typedef std::map<std::type_index, key_type> type_map;
4513514Sgabeblack@google.com
4613514Sgabeblack@google.com  public:
4713514Sgabeblack@google.com    static ispex_registry &
4813514Sgabeblack@google.com    instance()
4913514Sgabeblack@google.com    {
5013514Sgabeblack@google.com        if (!instance_) {
5113514Sgabeblack@google.com            // Don't cleanup registry.
5213514Sgabeblack@google.com            instance_ = new ispex_registry();
5313514Sgabeblack@google.com        }
5413514Sgabeblack@google.com        return *instance_;
5513514Sgabeblack@google.com    }
5613514Sgabeblack@google.com
5713514Sgabeblack@google.com    unsigned int
5813523Sgabeblack@google.com    register_extension(std::type_index type)
5913514Sgabeblack@google.com    {
6013514Sgabeblack@google.com        type_map::const_iterator it = ids_.find(type);
6113514Sgabeblack@google.com
6213514Sgabeblack@google.com        if (it == ids_.end()) {
6313514Sgabeblack@google.com            // New extension - generate/store ID.
6413514Sgabeblack@google.com            type_map::value_type v(type, static_cast<key_type>(ids_.size()));
6513514Sgabeblack@google.com            ids_.insert(v);
6613514Sgabeblack@google.com            return v.second;
6713514Sgabeblack@google.com        }
6813514Sgabeblack@google.com        return it->second;
6913514Sgabeblack@google.com    }
7013514Sgabeblack@google.com
7113514Sgabeblack@google.com    static unsigned int
7213514Sgabeblack@google.com    max_num_extensions()
7313514Sgabeblack@google.com    {
7413514Sgabeblack@google.com        return (instance_) ? instance().ids_.size() : 0;
7513514Sgabeblack@google.com    }
7613514Sgabeblack@google.com
7713514Sgabeblack@google.com  private:
7813514Sgabeblack@google.com    static ispex_registry *instance_;
7913514Sgabeblack@google.com    type_map ids_;
8013514Sgabeblack@google.com    ispex_registry() {}
8113514Sgabeblack@google.com};
8213514Sgabeblack@google.com
8313514Sgabeblack@google.comispex_registry *ispex_registry::instance_ = nullptr;
8413514Sgabeblack@google.com
8513514Sgabeblack@google.com} //  anonymous namespace
8613514Sgabeblack@google.com
8713514Sgabeblack@google.comunsigned int
8813514Sgabeblack@google.comispex_base::register_private_extension(const std::type_info &type)
8913514Sgabeblack@google.com{
9013514Sgabeblack@google.com    return ispex_registry::instance().register_extension(type);
9113514Sgabeblack@google.com}
9213514Sgabeblack@google.com
9313514Sgabeblack@google.com// Helper to do the numbering of private extension accessors.
9413514Sgabeblack@google.comstatic unsigned int
9513514Sgabeblack@google.commax_num_ispex_accessors(bool increment=false)
9613514Sgabeblack@google.com{
9713514Sgabeblack@google.com    static unsigned int max_num = 0;
9813514Sgabeblack@google.com    if (increment)
9913514Sgabeblack@google.com        ++max_num;
10013514Sgabeblack@google.com    return max_num;
10113514Sgabeblack@google.com}
10213514Sgabeblack@google.com
10313514Sgabeblack@google.com// ----------------------------------------------------------------------------
10413514Sgabeblack@google.com
10513514Sgabeblack@google.com// The pool for the container, plain as can be.
10613514Sgabeblack@google.comclass instance_specific_extension_container_pool
10713514Sgabeblack@google.com{
10813514Sgabeblack@google.com    instance_specific_extension_container_pool() : unused(nullptr) {}
10913514Sgabeblack@google.com    ~instance_specific_extension_container_pool();
11013514Sgabeblack@google.com
11113514Sgabeblack@google.com  public:
11213514Sgabeblack@google.com    static instance_specific_extension_container_pool &
11313514Sgabeblack@google.com    instance()
11413514Sgabeblack@google.com    {
11513514Sgabeblack@google.com        static instance_specific_extension_container_pool inst;
11613514Sgabeblack@google.com        return inst;
11713514Sgabeblack@google.com    }
11813514Sgabeblack@google.com
11913514Sgabeblack@google.com    instance_specific_extension_container *create();
12013514Sgabeblack@google.com    void free(instance_specific_extension_container *);
12113514Sgabeblack@google.com
12213514Sgabeblack@google.com  private:
12313514Sgabeblack@google.com    instance_specific_extension_container *unused;
12413514Sgabeblack@google.com};
12513514Sgabeblack@google.com
12613514Sgabeblack@google.cominstance_specific_extension_container *
12713514Sgabeblack@google.cominstance_specific_extension_container_pool::create()
12813514Sgabeblack@google.com{
12913514Sgabeblack@google.com    if (!unused) {
13013514Sgabeblack@google.com        unused = new instance_specific_extension_container();
13113514Sgabeblack@google.com    }
13213514Sgabeblack@google.com    instance_specific_extension_container *tmp = unused;
13313514Sgabeblack@google.com    unused = unused->next;
13413514Sgabeblack@google.com    return tmp;
13513514Sgabeblack@google.com}
13613514Sgabeblack@google.com
13713514Sgabeblack@google.comvoid
13813514Sgabeblack@google.cominstance_specific_extension_container_pool::free(
13913514Sgabeblack@google.com        instance_specific_extension_container *cont)
14013514Sgabeblack@google.com{
14113514Sgabeblack@google.com    cont->next = unused;
14213514Sgabeblack@google.com    unused = cont;
14313514Sgabeblack@google.com}
14413514Sgabeblack@google.com
14513514Sgabeblack@google.cominstance_specific_extension_container_pool::
14613514Sgabeblack@google.com    ~instance_specific_extension_container_pool()
14713514Sgabeblack@google.com{
14813514Sgabeblack@google.com    while (unused) {
14913514Sgabeblack@google.com        instance_specific_extension_container *tmp = unused;
15013514Sgabeblack@google.com        unused = unused->next;
15113514Sgabeblack@google.com        delete tmp;
15213514Sgabeblack@google.com    }
15313514Sgabeblack@google.com}
15413514Sgabeblack@google.com
15513514Sgabeblack@google.com// ----------------------------------------------------------------------------
15613514Sgabeblack@google.com
15713514Sgabeblack@google.cominstance_specific_extension_container *
15813514Sgabeblack@google.cominstance_specific_extension_container::create()
15913514Sgabeblack@google.com{
16013514Sgabeblack@google.com    return instance_specific_extension_container_pool::instance().create();
16113514Sgabeblack@google.com}
16213514Sgabeblack@google.com
16313514Sgabeblack@google.cominstance_specific_extension_container::
16413514Sgabeblack@google.com    instance_specific_extension_container() :
16513514Sgabeblack@google.com    use_count(0), m_txn(NULL), m_release_fn(NULL), m_carrier(NULL), next(NULL)
16613514Sgabeblack@google.com{
16713514Sgabeblack@google.com    resize();
16813514Sgabeblack@google.com}
16913514Sgabeblack@google.com
17013514Sgabeblack@google.comvoid
17113514Sgabeblack@google.cominstance_specific_extension_container::
17213514Sgabeblack@google.com    attach_carrier(instance_specific_extension_carrier *carrier,
17313514Sgabeblack@google.com            void *txn, release_fn *rel_fn)
17413514Sgabeblack@google.com{
17513514Sgabeblack@google.com    m_txn = txn;
17613514Sgabeblack@google.com    m_release_fn = rel_fn;
17713514Sgabeblack@google.com    m_carrier = carrier;
17813514Sgabeblack@google.com}
17913514Sgabeblack@google.com
18013514Sgabeblack@google.comvoid
18113514Sgabeblack@google.cominstance_specific_extension_container::resize()
18213514Sgabeblack@google.com{
18313514Sgabeblack@google.com    m_ispex_per_accessor.resize(max_num_ispex_accessors());
18413514Sgabeblack@google.com
18513514Sgabeblack@google.com    for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i) {
18613514Sgabeblack@google.com        m_ispex_per_accessor[i] =
18713514Sgabeblack@google.com            new instance_specific_extensions_per_accessor(this);
18813514Sgabeblack@google.com        m_ispex_per_accessor[i]->resize_extensions();
18913514Sgabeblack@google.com    }
19013514Sgabeblack@google.com}
19113514Sgabeblack@google.com
19213514Sgabeblack@google.cominstance_specific_extension_container::
19313514Sgabeblack@google.com    ~instance_specific_extension_container()
19413514Sgabeblack@google.com{
19513514Sgabeblack@google.com    for (unsigned int i = 0; i < m_ispex_per_accessor.size(); ++i)
19613514Sgabeblack@google.com        delete m_ispex_per_accessor[i];
19713514Sgabeblack@google.com}
19813514Sgabeblack@google.com
19913514Sgabeblack@google.comvoid
20013514Sgabeblack@google.cominstance_specific_extension_container::inc_use_count()
20113514Sgabeblack@google.com{
20213514Sgabeblack@google.com    use_count++;
20313514Sgabeblack@google.com}
20413514Sgabeblack@google.com
20513514Sgabeblack@google.comvoid
20613514Sgabeblack@google.cominstance_specific_extension_container::dec_use_count()
20713514Sgabeblack@google.com{
20813514Sgabeblack@google.com    if ((--use_count) == 0) {
20913514Sgabeblack@google.com        // If this container isn't used any more we release the carrier
21013514Sgabeblack@google.com        // extension.
21113514Sgabeblack@google.com        m_release_fn(m_carrier, m_txn);
21213514Sgabeblack@google.com        // We send it back to our pool.
21313514Sgabeblack@google.com        instance_specific_extension_container_pool::instance().free(this);
21413514Sgabeblack@google.com    }
21513514Sgabeblack@google.com}
21613514Sgabeblack@google.com
21713514Sgabeblack@google.cominstance_specific_extensions_per_accessor *
21813514Sgabeblack@google.cominstance_specific_extension_container::get_accessor(unsigned int idx)
21913514Sgabeblack@google.com{
22013514Sgabeblack@google.com    return m_ispex_per_accessor[idx];
22113514Sgabeblack@google.com}
22213514Sgabeblack@google.com
22313514Sgabeblack@google.com// ----------------------------------------------------------------------------
22413514Sgabeblack@google.com
22513514Sgabeblack@google.com// non-templatized version with manual index:
22613514Sgabeblack@google.comispex_base *
22713514Sgabeblack@google.cominstance_specific_extensions_per_accessor::set_extension(
22813514Sgabeblack@google.com        unsigned int index, ispex_base *ext)
22913514Sgabeblack@google.com{
23013514Sgabeblack@google.com    resize_extensions();
23113514Sgabeblack@google.com    ispex_base *tmp = m_extensions[index];
23213514Sgabeblack@google.com    m_extensions[index] = ext;
23313514Sgabeblack@google.com    if (!tmp && ext)
23413514Sgabeblack@google.com        m_container->inc_use_count();
23513514Sgabeblack@google.com    return tmp;
23613514Sgabeblack@google.com}
23713514Sgabeblack@google.com
23813514Sgabeblack@google.comispex_base *
23913514Sgabeblack@google.cominstance_specific_extensions_per_accessor::get_extension(
24013514Sgabeblack@google.com        unsigned int index) const
24113514Sgabeblack@google.com{
24213514Sgabeblack@google.com    return (index < m_extensions.size()) ? m_extensions[index] : nullptr;
24313514Sgabeblack@google.com}
24413514Sgabeblack@google.com
24513514Sgabeblack@google.comvoid
24613514Sgabeblack@google.cominstance_specific_extensions_per_accessor::clear_extension(unsigned int index)
24713514Sgabeblack@google.com{
24813514Sgabeblack@google.com    if (index < m_extensions.size()) {
24913514Sgabeblack@google.com        if (m_extensions[index])
25013514Sgabeblack@google.com            m_container->dec_use_count();
25113514Sgabeblack@google.com        m_extensions[index] = static_cast<ispex_base *>(nullptr);
25213514Sgabeblack@google.com    }
25313514Sgabeblack@google.com}
25413514Sgabeblack@google.com
25513514Sgabeblack@google.comvoid
25613514Sgabeblack@google.cominstance_specific_extensions_per_accessor::resize_extensions()
25713514Sgabeblack@google.com{
25813514Sgabeblack@google.com    m_extensions.expand(ispex_registry::max_num_extensions());
25913514Sgabeblack@google.com}
26013514Sgabeblack@google.com
26113514Sgabeblack@google.com// ----------------------------------------------------------------------------
26213514Sgabeblack@google.com
26313514Sgabeblack@google.cominstance_specific_extension_accessor::instance_specific_extension_accessor() :
26413514Sgabeblack@google.com    m_index(max_num_ispex_accessors(true) - 1)
26513514Sgabeblack@google.com{}
26613514Sgabeblack@google.com
26713514Sgabeblack@google.com} // namespace tlm_utils
268