gp.hh revision 13521
111308Santhony.gutierrez@amd.com/*****************************************************************************
211308Santhony.gutierrez@amd.com
311308Santhony.gutierrez@amd.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
411308Santhony.gutierrez@amd.com  more contributor license agreements.  See the NOTICE file distributed
511308Santhony.gutierrez@amd.com  with this work for additional information regarding copyright ownership.
611308Santhony.gutierrez@amd.com  Accellera licenses this file to you under the Apache License, Version 2.0
711308Santhony.gutierrez@amd.com  (the "License"); you may not use this file except in compliance with the
811308Santhony.gutierrez@amd.com  License.  You may obtain a copy of the License at
911308Santhony.gutierrez@amd.com
1011308Santhony.gutierrez@amd.com    http://www.apache.org/licenses/LICENSE-2.0
1111308Santhony.gutierrez@amd.com
1211308Santhony.gutierrez@amd.com  Unless required by applicable law or agreed to in writing, software
1311308Santhony.gutierrez@amd.com  distributed under the License is distributed on an "AS IS" BASIS,
1411308Santhony.gutierrez@amd.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1511308Santhony.gutierrez@amd.com  implied.  See the License for the specific language governing
1611308Santhony.gutierrez@amd.com  permissions and limitations under the License.
1712697Santhony.gutierrez@amd.com
1812697Santhony.gutierrez@amd.com *****************************************************************************/
1912697Santhony.gutierrez@amd.com
2011308Santhony.gutierrez@amd.com#ifndef __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_GP_HH__
2111308Santhony.gutierrez@amd.com#define __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_GP_HH__
2211308Santhony.gutierrez@amd.com
2311308Santhony.gutierrez@amd.com#include <systemc>
2411308Santhony.gutierrez@amd.com#include <typeinfo> // std::type_info
2511308Santhony.gutierrez@amd.com
2611308Santhony.gutierrez@amd.com#include "tlm_core/2/generic_payload/array.hh"
2711308Santhony.gutierrez@amd.com
2811308Santhony.gutierrez@amd.comnamespace tlm
2911308Santhony.gutierrez@amd.com{
3011308Santhony.gutierrez@amd.com
3111308Santhony.gutierrez@amd.comclass tlm_generic_payload;
3211308Santhony.gutierrez@amd.com
3312697Santhony.gutierrez@amd.comclass tlm_mm_interface
3412697Santhony.gutierrez@amd.com{
3511308Santhony.gutierrez@amd.com  public:
3611308Santhony.gutierrez@amd.com    virtual void free(tlm_generic_payload *) = 0;
3711308Santhony.gutierrez@amd.com    virtual ~tlm_mm_interface() {}
3811308Santhony.gutierrez@amd.com};
3911308Santhony.gutierrez@amd.com
4011308Santhony.gutierrez@amd.com//---------------------------------------------------------------------------
4111308Santhony.gutierrez@amd.com// Classes and helpers for the extension mechanism
4211308Santhony.gutierrez@amd.com//---------------------------------------------------------------------------
4311308Santhony.gutierrez@amd.com// Helper function:
4411308Santhony.gutierrez@amd.comunsigned int max_num_extensions();
4511308Santhony.gutierrez@amd.com
4611308Santhony.gutierrez@amd.com// This class can be used for storing pointers to the extension classes, used
4711308Santhony.gutierrez@amd.com// in tlm_generic_payload:
4811308Santhony.gutierrez@amd.comclass tlm_extension_base
4911308Santhony.gutierrez@amd.com{
5011308Santhony.gutierrez@amd.com  public:
5111308Santhony.gutierrez@amd.com    virtual tlm_extension_base *clone() const = 0;
5211308Santhony.gutierrez@amd.com    virtual void free() { delete this; }
5311308Santhony.gutierrez@amd.com    virtual void copy_from(tlm_extension_base const &) = 0;
5411308Santhony.gutierrez@amd.com  protected:
5511308Santhony.gutierrez@amd.com    virtual ~tlm_extension_base() {}
5611308Santhony.gutierrez@amd.com    static unsigned int register_extension(const std::type_info &);
5711308Santhony.gutierrez@amd.com};
5811308Santhony.gutierrez@amd.com
5911308Santhony.gutierrez@amd.com// Base class for all extension classes, derive your extension class in
6011308Santhony.gutierrez@amd.com// the following way:
6111308Santhony.gutierrez@amd.com// class my_extension : public tlm_extension<my_extension> { ...
6211308Santhony.gutierrez@amd.com// This triggers proper extension registration during C++ static
6311308Santhony.gutierrez@amd.com// contruction time. my_extension::ID will hold the unique index in the
6411308Santhony.gutierrez@amd.com// tlm_generic_payload::m_extensions array.
6511308Santhony.gutierrez@amd.comtemplate <typename T>
6611308Santhony.gutierrez@amd.comclass tlm_extension : public tlm_extension_base
6711308Santhony.gutierrez@amd.com{
6811308Santhony.gutierrez@amd.com  public:
6911308Santhony.gutierrez@amd.com    virtual tlm_extension_base *clone() const = 0;
7011308Santhony.gutierrez@amd.com    virtual void copy_from(tlm_extension_base const &ext) = 0;
7111308Santhony.gutierrez@amd.com    virtual ~tlm_extension() {}
7211308Santhony.gutierrez@amd.com    const static unsigned int ID;
7311308Santhony.gutierrez@amd.com};
7411308Santhony.gutierrez@amd.com
7511308Santhony.gutierrez@amd.comtemplate <typename T>
7611308Santhony.gutierrez@amd.comconst unsigned int tlm_extension<T>::ID =
7711308Santhony.gutierrez@amd.com    tlm_extension_base::register_extension(typeid(T));
7811308Santhony.gutierrez@amd.com
7911308Santhony.gutierrez@amd.com//---------------------------------------------------------------------------
8011308Santhony.gutierrez@amd.com// enumeration types
8111308Santhony.gutierrez@amd.com//---------------------------------------------------------------------------
8211308Santhony.gutierrez@amd.comenum tlm_command
8311308Santhony.gutierrez@amd.com{
8411308Santhony.gutierrez@amd.com    TLM_READ_COMMAND,
8511308Santhony.gutierrez@amd.com    TLM_WRITE_COMMAND,
8611308Santhony.gutierrez@amd.com    TLM_IGNORE_COMMAND
8711308Santhony.gutierrez@amd.com};
8811308Santhony.gutierrez@amd.com
8911308Santhony.gutierrez@amd.comenum tlm_response_status
9011308Santhony.gutierrez@amd.com{
9111308Santhony.gutierrez@amd.com    TLM_OK_RESPONSE = 1,
9211308Santhony.gutierrez@amd.com    TLM_INCOMPLETE_RESPONSE = 0,
9311308Santhony.gutierrez@amd.com    TLM_GENERIC_ERROR_RESPONSE = -1,
9411308Santhony.gutierrez@amd.com    TLM_ADDRESS_ERROR_RESPONSE = -2,
9511308Santhony.gutierrez@amd.com    TLM_COMMAND_ERROR_RESPONSE = -3,
9611308Santhony.gutierrez@amd.com    TLM_BURST_ERROR_RESPONSE = -4,
9711308Santhony.gutierrez@amd.com    TLM_BYTE_ENABLE_ERROR_RESPONSE = -5
9811308Santhony.gutierrez@amd.com};
9911308Santhony.gutierrez@amd.com
10011308Santhony.gutierrez@amd.comenum tlm_gp_option
10111308Santhony.gutierrez@amd.com{
10211308Santhony.gutierrez@amd.com    TLM_MIN_PAYLOAD,
10311308Santhony.gutierrez@amd.com    TLM_FULL_PAYLOAD,
10411308Santhony.gutierrez@amd.com    TLM_FULL_PAYLOAD_ACCEPTED
10511308Santhony.gutierrez@amd.com};
10611308Santhony.gutierrez@amd.com
10711308Santhony.gutierrez@amd.com#define TLM_BYTE_DISABLED 0x0
10811308Santhony.gutierrez@amd.com#define TLM_BYTE_ENABLED 0xff
10911308Santhony.gutierrez@amd.com
11011308Santhony.gutierrez@amd.com//---------------------------------------------------------------------------
11111308Santhony.gutierrez@amd.com// The generic payload class:
11211308Santhony.gutierrez@amd.com//---------------------------------------------------------------------------
11311308Santhony.gutierrez@amd.com
11411308Santhony.gutierrez@amd.comextern template class tlm_array<tlm_extension_base *>;
11511308Santhony.gutierrez@amd.com
11611308Santhony.gutierrez@amd.comclass tlm_generic_payload
11711308Santhony.gutierrez@amd.com{
11811308Santhony.gutierrez@amd.com  public:
11911308Santhony.gutierrez@amd.com    tlm_generic_payload();
12011308Santhony.gutierrez@amd.com    explicit tlm_generic_payload(tlm_mm_interface *mm);
12111308Santhony.gutierrez@amd.com
12211308Santhony.gutierrez@amd.com    void
12311308Santhony.gutierrez@amd.com    acquire()
12411308Santhony.gutierrez@amd.com    {
12511308Santhony.gutierrez@amd.com        sc_assert(m_mm != 0);
12611308Santhony.gutierrez@amd.com        m_ref_count++;
12711308Santhony.gutierrez@amd.com    }
12811308Santhony.gutierrez@amd.com
12911308Santhony.gutierrez@amd.com    void
13011308Santhony.gutierrez@amd.com    release()
13111308Santhony.gutierrez@amd.com    {
13211308Santhony.gutierrez@amd.com        sc_assert(m_mm != 0 && m_ref_count > 0);
13311308Santhony.gutierrez@amd.com        if (--m_ref_count == 0)
13411308Santhony.gutierrez@amd.com            m_mm->free(this);
13511308Santhony.gutierrez@amd.com    }
13611308Santhony.gutierrez@amd.com
13711308Santhony.gutierrez@amd.com    int get_ref_count() const { return m_ref_count; }
13811308Santhony.gutierrez@amd.com
13911308Santhony.gutierrez@amd.com    void set_mm(tlm_mm_interface *mm) { m_mm = mm; }
14011308Santhony.gutierrez@amd.com    bool has_mm() const { return m_mm != 0; }
14111308Santhony.gutierrez@amd.com
14211308Santhony.gutierrez@amd.com    void reset();
14311308Santhony.gutierrez@amd.com
14411308Santhony.gutierrez@amd.com  private:
14511692Santhony.gutierrez@amd.com    // Disabled copy ctor and assignment operator.
14611308Santhony.gutierrez@amd.com    tlm_generic_payload(const tlm_generic_payload &x);
14711308Santhony.gutierrez@amd.com    tlm_generic_payload &operator = (const tlm_generic_payload &x);
14811308Santhony.gutierrez@amd.com
14911308Santhony.gutierrez@amd.com  public:
15011308Santhony.gutierrez@amd.com    // Non-virtual deep-copying of the object.
15111308Santhony.gutierrez@amd.com    void deep_copy_from(const tlm_generic_payload &other);
15211308Santhony.gutierrez@amd.com
15311308Santhony.gutierrez@amd.com    // To update the state of the original generic payload from a deep copy.
15411308Santhony.gutierrez@amd.com    // Assumes that "other" was created from the original by calling
15511308Santhony.gutierrez@amd.com    // deep_copy_from Argument use_byte_enable_on_read determines whether to
15611308Santhony.gutierrez@amd.com    // use or ignores byte enables when copying back the data array on a read
15711308Santhony.gutierrez@amd.com    // command.
15811308Santhony.gutierrez@amd.com
15911308Santhony.gutierrez@amd.com    void update_original_from(const tlm_generic_payload &other,
16011308Santhony.gutierrez@amd.com                              bool use_byte_enable_on_read=true);
16111308Santhony.gutierrez@amd.com
16211308Santhony.gutierrez@amd.com    void update_extensions_from(const tlm_generic_payload &other);
16311308Santhony.gutierrez@amd.com
16411308Santhony.gutierrez@amd.com    // Free all extensions. Useful when reusing a cloned transaction that
16511308Santhony.gutierrez@amd.com    // doesn't have memory manager. Normal and sticky extensions are freed and
16611308Santhony.gutierrez@amd.com    // extension array cleared.
16711308Santhony.gutierrez@amd.com    void free_all_extensions();
16811308Santhony.gutierrez@amd.com
16911308Santhony.gutierrez@amd.com    virtual ~tlm_generic_payload();
17011308Santhony.gutierrez@amd.com
17111308Santhony.gutierrez@amd.com    //----------------
17211308Santhony.gutierrez@amd.com    // API (including setters & getters).
17311308Santhony.gutierrez@amd.com    //---------------
17411308Santhony.gutierrez@amd.com
17511308Santhony.gutierrez@amd.com    // Command related method.
17611308Santhony.gutierrez@amd.com    bool is_read() const { return (m_command == TLM_READ_COMMAND); }
17711308Santhony.gutierrez@amd.com    void set_read() { m_command = TLM_READ_COMMAND; }
17811308Santhony.gutierrez@amd.com    bool is_write() const { return (m_command == TLM_WRITE_COMMAND); }
17911308Santhony.gutierrez@amd.com    void set_write() { m_command = TLM_WRITE_COMMAND; }
18011308Santhony.gutierrez@amd.com    tlm_command get_command() const { return m_command; }
18111308Santhony.gutierrez@amd.com    void set_command(const tlm_command command) { m_command = command; }
18211308Santhony.gutierrez@amd.com
18311308Santhony.gutierrez@amd.com    // Address related methods.
18411308Santhony.gutierrez@amd.com    sc_dt::uint64 get_address() const { return m_address; }
18511308Santhony.gutierrez@amd.com    void set_address(const sc_dt::uint64 address) { m_address = address; }
18611308Santhony.gutierrez@amd.com
18711308Santhony.gutierrez@amd.com    // Data related methods.
18811308Santhony.gutierrez@amd.com    unsigned char *get_data_ptr() const { return m_data; }
18911308Santhony.gutierrez@amd.com    void set_data_ptr(unsigned char *data) { m_data = data; }
19011308Santhony.gutierrez@amd.com
19111308Santhony.gutierrez@amd.com    // Transaction length (in bytes) related methods.
19211308Santhony.gutierrez@amd.com    unsigned int get_data_length() const { return m_length; }
19311308Santhony.gutierrez@amd.com    void set_data_length(const unsigned int length) { m_length = length; }
19411308Santhony.gutierrez@amd.com
19511308Santhony.gutierrez@amd.com    // Response status related methods.
19611308Santhony.gutierrez@amd.com    bool is_response_ok() const { return (m_response_status > 0); }
19711308Santhony.gutierrez@amd.com    bool is_response_error() const { return (m_response_status <= 0); }
19811308Santhony.gutierrez@amd.com    tlm_response_status
19911308Santhony.gutierrez@amd.com    get_response_status() const
20011308Santhony.gutierrez@amd.com    {
20111308Santhony.gutierrez@amd.com        return m_response_status;
20211308Santhony.gutierrez@amd.com    }
20311308Santhony.gutierrez@amd.com    void
20411308Santhony.gutierrez@amd.com    set_response_status(const tlm_response_status response_status)
20511308Santhony.gutierrez@amd.com    {
20611308Santhony.gutierrez@amd.com        m_response_status = response_status;
20711308Santhony.gutierrez@amd.com    }
20811308Santhony.gutierrez@amd.com    std::string get_response_string() const;
20911308Santhony.gutierrez@amd.com
21011308Santhony.gutierrez@amd.com    // Streaming related methods.
21111692Santhony.gutierrez@amd.com    unsigned int get_streaming_width() const { return m_streaming_width; }
21211692Santhony.gutierrez@amd.com    void
21311308Santhony.gutierrez@amd.com    set_streaming_width(const unsigned int streaming_width)
21411308Santhony.gutierrez@amd.com    {
21511308Santhony.gutierrez@amd.com        m_streaming_width = streaming_width;
21611308Santhony.gutierrez@amd.com    }
21711308Santhony.gutierrez@amd.com
21811308Santhony.gutierrez@amd.com    // Byte enable related methods.
21911308Santhony.gutierrez@amd.com    unsigned char *get_byte_enable_ptr() const { return m_byte_enable; }
22011308Santhony.gutierrez@amd.com    void
22111308Santhony.gutierrez@amd.com    set_byte_enable_ptr(unsigned char *byte_enable)
22211308Santhony.gutierrez@amd.com    {
22311308Santhony.gutierrez@amd.com        m_byte_enable = byte_enable;
22411308Santhony.gutierrez@amd.com    }
22511308Santhony.gutierrez@amd.com    unsigned int
22611308Santhony.gutierrez@amd.com    get_byte_enable_length() const
22711308Santhony.gutierrez@amd.com    {
22811308Santhony.gutierrez@amd.com        return m_byte_enable_length;
22911308Santhony.gutierrez@amd.com    }
23011308Santhony.gutierrez@amd.com    void
23111308Santhony.gutierrez@amd.com    set_byte_enable_length(const unsigned int byte_enable_length)
23211308Santhony.gutierrez@amd.com    {
23311308Santhony.gutierrez@amd.com        m_byte_enable_length = byte_enable_length;
23411308Santhony.gutierrez@amd.com    }
23511308Santhony.gutierrez@amd.com
23611308Santhony.gutierrez@amd.com    // This is the "DMI-hint" a slave can set this to true if it
23711308Santhony.gutierrez@amd.com    // wants to indicate that a DMI request would be supported:
23811308Santhony.gutierrez@amd.com    void
23911308Santhony.gutierrez@amd.com    set_dmi_allowed(bool dmi_allowed)
24011308Santhony.gutierrez@amd.com    {
24111308Santhony.gutierrez@amd.com        m_dmi = dmi_allowed;
24211308Santhony.gutierrez@amd.com    }
24311308Santhony.gutierrez@amd.com    bool
24411308Santhony.gutierrez@amd.com    is_dmi_allowed() const
24511308Santhony.gutierrez@amd.com    {
24611308Santhony.gutierrez@amd.com        return m_dmi;
24711308Santhony.gutierrez@amd.com    }
24811308Santhony.gutierrez@amd.com
24911308Santhony.gutierrez@amd.com    // Use full set of attributes in DMI/debug?
25011308Santhony.gutierrez@amd.com    tlm_gp_option get_gp_option() const { return m_gp_option; }
25111308Santhony.gutierrez@amd.com    void set_gp_option(const tlm_gp_option gp_opt) { m_gp_option = gp_opt; }
25211308Santhony.gutierrez@amd.com
25311308Santhony.gutierrez@amd.com  private:
25411308Santhony.gutierrez@amd.com    /* --------------------------------------------------------------------- */
25511308Santhony.gutierrez@amd.com    /* Generic Payload attributes:                                           */
25611308Santhony.gutierrez@amd.com    /* --------------------------------------------------------------------- */
25711308Santhony.gutierrez@amd.com    /* - m_command         : Type of transaction. Three values supported:    */
25811308Santhony.gutierrez@amd.com    /*                       - TLM_WRITE_COMMAND                             */
25911308Santhony.gutierrez@amd.com    /*                       - TLM_READ_COMMAND                              */
26011308Santhony.gutierrez@amd.com    /*                       - TLM_IGNORE_COMMAND                            */
26111308Santhony.gutierrez@amd.com    /* - m_address         : Transaction base address (byte-addressing).     */
26211308Santhony.gutierrez@amd.com    /* - m_data            : When m_command = TLM_WRITE_COMMAND contains a   */
26311308Santhony.gutierrez@amd.com    /*                       pointer to the data to be written in the target.*/
26411308Santhony.gutierrez@amd.com    /*                       When m_command = TLM_READ_COMMAND contains a    */
26511308Santhony.gutierrez@amd.com    /*                       pointer where to copy the data read from the    */
26611308Santhony.gutierrez@amd.com    /*                       target.                                         */
26711308Santhony.gutierrez@amd.com    /* - m_length          : Total number of bytes of the transaction.       */
26811308Santhony.gutierrez@amd.com    /* - m_response_status : This attribute indicates whether an error has   */
26911308Santhony.gutierrez@amd.com    /*                       occurred during the transaction.                */
27011308Santhony.gutierrez@amd.com    /*                       Values supported are:                           */
27111308Santhony.gutierrez@amd.com    /*                       - TLM_OK_RESP                                   */
27211308Santhony.gutierrez@amd.com    /*                       - TLM_INCOMPLETE_RESP                           */
27311308Santhony.gutierrez@amd.com    /*                       - TLM_GENERIC_ERROR_RESP                        */
27411308Santhony.gutierrez@amd.com    /*                       - TLM_ADDRESS_ERROR_RESP                        */
27511308Santhony.gutierrez@amd.com    /*                       - TLM_COMMAND_ERROR_RESP                        */
27611308Santhony.gutierrez@amd.com    /*                       - TLM_BURST_ERROR_RESP                          */
27711308Santhony.gutierrez@amd.com    /*                       - TLM_BYTE_ENABLE_ERROR_RESP                    */
27811308Santhony.gutierrez@amd.com    /*                                                                       */
27911308Santhony.gutierrez@amd.com    /* - m_byte_enable     : It can be used to create burst transfers where  */
28011308Santhony.gutierrez@amd.com    /*                    the address increment between each beat is greater */
28111308Santhony.gutierrez@amd.com    /*                    than the word length of each beat, or to place     */
28211308Santhony.gutierrez@amd.com    /*                    words in selected byte lanes of a bus.             */
28311308Santhony.gutierrez@amd.com    /* - m_byte_enable_length : For a read or a write command, the target    */
28411308Santhony.gutierrez@amd.com    /*                    interpret the byte enable length attribute as the  */
28511308Santhony.gutierrez@amd.com    /*                    number of elements in the bytes enable array.      */
28611308Santhony.gutierrez@amd.com    /* - m_streaming_width  :                                                */
28711308Santhony.gutierrez@amd.com    /* --------------------------------------------------------------------- */
28811308Santhony.gutierrez@amd.com
28911308Santhony.gutierrez@amd.com    sc_dt::uint64 m_address;
29011308Santhony.gutierrez@amd.com    tlm_command m_command;
29111308Santhony.gutierrez@amd.com    unsigned char *m_data;
29211308Santhony.gutierrez@amd.com    unsigned int m_length;
29311308Santhony.gutierrez@amd.com    tlm_response_status m_response_status;
29411308Santhony.gutierrez@amd.com    bool m_dmi;
29511308Santhony.gutierrez@amd.com    unsigned char *m_byte_enable;
29611308Santhony.gutierrez@amd.com    unsigned int m_byte_enable_length;
29711308Santhony.gutierrez@amd.com    unsigned int m_streaming_width;
29811308Santhony.gutierrez@amd.com    tlm_gp_option m_gp_option;
29911308Santhony.gutierrez@amd.com
30011308Santhony.gutierrez@amd.com  public:
30111308Santhony.gutierrez@amd.com    /* --------------------------------------------------------------------- */
30211308Santhony.gutierrez@amd.com    /* Dynamic extension mechanism:                                          */
30311308Santhony.gutierrez@amd.com    /* --------------------------------------------------------------------- */
30411308Santhony.gutierrez@amd.com    /* The extension mechanism is intended to enable initiator modules to    */
30511308Santhony.gutierrez@amd.com    /* optionally and transparently add data fields to the                   */
30611308Santhony.gutierrez@amd.com    /* tlm_generic_payload. Target modules are free to check for extensions  */
30711308Santhony.gutierrez@amd.com    /* and may or may not react to the data in the extension fields. The     */
30811308Santhony.gutierrez@amd.com    /* definition of the extensions' semantics is solely in the              */
30911308Santhony.gutierrez@amd.com    /* responsibility of the user.                                           */
31011308Santhony.gutierrez@amd.com    /*                                                                       */
31111308Santhony.gutierrez@amd.com    /* The following rules apply:                                            */
31211308Santhony.gutierrez@amd.com    /*                                                                       */
31311308Santhony.gutierrez@amd.com    /* - Every extension class must be derived from tlm_extension, e.g.:     */
31411308Santhony.gutierrez@amd.com    /*     class my_extension : public tlm_extension<my_extension> { ... }   */
31511308Santhony.gutierrez@amd.com    /*                                                                       */
31611308Santhony.gutierrez@amd.com    /* - A tlm_generic_payload object should be constructed after C++        */
31711308Santhony.gutierrez@amd.com    /*   static initialization time. This way it is guaranteed that the      */
31811308Santhony.gutierrez@amd.com    /*   extension array is of sufficient size to hold all possible          */
31911308Santhony.gutierrez@amd.com    /*   extensions. Alternatively, the initiator module can enforce a valid */
32011308Santhony.gutierrez@amd.com    /*   extension array size by calling the resize_extensions() method      */
32111308Santhony.gutierrez@amd.com    /*   once before the first transaction with the payload object is        */
32211308Santhony.gutierrez@amd.com    /*   initiated.                                                          */
32311308Santhony.gutierrez@amd.com    /*                                                                       */
32411308Santhony.gutierrez@amd.com    /* - Initiators should use the the set_extension(e) or clear_extension(e)*/
32511308Santhony.gutierrez@amd.com    /*   methods for manipulating the extension array. The type of the       */
32611308Santhony.gutierrez@amd.com    /*   argument must be a pointer to the specific registered extension     */
32711308Santhony.gutierrez@amd.com    /*   type (my_extension in the above example) and is used to             */
32811308Santhony.gutierrez@amd.com    /*   automatically locate the appropriate index in the array.            */
32911308Santhony.gutierrez@amd.com    /*                                                                       */
33011308Santhony.gutierrez@amd.com    /* - Targets can check for a specific extension by calling               */
33111308Santhony.gutierrez@amd.com    /*   get_extension(e). e will point to zero if the extension is not      */
33211308Santhony.gutierrez@amd.com    /*   present.                                                            */
33311308Santhony.gutierrez@amd.com    /*                                                                       */
334    /* --------------------------------------------------------------------- */
335
336    // Stick the pointer to an extension into the vector, return the
337    // previous value:
338    template <typename T>
339    T *
340    set_extension(T *ext)
341    {
342        return static_cast<T *>(set_extension(T::ID, ext));
343    }
344
345    // Non-templatized version with manual index:
346    tlm_extension_base *set_extension(
347            unsigned int index, tlm_extension_base *ext);
348
349    // Stick the pointer to an extension into the vector, return the
350    // previous value and schedule its release.
351    template <typename T>
352    T *
353    set_auto_extension(T *ext)
354    {
355        return static_cast<T *>(set_auto_extension(T::ID, ext));
356    }
357
358    // Non-templatized version with manual index:
359    tlm_extension_base *set_auto_extension(
360            unsigned int index, tlm_extension_base *ext);
361
362    // Check for an extension, ext will point to 0 if not present.
363    template <typename T>
364    void get_extension(T *& ext) const { ext = get_extension<T>(); }
365    template <typename T>
366    T *
367    get_extension() const
368    {
369        return static_cast<T*>(get_extension(T::ID));
370    }
371    // Non-templatized version with manual index:
372    tlm_extension_base *get_extension(unsigned int index) const;
373
374    // This call just removes the extension from the txn but does not
375    // call free() or tells the MM to do so it return false if there was
376    // active MM so you are now in an unsafe situation recommended use:
377    // when 100% sure there is no MM.
378    template <typename T>
379    void clear_extension(const T *ext) { clear_extension<T>(); }
380
381    // This call just removes the extension from the txn but does not
382    // call free() or tells the MM to do so it return false if there was
383    // active MM so you are now in an unsafe situation recommended use: when
384    // 100% sure there is no MM.
385    template <typename T>
386    void clear_extension() { clear_extension(T::ID); }
387
388    // This call removes the extension from the txn and does call free() or
389    // tells the MM to do so when the txn is finally done recommended use:
390    // when not sure there is no MM.
391    template <typename T>
392    void release_extension(T *ext)
393    {
394        release_extension<T>();
395    }
396
397    // This call removes the extension from the txn and does call free() or
398    // tells the MM to do so when the txn is finally done recommended use:
399    // when not sure there is no MM
400    template <typename T>
401    void release_extension()
402    {
403        release_extension(T::ID);
404    }
405
406  private:
407    // Non-templatized version with manual index
408    void clear_extension(unsigned int index);
409    // Non-templatized version with manual index
410    void release_extension(unsigned int index);
411
412  public:
413    // Make sure the extension array is large enough. Can be called once by
414    // an initiator module (before issuing the first transaction) to make
415    // sure that the extension array is of correct size. This is only needed
416    // if the initiator cannot guarantee that the generic payload object is
417    // allocated after C++ static construction time.
418    void resize_extensions();
419
420  private:
421    tlm_array<tlm_extension_base *> m_extensions;
422    tlm_mm_interface *m_mm;
423    unsigned int m_ref_count;
424};
425
426} // namespace tlm
427
428#endif /* __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_GP_HH__ */
429