instance_specific_extensions_int.h revision 13513
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
2213511Sgabeblack@google.com#include <tlm>
2313511Sgabeblack@google.com
2413513Sgabeblack@google.comnamespace tlm_utils
2513513Sgabeblack@google.com{
2613513Sgabeblack@google.com
2713513Sgabeblack@google.comclass ispex_base;
2813513Sgabeblack@google.comclass instance_specific_extension_accessor;
2913513Sgabeblack@google.comclass instance_specific_extension_container;
3013511Sgabeblack@google.comclass instance_specific_extension_carrier;
3113511Sgabeblack@google.comclass instance_specific_extension_container_pool;
3213511Sgabeblack@google.com
3313513Sgabeblack@google.com} // namespace tlm_utils
3413513Sgabeblack@google.com
3513513Sgabeblack@google.comnamespace tlm
3613513Sgabeblack@google.com{
3713513Sgabeblack@google.com
3813513Sgabeblack@google.comextern template class tlm_array<tlm_utils::ispex_base *>;
3913513Sgabeblack@google.com
4013511Sgabeblack@google.com} // namespace tlm
4113511Sgabeblack@google.com
4213513Sgabeblack@google.comnamespace tlm_utils
4313513Sgabeblack@google.com{
4413511Sgabeblack@google.com
4513513Sgabeblack@google.com// The private extension base. Similar to normal extension base, but without
4613513Sgabeblack@google.com// clone and free.
4713513Sgabeblack@google.comclass ispex_base
4813511Sgabeblack@google.com{
4913511Sgabeblack@google.com    friend class tlm::tlm_array<ispex_base*>;
5013513Sgabeblack@google.com    void free() {} // Needed for explicit tlm_array instantiation.
5113513Sgabeblack@google.com
5213513Sgabeblack@google.com  public:
5313511Sgabeblack@google.com    virtual ~ispex_base() {}
5413513Sgabeblack@google.com
5513513Sgabeblack@google.com  protected:
5613513Sgabeblack@google.com    static unsigned int register_private_extension(const std::type_info &);
5713511Sgabeblack@google.com};
5813511Sgabeblack@google.com
5913513Sgabeblack@google.com// This thing is basically a snippet of the generic_payload.
6013513Sgabeblack@google.com// It contains all the extension specific code (the extension API so to speak)
6113511Sgabeblack@google.com// the differences are:
6213513Sgabeblack@google.com// - it calls back to its owner whenever a real (==non-NULL) extension gets
6313513Sgabeblack@google.com// set for the first time.
6413513Sgabeblack@google.com// - it calls back to its owner whenever a living (==non-NULL) extension gets
6513513Sgabeblack@google.com// cleared.
6613513Sgabeblack@google.comclass instance_specific_extensions_per_accessor
6713511Sgabeblack@google.com{
6813513Sgabeblack@google.com  public:
6913513Sgabeblack@google.com    typedef instance_specific_extension_container container_type;
7013511Sgabeblack@google.com
7113513Sgabeblack@google.com    explicit
7213513Sgabeblack@google.com    instance_specific_extensions_per_accessor(container_type *container) :
7313513Sgabeblack@google.com        m_container(container)
7413513Sgabeblack@google.com    {}
7513511Sgabeblack@google.com
7613513Sgabeblack@google.com    template <typename T>
7713513Sgabeblack@google.com    T *
7813513Sgabeblack@google.com    set_extension(T *ext)
7913513Sgabeblack@google.com    {
8013513Sgabeblack@google.com        return static_cast<T *>(set_extension(T::priv_id, ext));
8113513Sgabeblack@google.com    }
8213511Sgabeblack@google.com
8313513Sgabeblack@google.com    // Non-templatized version with manual index:
8413513Sgabeblack@google.com    ispex_base *set_extension(unsigned int index, ispex_base *ext);
8513511Sgabeblack@google.com
8613513Sgabeblack@google.com    // Check for an extension, ext will be nullptr if not present.
8713513Sgabeblack@google.com    template <typename T>
8813513Sgabeblack@google.com    void get_extension(T *& ext) const
8913513Sgabeblack@google.com    {
9013513Sgabeblack@google.com        ext = static_cast<T *>(get_extension(T::priv_id));
9113513Sgabeblack@google.com    }
9213513Sgabeblack@google.com    // Non-templatized version:
9313513Sgabeblack@google.com    ispex_base *get_extension(unsigned int index) const;
9413511Sgabeblack@google.com
9513513Sgabeblack@google.com    // Clear extension, the argument is needed to find the right index:
9613513Sgabeblack@google.com    template <typename T>
9713513Sgabeblack@google.com    void clear_extension(const T *)
9813513Sgabeblack@google.com    {
9913513Sgabeblack@google.com        clear_extension(T::priv_id);
10013513Sgabeblack@google.com    }
10113511Sgabeblack@google.com
10213513Sgabeblack@google.com    // Non-templatized version with manual index
10313513Sgabeblack@google.com    void clear_extension(unsigned int index);
10413511Sgabeblack@google.com
10513513Sgabeblack@google.com    // Make sure the extension array is large enough. Can be called once by
10613513Sgabeblack@google.com    // an initiator module (before issuing the first transaction) to make
10713513Sgabeblack@google.com    // sure that the extension array is of correct size. This is only needed
10813513Sgabeblack@google.com    // if the initiator cannot guarantee that the generic payload object is
10913513Sgabeblack@google.com    // allocated after C++ static construction time.
11013513Sgabeblack@google.com    void resize_extensions();
11113511Sgabeblack@google.com
11213513Sgabeblack@google.com  private:
11313513Sgabeblack@google.com    tlm::tlm_array<ispex_base *> m_extensions;
11413513Sgabeblack@google.com    container_type* m_container;
11513513Sgabeblack@google.com};
11613511Sgabeblack@google.com
11713513Sgabeblack@google.com// This thing contains the vector of extensions per accessor
11813513Sgabeblack@google.com// which can be really large so this one should be pool allocated.
11913513Sgabeblack@google.com// Therefore it keeps a use_count of itself to automatically free itself.
12013513Sgabeblack@google.com// - to this end it provides callbacks to the extensions per accessor
12113513Sgabeblack@google.com//   to increment and decrement the use_count.
12213513Sgabeblack@google.comclass instance_specific_extension_container
12313513Sgabeblack@google.com{
12413513Sgabeblack@google.com    friend class instance_specific_extension_accessor;
12513513Sgabeblack@google.com    friend class instance_specific_extension_carrier;
12613513Sgabeblack@google.com    friend class instance_specific_extension_container_pool;
12713513Sgabeblack@google.com    friend class instance_specific_extensions_per_accessor;
12813511Sgabeblack@google.com
12913513Sgabeblack@google.com    typedef void release_fn(instance_specific_extension_carrier *, void *);
13013511Sgabeblack@google.com
13113513Sgabeblack@google.com    instance_specific_extension_container();
13213513Sgabeblack@google.com    ~instance_specific_extension_container();
13313511Sgabeblack@google.com
13413513Sgabeblack@google.com    void resize();
13513511Sgabeblack@google.com
13613513Sgabeblack@google.com    void inc_use_count();
13713513Sgabeblack@google.com    void dec_use_count();
13813511Sgabeblack@google.com
13913513Sgabeblack@google.com    static instance_specific_extension_container *create();
14013513Sgabeblack@google.com    void attach_carrier(
14113513Sgabeblack@google.com            instance_specific_extension_carrier *, void *txn, release_fn *);
14213511Sgabeblack@google.com
14313513Sgabeblack@google.com    instance_specific_extensions_per_accessor *
14413513Sgabeblack@google.com        get_accessor(unsigned int index);
14513511Sgabeblack@google.com
14613513Sgabeblack@google.com    std::vector<instance_specific_extensions_per_accessor *>
14713513Sgabeblack@google.com        m_ispex_per_accessor;
14813513Sgabeblack@google.com    unsigned int use_count;
14913513Sgabeblack@google.com    void *m_txn;
15013513Sgabeblack@google.com    release_fn *m_release_fn;
15113513Sgabeblack@google.com    instance_specific_extension_carrier *m_carrier;
15213513Sgabeblack@google.com    instance_specific_extension_container *next; // For pooling.
15313513Sgabeblack@google.com};
15413511Sgabeblack@google.com
15513511Sgabeblack@google.com// ----------------------------------------------------------------------------
15613511Sgabeblack@google.com
15713513Sgabeblack@google.com// This class 'hides' all the instance specific extension stuff from the user.
15813513Sgabeblack@google.com// They instantiates one of those (e.g. instance_specific_extension_accessor
15913513Sgabeblack@google.com// extAcc;) and can then access the private extensions.
16013511Sgabeblack@google.com//    extAcc(txn).extensionAPIFnCall()
16113513Sgabeblack@google.com// where extensionAPIFnCall is set_extension, get_extension,
16213513Sgabeblack@google.com//      clear_extension,...
16313513Sgabeblack@google.comclass instance_specific_extension_accessor
16413511Sgabeblack@google.com{
16513513Sgabeblack@google.com  public:
16613513Sgabeblack@google.com    instance_specific_extension_accessor();
16713511Sgabeblack@google.com
16813513Sgabeblack@google.com    // Implementation in instance_specific_extensions.h
16913513Sgabeblack@google.com    template <typename T>
17013513Sgabeblack@google.com    inline instance_specific_extensions_per_accessor &operator () (T &txn);
17113511Sgabeblack@google.com
17213513Sgabeblack@google.com  protected:
17313513Sgabeblack@google.com    template<typename T>
17413513Sgabeblack@google.com    static void release_carrier(
17513513Sgabeblack@google.com            instance_specific_extension_carrier *, void * txn);
17613511Sgabeblack@google.com
17713513Sgabeblack@google.com    unsigned int m_index;
17813513Sgabeblack@google.com};
17913511Sgabeblack@google.com
18013511Sgabeblack@google.com} // namespace tlm_utils
18113513Sgabeblack@google.com
18213513Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_INT_H__ */
183