TLM-2.0: include/tlm/tlm_h/tlm_generic_payload/tlm_gp.h Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# include/tlm/tlm_h/tlm_generic_payload/tlm_gp.h

Go to the documentation of this file.

    00001 /*****************************************************************************
    00002
    00003   The following code is derived, directly or indirectly, from the SystemC
    00004   source code Copyright (c) 1996-2008 by all Contributors.
    00005   All Rights reserved.
    00006
    00007   The contents of this file are subject to the restrictions and limitations
    00008   set forth in the SystemC Open Source License Version 3.0 (the "License");
    00009   You may not use this file except in compliance with such restrictions and
    00010   limitations. You may obtain instructions on how to receive a copy of the
    00011   License at http://www.systemc.org/. Software distributed by Contributors
    00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
    00013   ANY KIND, either express or implied. See the License for the specific
    00014   language governing rights and limitations under the License.
    00015
    00016 *****************************************************************************/
    00017
    00018 // 12-Jan-2009  John Aynsley  Bug fix. has_mm() and get_ref_count() should both be const
    00019 // 23-Mar-2009  John Aynsley  Add method update_original_from()
    00020 // 20-Apr-2009  John Aynsley  Bug fix for 64-bit machines: unsigned long int -> unsigned int
    00021
    00022
    00023 #ifndef __TLM_GP_H__
    00024 #define __TLM_GP_H__
    00025
    00026 #include <systemc>
    00027 #include "tlm_array.h"
    00028
    00029 namespace tlm {
    00030
    00031 class
    00032 tlm_generic_payload;
    00033
    00034 class tlm_mm_interface {
    00035 public:
    00036   virtual void free(tlm_generic_payload*) = 0;
    00037   virtual ~tlm_mm_interface() {}
    00038 };
    00039
    00040 //---------------------------------------------------------------------------
    00041 // Classes and helper functions for the extension mechanism
    00042 //---------------------------------------------------------------------------
    00043 // Helper function:
    00044 inline unsigned int max_num_extensions(bool increment=false)
    00045 {
    00046     static unsigned int max_num = 0;
    00047     if (increment) ++max_num;
    00048     return max_num;
    00049 }
    00050
    00051 // This class can be used for storing pointers to the extension classes, used
    00052 // in tlm_generic_payload:
    00053 class tlm_extension_base
    00054 {
    00055 public:
    00056     virtual tlm_extension_base* clone() const = 0;
    00057     virtual void free() { delete this; }
    00058     virtual void copy_from(tlm_extension_base const &) = 0;
    00059 protected:
    00060     virtual ~tlm_extension_base() {}
    00061     static unsigned int register_extension()
    00062     {
    00063         return (max_num_extensions(true) - 1);
    00064     };
    00065 };
    00066
    00067 // Base class for all extension classes, derive your extension class in
    00068 // the following way:
    00069 // class my_extension : public tlm_extension<my_extension> { ...
    00070 // This triggers proper extension registration during C++ static
    00071 // contruction time. my_extension::ID will hold the unique index in the
    00072 // tlm_generic_payload::m_extensions array.
    00073 template <typename T>
    00074 class tlm_extension : public tlm_extension_base
    00075 {
    00076 public:
    00077     virtual tlm_extension_base* clone() const = 0;
    00078     virtual void copy_from(tlm_extension_base const &ext) = 0; //{assert(typeid(this)==typeid(ext)); assert(ID === ext.ID); assert(0);}
    00079     virtual ~tlm_extension() {}
    00080     const static unsigned int ID;
    00081 };
    00082
    00083 template <typename T>
    00084 const
    00085 unsigned int tlm_extension<T>::ID = tlm_extension_base::register_extension();
    00086
    00087 //---------------------------------------------------------------------------
    00088 // enumeration types
    00089 //---------------------------------------------------------------------------
    00090 enum tlm_command {
    00091     TLM_READ_COMMAND,
    00092     TLM_WRITE_COMMAND,
    00093     TLM_IGNORE_COMMAND
    00094 };
    00095
    00096 enum tlm_response_status {
    00097     TLM_OK_RESPONSE = 1,
    00098     TLM_INCOMPLETE_RESPONSE = 0,
    00099     TLM_GENERIC_ERROR_RESPONSE = -1,
    00100     TLM_ADDRESS_ERROR_RESPONSE = -2,
    00101     TLM_COMMAND_ERROR_RESPONSE = -3,
    00102     TLM_BURST_ERROR_RESPONSE = -4,
    00103     TLM_BYTE_ENABLE_ERROR_RESPONSE = -5
    00104 };
    00105
    00106 #define TLM_BYTE_DISABLED 0x0
    00107 #define TLM_BYTE_ENABLED 0xff
    00108
    00109 //---------------------------------------------------------------------------
    00110 // The generic payload class:
    00111 //---------------------------------------------------------------------------
    00112 class tlm_generic_payload {
    00113
    00114 public:
    00115     //---------------
    00116     // Constructors
    00117     //---------------
    00118
    00119     // Default constructor
    00120     tlm_generic_payload()
    00121         : m_address(0)
    00122         , m_command(TLM_IGNORE_COMMAND)
    00123         , m_data(0)
    00124         , m_length(0)
    00125         , m_response_status(TLM_INCOMPLETE_RESPONSE)
    00126         , m_dmi(false)
    00127         , m_byte_enable(0)
    00128         , m_byte_enable_length(0)
    00129         , m_streaming_width(0)
    00130         , m_extensions(max_num_extensions())
    00131         , m_mm(0)
    00132         , m_ref_count(0)
    00133     {
    00134     }
    00135
    00136     explicit tlm_generic_payload(tlm_mm_interface* mm)
    00137         : m_address(0)
    00138         , m_command(TLM_IGNORE_COMMAND)
    00139         , m_data(0)
    00140         , m_length(0)
    00141         , m_response_status(TLM_INCOMPLETE_RESPONSE)
    00142         , m_dmi(false)
    00143         , m_byte_enable(0)
    00144         , m_byte_enable_length(0)
    00145         , m_streaming_width(0)
    00146         , m_extensions(max_num_extensions())
    00147         , m_mm(mm)
    00148         , m_ref_count(0)
    00149     {
    00150     }
    00151
    00152     void acquire(){assert(m_mm != 0); m_ref_count++;}
    00153     void release(){assert(m_mm != 0); if (--m_ref_count==0) m_mm->free(this);}
    00154     int get_ref_count() const {return m_ref_count;}
    00155     void set_mm(tlm_mm_interface* mm) { m_mm = mm; }
    00156     bool has_mm() const { return m_mm != 0; }
    00157
    00158     void reset(){
    00159       //should the other members be reset too?
    00160       m_extensions.free_entire_cache();
    00161     };
    00162
    00163
    00164 private:
    00165     //disabled copy ctor and assignment operator.
    00166     // Copy constructor
    00167     tlm_generic_payload(const tlm_generic_payload& x)
    00168         : m_address(x.get_address())
    00169         , m_command(x.get_command())
    00170         , m_data(x.get_data_ptr())
    00171         , m_length(x.get_data_length())
    00172         , m_response_status(x.get_response_status())
    00173         , m_dmi(x.is_dmi_allowed())
    00174         , m_byte_enable(x.get_byte_enable_ptr())
    00175         , m_byte_enable_length(x.get_byte_enable_length())
    00176         , m_streaming_width(x.get_streaming_width())
    00177         , m_extensions(max_num_extensions())
    00178     {
    00179         // copy all extensions
    00180         for(unsigned int i=0; i<m_extensions.size(); i++)
    00181         {
    00182             m_extensions[i] = x.get_extension(i);
    00183         }
    00184     }
    00185
    00186     // Assignment operator
    00187     tlm_generic_payload& operator= (const tlm_generic_payload& x)
    00188     {
    00189         m_command =            x.get_command();
    00190         m_address =            x.get_address();
    00191         m_data =               x.get_data_ptr();
    00192         m_length =             x.get_data_length();
    00193         m_response_status =    x.get_response_status();
    00194         m_byte_enable =        x.get_byte_enable_ptr();
    00195         m_byte_enable_length = x.get_byte_enable_length();
    00196         m_streaming_width =    x.get_streaming_width();
    00197         m_dmi =                x.is_dmi_allowed();
    00198
    00199         // extension copy: all extension arrays must be of equal size by
    00200         // construction (i.e. it must either be constructed after C++
    00201         // static construction time, or the resize_extensions() method must
    00202         // have been called prior to using the object)
    00203         for(unsigned int i=0; i<m_extensions.size(); i++)
    00204         {
    00205             m_extensions[i] = x.get_extension(i);
    00206         }
    00207         return (*this);
    00208     }
    00209 public:
    00210     // non-virtual deep-copying of the object
    00211     void deep_copy_from(const tlm_generic_payload & other)
    00212     {
    00213         m_command =            other.get_command();
    00214         m_address =            other.get_address();
    00215         m_length =             other.get_data_length();
    00216         m_response_status =    other.get_response_status();
    00217         m_byte_enable_length = other.get_byte_enable_length();
    00218         m_streaming_width =    other.get_streaming_width();
    00219         m_dmi =                other.is_dmi_allowed();
    00220
    00221         // deep copy data
    00222         // there must be enough space in the target transaction!
    00223         if(m_data && other.m_data)
    00224         {
    00225             memcpy(m_data, other.m_data, m_length);
    00226         }
    00227         // deep copy byte enables
    00228         // there must be enough space in the target transaction!
    00229         if(m_byte_enable && other.m_byte_enable)
    00230         {
    00231             memcpy(m_byte_enable, other.m_byte_enable, m_byte_enable_length);
    00232         }
    00233         // deep copy extensions (sticky and non-sticky)
    00234         for(unsigned int i=0; i<other.m_extensions.size(); i++)
    00235         {
    00236             if(other.m_extensions[i])
    00237             {                       //original has extension i
    00238                 if(!m_extensions[i])
    00239                 {                   //We don't: clone.
    00240                     tlm_extension_base *ext = other.m_extensions[i]->clone();
    00241                     if(ext)     //extension may not be clonable.
    00242                     {
    00243                         if(has_mm())
    00244                         {           //mm can take care of removing cloned extensions
    00245                             set_auto_extension(i, ext);
    00246                         }
    00247                         else
    00248                         {           // no mm, user will call free_all_extensions().
    00249                             set_extension(i, ext);
    00250                         }
    00251                     }
    00252                 }
    00253                 else
    00254                 {                   //We already have such extension. Copy original over it.
    00255                     m_extensions[i]->copy_from(*other.m_extensions[i]);
    00256                 }
    00257             }
    00258         }
    00259     }
    00260
    00261     // To update the state of the original generic payload from a deep copy
    00262     // Assumes that "other" was created from the original by calling deep_copy_from
    00263     // Argument use_byte_enable_on_read determines whether to use or ignores byte enables
    00264     // when copying back the data array on a read command
    00265
    00266     void update_original_from(const tlm_generic_payload & other,
    00267                               bool use_byte_enable_on_read = true)
    00268     {
    00269         // Copy back extensions that are present on the original
    00270         update_extensions_from(other);
    00271
    00272         // Copy back the response status and DMI hint attributes
    00273         m_response_status = other.get_response_status();
    00274         m_dmi             = other.is_dmi_allowed();
    00275
    00276         // Copy back the data array for a read command only
    00277         // deep_copy_from allowed null pointers, and so will we
    00278         // We assume the arrays are the same size
    00279         // We test for equal pointers in case the original and the copy share the same array
    00280
    00281         if(is_read() && m_data && other.m_data && m_data != other.m_data)
    00282         {
    00283             if (m_byte_enable && use_byte_enable_on_read)
    00284             {
    00285                 if (m_byte_enable_length == 8 && m_length % 8 == 0 )
    00286                 {
    00287                     // Optimized implementation copies 64-bit words by masking
    00288                     for (unsigned int i = 0; i < m_length; i += 8)
    00289                     {
    00290                         typedef sc_dt::uint64* u;
    00291                         *reinterpret_cast<u>(&m_data[i]) &= ~*reinterpret_cast<u>(m_byte_enable);
    00292                         *reinterpret_cast<u>(&m_data[i]) |= *reinterpret_cast<u>(&other.m_data[i]) &
    00293                                                             *reinterpret_cast<u>(m_byte_enable);
    00294                     }
    00295                 }
    00296                 else if (m_byte_enable_length == 4 && m_length % 4 == 0 )
    00297                 {
    00298                     // Optimized implementation copies 32-bit words by masking
    00299                     for (unsigned int i = 0; i < m_length; i += 4)
    00300                     {
    00301                         typedef unsigned int* u;
    00302                         *reinterpret_cast<u>(&m_data[i]) &= ~*reinterpret_cast<u>(m_byte_enable);
    00303                         *reinterpret_cast<u>(&m_data[i]) |= *reinterpret_cast<u>(&other.m_data[i]) &
    00304                                                             *reinterpret_cast<u>(m_byte_enable);
    00305                     }
    00306                 }
    00307                 else
    00308                     // Unoptimized implementation
    00309                     for (unsigned int i = 0; i < m_length; i++)
    00310                         if ( m_byte_enable[i % m_byte_enable_length] )
    00311                             m_data[i] = other.m_data[i];
    00312             }
    00313             else
    00314               memcpy(m_data, other.m_data, m_length);
    00315         }
    00316     }
    00317
    00318     void update_extensions_from(const tlm_generic_payload & other)
    00319     {
    00320         // deep copy extensions that are already present
    00321         for(unsigned int i=0; i<other.m_extensions.size(); i++)
    00322         {
    00323             if(other.m_extensions[i])
    00324             {                       //original has extension i
    00325                 if(m_extensions[i])
    00326                 {                   //We have it too. copy.
    00327                     m_extensions[i]->copy_from(*other.m_extensions[i]);
    00328                 }
    00329             }
    00330         }
    00331     }
    00332
    00333     // Free all extensions. Useful when reusing a cloned transaction that doesn't have memory manager.
    00334     // normal and sticky extensions are freed and extension array cleared.
    00335     void free_all_extensions()
    00336     {
    00337         m_extensions.free_entire_cache();
    00338         for(unsigned int i=0; i<m_extensions.size(); i++)
    00339         {
    00340             if(m_extensions[i])
    00341             {
    00342                 m_extensions[i]->free();
    00343                 m_extensions[i] = 0;
    00344             }
    00345         }
    00346     }
    00347     //--------------
    00348     // Destructor
    00349     //--------------
    00350     virtual ~tlm_generic_payload() {
    00351         for(unsigned int i=0; i<m_extensions.size(); i++)
    00352             if(m_extensions[i]) m_extensions[i]->free();
    00353     }
    00354
    00355     //----------------
    00356     // API (including setters & getters)
    00357     //---------------
    00358
    00359     // Command related method
    00360     bool                 is_read() const {return (m_command == TLM_READ_COMMAND);}
    00361     void                 set_read() {m_command = TLM_READ_COMMAND;}
    00362     bool                 is_write() const {return (m_command == TLM_WRITE_COMMAND);}
    00363     void                 set_write() {m_command = TLM_WRITE_COMMAND;}
    00364     tlm_command          get_command() const {return m_command;}
    00365     void                 set_command(const tlm_command command) {m_command = command;}
    00366
    00367     // Address related methods
    00368     sc_dt::uint64        get_address() const {return m_address;}
    00369     void                 set_address(const sc_dt::uint64 address) {m_address = address;}
    00370
    00371     // Data related methods
    00372     unsigned char*       get_data_ptr() const {return m_data;}
    00373     void                 set_data_ptr(unsigned char* data) {m_data = data;}
    00374
    00375     // Transaction length (in bytes) related methods
    00376     unsigned int         get_data_length() const {return m_length;}
    00377     void                 set_data_length(const unsigned int length) {m_length = length;}
    00378
    00379     // Response status related methods
    00380     bool                 is_response_ok() const {return (m_response_status > 0);}
    00381     bool                 is_response_error() const {return (m_response_status <= 0);}
    00382     tlm_response_status  get_response_status() const {return m_response_status;}
    00383     void                 set_response_status(const tlm_response_status response_status)
    00384         {m_response_status = response_status;}
    00385     std::string          get_response_string() const
    00386     {
    00387         switch(m_response_status)
    00388         {
    00389         case TLM_OK_RESPONSE:            return "TLM_OK_RESPONSE";
    00390         case TLM_INCOMPLETE_RESPONSE:    return "TLM_INCOMPLETE_RESPONSE";
    00391         case TLM_GENERIC_ERROR_RESPONSE: return "TLM_GENERIC_ERROR_RESPONSE";
    00392         case TLM_ADDRESS_ERROR_RESPONSE: return "TLM_ADDRESS_ERROR_RESPONSE";
    00393         case TLM_COMMAND_ERROR_RESPONSE: return "TLM_COMMAND_ERROR_RESPONSE";
    00394         case TLM_BURST_ERROR_RESPONSE:   return "TLM_BURST_ERROR_RESPONSE";
    00395         case TLM_BYTE_ENABLE_ERROR_RESPONSE: return "TLM_BYTE_ENABLE_ERROR_RESPONSE";
    00396         }
    00397         return "TLM_UNKNOWN_RESPONSE";
    00398     }
    00399
    00400     // Streaming related methods
    00401     unsigned int         get_streaming_width() const {return m_streaming_width;}
    00402     void                 set_streaming_width(const unsigned int streaming_width) {m_streaming_width = streaming_width; }
    00403
    00404     // Byte enable related methods
    00405     unsigned char*       get_byte_enable_ptr() const {return m_byte_enable;}
    00406     void                 set_byte_enable_ptr(unsigned char* byte_enable){m_byte_enable = byte_enable;}
    00407     unsigned int         get_byte_enable_length() const {return m_byte_enable_length;}
    00408     void                 set_byte_enable_length(const unsigned int byte_enable_length){m_byte_enable_length = byte_enable_length;}
    00409
    00410     // This is the "DMI-hint" a slave can set this to true if it
    00411     // wants to indicate that a DMI request would be supported:
    00412     void                 set_dmi_allowed(bool dmi_allowed) { m_dmi = dmi_allowed; }
    00413     bool                 is_dmi_allowed() const { return m_dmi; }
    00414
    00415 private:
    00416
    00417     /* --------------------------------------------------------------------- */
    00418     /* Generic Payload attributes:                                           */
    00419     /* --------------------------------------------------------------------- */
    00420     /* - m_command         : Type of transaction. Three values supported:    */
    00421     /*                       - TLM_WRITE_COMMAND                             */
    00422     /*                       - TLM_READ_COMMAND                              */
    00423     /*                       - TLM_IGNORE_COMMAND                            */
    00424     /* - m_address         : Transaction base address (byte-addressing).     */
    00425     /* - m_data            : When m_command = TLM_WRITE_COMMAND contains a   */
    00426     /*                       pointer to the data to be written in the target.*/
    00427     /*                       When m_command = TLM_READ_COMMAND contains a    */
    00428     /*                       pointer where to copy the data read from the    */
    00429     /*                       target.                                         */
    00430     /* - m_length          : Total number of bytes of the transaction.       */
    00431     /* - m_response_status : This attribute indicates whether an error has   */
    00432     /*                       occurred during the transaction.                */
    00433     /*                       Values supported are:                           */
    00434     /*                       - TLM_OK_RESP                                   */
    00435     /*                       - TLM_INCOMPLETE_RESP                           */
    00436     /*                       - TLM_GENERIC_ERROR_RESP                        */
    00437     /*                       - TLM_ADDRESS_ERROR_RESP                        */
    00438     /*                       - TLM_COMMAND_ERROR_RESP                        */
    00439     /*                       - TLM_BURST_ERROR_RESP                          */
    00440     /*                       - TLM_BYTE_ENABLE_ERROR_RESP                    */
    00441     /*                                                                       */
    00442     /* - m_byte_enable     : It can be used to create burst transfers where  */
    00443     /*                    the address increment between each beat is greater */
    00444     /*                    than the word length of each beat, or to place     */
    00445     /*                    words in selected byte lanes of a bus.             */
    00446     /* - m_byte_enable_length : For a read or a write command, the target    */
    00447     /*                    interpret the byte enable length attribute as the  */
    00448     /*                    number of elements in the bytes enable array.      */
    00449     /* - m_streaming_width  :                                                */
    00450     /* --------------------------------------------------------------------- */
    00451
    00452     sc_dt::uint64        m_address;
    00453     tlm_command          m_command;
    00454     unsigned char*       m_data;
    00455     unsigned int         m_length;
    00456     tlm_response_status  m_response_status;
    00457     bool                 m_dmi;
    00458     unsigned char*       m_byte_enable;
    00459     unsigned int         m_byte_enable_length;
    00460     unsigned int         m_streaming_width;
    00461
    00462 public:
    00463
    00464     /* --------------------------------------------------------------------- */
    00465     /* Dynamic extension mechanism:                                          */
    00466     /* --------------------------------------------------------------------- */
    00467     /* The extension mechanism is intended to enable initiator modules to    */
    00468     /* optionally and transparently add data fields to the                   */
    00469     /* tlm_generic_payload. Target modules are free to check for extensions  */
    00470     /* and may or may not react to the data in the extension fields. The     */
    00471     /* definition of the extensions' semantics is solely in the              */
    00472     /* responsibility of the user.                                           */
    00473     /*                                                                       */
    00474     /* The following rules apply:                                            */
    00475     /*                                                                       */
    00476     /* - Every extension class must be derived from tlm_extension, e.g.:     */
    00477     /*     class my_extension : public tlm_extension<my_extension> { ... }   */
    00478     /*                                                                       */
    00479     /* - A tlm_generic_payload object should be constructed after C++        */
    00480     /*   static initialization time. This way it is guaranteed that the      */
    00481     /*   extension array is of sufficient size to hold all possible          */
    00482     /*   extensions. Alternatively, the initiator module can enforce a valid */
    00483     /*   extension array size by calling the resize_extensions() method      */
    00484     /*   once before the first transaction with the payload object is        */
    00485     /*   initiated.                                                          */
    00486     /*                                                                       */
    00487     /* - Initiators should use the the set_extension(e) or clear_extension(e)*/
    00488     /*   methods for manipulating the extension array. The type of the       */
    00489     /*   argument must be a pointer to the specific registered extension     */
    00490     /*   type (my_extension in the above example) and is used to             */
    00491     /*   automatically locate the appropriate index in the array.            */
    00492     /*                                                                       */
    00493     /* - Targets can check for a specific extension by calling               */
    00494     /*   get_extension(e). e will point to zero if the extension is not      */
    00495     /*   present.                                                            */
    00496     /*                                                                       */
    00497     /* --------------------------------------------------------------------- */
    00498
    00499     // Stick the pointer to an extension into the vector, return the
    00500     // previous value:
    00501     template <typename T> T* set_extension(T* ext)
    00502     {
    00503         return static_cast<T*>(set_extension(T::ID, ext));
    00504     }
    00505
    00506     // non-templatized version with manual index:
    00507     tlm_extension_base* set_extension(unsigned int index,
    00508                                       tlm_extension_base* ext)
    00509     {
    00510         tlm_extension_base* tmp = m_extensions[index];
    00511         m_extensions[index] = ext;
    00512         return tmp;
    00513     }
    00514
    00515     // Stick the pointer to an extension into the vector, return the
    00516     // previous value and schedule its release
    00517     template <typename T> T* set_auto_extension(T* ext)
    00518     {
    00519         return static_cast<T*>(set_auto_extension(T::ID, ext));
    00520     }
    00521
    00522     // non-templatized version with manual index:
    00523     tlm_extension_base* set_auto_extension(unsigned int index,
    00524                                            tlm_extension_base* ext)
    00525     {
    00526         tlm_extension_base* tmp = m_extensions[index];
    00527         m_extensions[index] = ext;
    00528         if (!tmp) m_extensions.insert_in_cache(&m_extensions[index]);
    00529         assert(m_mm != 0);
    00530         return tmp;
    00531     }
    00532
    00533     // Check for an extension, ext will point to 0 if not present
    00534     template <typename T> void get_extension(T*& ext) const
    00535     {
    00536         ext = get_extension<T>();
    00537     }
    00538     template <typename T> T* get_extension() const
    00539     {
    00540         return static_cast<T*>(get_extension(T::ID));
    00541     }
    00542     // Non-templatized version with manual index:
    00543     tlm_extension_base* get_extension(unsigned int index) const
    00544     {
    00545         return m_extensions[index];
    00546     }
    00547
    00548     //this call just removes the extension from the txn but does not
    00549     // call free() or tells the MM to do so
    00550     // it return false if there was active MM so you are now in an unsafe situation
    00551     // recommended use: when 100% sure there is no MM
    00552     template <typename T> void clear_extension(const T* ext)
    00553     {
    00554         clear_extension<T>();
    00555     }
    00556
    00557     //this call just removes the extension from the txn but does not
    00558     // call free() or tells the MM to do so
    00559     // it return false if there was active MM so you are now in an unsafe situation
    00560     // recommended use: when 100% sure there is no MM
    00561     template <typename T> void clear_extension()
    00562     {
    00563         clear_extension(T::ID);
    00564     }
    00565
    00566     //this call removes the extension from the txn and does
    00567     // call free() or tells the MM to do so when the txn is finally done
    00568     // recommended use: when not sure there is no MM
    00569     template <typename T> void release_extension(T* ext)
    00570     {
    00571         release_extension<T>();
    00572     }
    00573
    00574     //this call removes the extension from the txn and does
    00575     // call free() or tells the MM to do so when the txn is finally done
    00576     // recommended use: when not sure there is no MM
    00577     template <typename T> void release_extension()
    00578     {
    00579         release_extension(T::ID);
    00580     }
    00581
    00582 private:
    00583     // Non-templatized version with manual index
    00584     void clear_extension(unsigned int index)
    00585     {
    00586         m_extensions[index] = static_cast<tlm_extension_base*>(0);
    00587     }
    00588     // Non-templatized version with manual index
    00589     void release_extension(unsigned int index)
    00590     {
    00591         if (m_mm)
    00592         {
    00593             m_extensions.insert_in_cache(&m_extensions[index]);
    00594         }
    00595         else
    00596         {
    00597             m_extensions[index]->free();
    00598             m_extensions[index] = static_cast<tlm_extension_base*>(0);
    00599         }
    00600     }
    00601
    00602 public:
    00603     // Make sure the extension array is large enough. Can be called once by
    00604     // an initiator module (before issuing the first transaction) to make
    00605     // sure that the extension array is of correct size. This is only needed
    00606     // if the initiator cannot guarantee that the generic payload object is
    00607     // allocated after C++ static construction time.
    00608     void resize_extensions()
    00609     {
    00610         m_extensions.expand(max_num_extensions());
    00611     }
    00612
    00613 private:
    00614     tlm_array<tlm_extension_base*> m_extensions;
    00615     tlm_mm_interface*              m_mm;
    00616     unsigned int                   m_ref_count;
    00617 };
    00618
    00619 } // namespace tlm
    00620
    00621 #endif /* __TLM_GP_H__ */