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

Generated on Thu Jun 5 17:43:03 2008 for TLM 2 by  doxygen 1.5.3