113511Sgabeblack@google.com/*****************************************************************************
213511Sgabeblack@google.com
313511Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
413511Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
513511Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
613511Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
713511Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
813511Sgabeblack@google.com  License.  You may obtain a copy of the License at
913511Sgabeblack@google.com
1013511Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1113511Sgabeblack@google.com
1213511Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1313511Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1413511Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1513511Sgabeblack@google.com  implied.  See the License for the specific language governing
1613511Sgabeblack@google.com  permissions and limitations under the License.
1713511Sgabeblack@google.com
1813511Sgabeblack@google.com *****************************************************************************/
1913513Sgabeblack@google.com#ifndef __SYSTEMC_EXT_TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_INT_H__
2013513Sgabeblack@google.com#define __SYSTEMC_EXT_TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_INT_H__
2113511Sgabeblack@google.com
2213586Sgabeblack@google.com#include <vector>
2313586Sgabeblack@google.com
2413586Sgabeblack@google.com#include "../tlm_core/2/generic_payload/array.hh"
2513511Sgabeblack@google.com
2613513Sgabeblack@google.comnamespace tlm_utils
2713513Sgabeblack@google.com{
2813513Sgabeblack@google.com
2913513Sgabeblack@google.comclass ispex_base;
3013513Sgabeblack@google.comclass instance_specific_extension_accessor;
3113513Sgabeblack@google.comclass instance_specific_extension_container;
3213511Sgabeblack@google.comclass instance_specific_extension_carrier;
3313511Sgabeblack@google.comclass instance_specific_extension_container_pool;
3413511Sgabeblack@google.com
3513513Sgabeblack@google.com} // namespace tlm_utils
3613513Sgabeblack@google.com
3713513Sgabeblack@google.comnamespace tlm
3813513Sgabeblack@google.com{
3913513Sgabeblack@google.com
4013513Sgabeblack@google.comextern template class tlm_array<tlm_utils::ispex_base *>;
4113513Sgabeblack@google.com
4213511Sgabeblack@google.com} // namespace tlm
4313511Sgabeblack@google.com
4413513Sgabeblack@google.comnamespace tlm_utils
4513513Sgabeblack@google.com{
4613511Sgabeblack@google.com
4713513Sgabeblack@google.com// The private extension base. Similar to normal extension base, but without
4813513Sgabeblack@google.com// clone and free.
4913513Sgabeblack@google.comclass ispex_base
5013511Sgabeblack@google.com{
5113511Sgabeblack@google.com    friend class tlm::tlm_array<ispex_base*>;
5213513Sgabeblack@google.com    void free() {} // Needed for explicit tlm_array instantiation.
5313513Sgabeblack@google.com
5413513Sgabeblack@google.com  public:
5513511Sgabeblack@google.com    virtual ~ispex_base() {}
5613513Sgabeblack@google.com
5713513Sgabeblack@google.com  protected:
5813513Sgabeblack@google.com    static unsigned int register_private_extension(const std::type_info &);
5913511Sgabeblack@google.com};
6013511Sgabeblack@google.com
6113513Sgabeblack@google.com// This thing is basically a snippet of the generic_payload.
6213513Sgabeblack@google.com// It contains all the extension specific code (the extension API so to speak)
6313511Sgabeblack@google.com// the differences are:
6413513Sgabeblack@google.com// - it calls back to its owner whenever a real (==non-NULL) extension gets
6513513Sgabeblack@google.com// set for the first time.
6613513Sgabeblack@google.com// - it calls back to its owner whenever a living (==non-NULL) extension gets
6713513Sgabeblack@google.com// cleared.
6813513Sgabeblack@google.comclass instance_specific_extensions_per_accessor
6913511Sgabeblack@google.com{
7013513Sgabeblack@google.com  public:
7113513Sgabeblack@google.com    typedef instance_specific_extension_container container_type;
7213511Sgabeblack@google.com
7313513Sgabeblack@google.com    explicit
7413513Sgabeblack@google.com    instance_specific_extensions_per_accessor(container_type *container) :
7513513Sgabeblack@google.com        m_container(container)
7613513Sgabeblack@google.com    {}
7713511Sgabeblack@google.com
7813513Sgabeblack@google.com    template <typename T>
7913513Sgabeblack@google.com    T *
8013513Sgabeblack@google.com    set_extension(T *ext)
8113513Sgabeblack@google.com    {
8213513Sgabeblack@google.com        return static_cast<T *>(set_extension(T::priv_id, ext));
8313513Sgabeblack@google.com    }
8413511Sgabeblack@google.com
8513513Sgabeblack@google.com    // Non-templatized version with manual index:
8613513Sgabeblack@google.com    ispex_base *set_extension(unsigned int index, ispex_base *ext);
8713511Sgabeblack@google.com
8813513Sgabeblack@google.com    // Check for an extension, ext will be nullptr if not present.
8913513Sgabeblack@google.com    template <typename T>
9013513Sgabeblack@google.com    void get_extension(T *& ext) const
9113513Sgabeblack@google.com    {
9213513Sgabeblack@google.com        ext = static_cast<T *>(get_extension(T::priv_id));
9313513Sgabeblack@google.com    }
9413513Sgabeblack@google.com    // Non-templatized version:
9513513Sgabeblack@google.com    ispex_base *get_extension(unsigned int index) const;
9613511Sgabeblack@google.com
9713513Sgabeblack@google.com    // Clear extension, the argument is needed to find the right index:
9813513Sgabeblack@google.com    template <typename T>
9913513Sgabeblack@google.com    void clear_extension(const T *)
10013513Sgabeblack@google.com    {
10113513Sgabeblack@google.com        clear_extension(T::priv_id);
10213513Sgabeblack@google.com    }
10313511Sgabeblack@google.com
10413513Sgabeblack@google.com    // Non-templatized version with manual index
10513513Sgabeblack@google.com    void clear_extension(unsigned int index);
10613511Sgabeblack@google.com
10713513Sgabeblack@google.com    // Make sure the extension array is large enough. Can be called once by
10813513Sgabeblack@google.com    // an initiator module (before issuing the first transaction) to make
10913513Sgabeblack@google.com    // sure that the extension array is of correct size. This is only needed
11013513Sgabeblack@google.com    // if the initiator cannot guarantee that the generic payload object is
11113513Sgabeblack@google.com    // allocated after C++ static construction time.
11213513Sgabeblack@google.com    void resize_extensions();
11313511Sgabeblack@google.com
11413513Sgabeblack@google.com  private:
11513513Sgabeblack@google.com    tlm::tlm_array<ispex_base *> m_extensions;
11613513Sgabeblack@google.com    container_type* m_container;
11713513Sgabeblack@google.com};
11813511Sgabeblack@google.com
11913513Sgabeblack@google.com// This thing contains the vector of extensions per accessor
12013513Sgabeblack@google.com// which can be really large so this one should be pool allocated.
12113513Sgabeblack@google.com// Therefore it keeps a use_count of itself to automatically free itself.
12213513Sgabeblack@google.com// - to this end it provides callbacks to the extensions per accessor
12313513Sgabeblack@google.com//   to increment and decrement the use_count.
12413513Sgabeblack@google.comclass instance_specific_extension_container
12513513Sgabeblack@google.com{
12613513Sgabeblack@google.com    friend class instance_specific_extension_accessor;
12713513Sgabeblack@google.com    friend class instance_specific_extension_carrier;
12813513Sgabeblack@google.com    friend class instance_specific_extension_container_pool;
12913513Sgabeblack@google.com    friend class instance_specific_extensions_per_accessor;
13013511Sgabeblack@google.com
13113513Sgabeblack@google.com    typedef void release_fn(instance_specific_extension_carrier *, void *);
13213511Sgabeblack@google.com
13313513Sgabeblack@google.com    instance_specific_extension_container();
13413513Sgabeblack@google.com    ~instance_specific_extension_container();
13513511Sgabeblack@google.com
13613513Sgabeblack@google.com    void resize();
13713511Sgabeblack@google.com
13813513Sgabeblack@google.com    void inc_use_count();
13913513Sgabeblack@google.com    void dec_use_count();
14013511Sgabeblack@google.com
14113513Sgabeblack@google.com    static instance_specific_extension_container *create();
14213513Sgabeblack@google.com    void attach_carrier(
14313513Sgabeblack@google.com            instance_specific_extension_carrier *, void *txn, release_fn *);
14413511Sgabeblack@google.com
14513513Sgabeblack@google.com    instance_specific_extensions_per_accessor *
14613513Sgabeblack@google.com        get_accessor(unsigned int index);
14713511Sgabeblack@google.com
14813513Sgabeblack@google.com    std::vector<instance_specific_extensions_per_accessor *>
14913513Sgabeblack@google.com        m_ispex_per_accessor;
15013513Sgabeblack@google.com    unsigned int use_count;
15113513Sgabeblack@google.com    void *m_txn;
15213513Sgabeblack@google.com    release_fn *m_release_fn;
15313513Sgabeblack@google.com    instance_specific_extension_carrier *m_carrier;
15413513Sgabeblack@google.com    instance_specific_extension_container *next; // For pooling.
15513513Sgabeblack@google.com};
15613511Sgabeblack@google.com
15713511Sgabeblack@google.com// ----------------------------------------------------------------------------
15813511Sgabeblack@google.com
15913513Sgabeblack@google.com// This class 'hides' all the instance specific extension stuff from the user.
16013513Sgabeblack@google.com// They instantiates one of those (e.g. instance_specific_extension_accessor
16113513Sgabeblack@google.com// extAcc;) and can then access the private extensions.
16213511Sgabeblack@google.com//    extAcc(txn).extensionAPIFnCall()
16313513Sgabeblack@google.com// where extensionAPIFnCall is set_extension, get_extension,
16413513Sgabeblack@google.com//      clear_extension,...
16513513Sgabeblack@google.comclass instance_specific_extension_accessor
16613511Sgabeblack@google.com{
16713513Sgabeblack@google.com  public:
16813513Sgabeblack@google.com    instance_specific_extension_accessor();
16913511Sgabeblack@google.com
17013513Sgabeblack@google.com    // Implementation in instance_specific_extensions.h
17113513Sgabeblack@google.com    template <typename T>
17213513Sgabeblack@google.com    inline instance_specific_extensions_per_accessor &operator () (T &txn);
17313511Sgabeblack@google.com
17413513Sgabeblack@google.com  protected:
17513513Sgabeblack@google.com    template<typename T>
17613513Sgabeblack@google.com    static void release_carrier(
17713513Sgabeblack@google.com            instance_specific_extension_carrier *, void * txn);
17813511Sgabeblack@google.com
17913513Sgabeblack@google.com    unsigned int m_index;
18013513Sgabeblack@google.com};
18113511Sgabeblack@google.com
18213511Sgabeblack@google.com} // namespace tlm_utils
18313513Sgabeblack@google.com
18413513Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_INT_H__ */
185