C:/ESLX/projects/TLMWG/tlm2/include/tlm/tlm_utils/instance_specific_extensions.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 Instance specific extensions, are extension that only a single instance of a module
00020 may access. They are invisible to all other modules; they are private to this
00021 instance so to speak.
00022 
00023 As they are only of value to a certain instance, this instance knows very well
00024 when it needs them and when it does not need them any longer (usually when
00025 a transaction passes through a module for the last time).
00026 It does not have to care if anyone else in the system may still have a
00027 reference to the transaction as this one is not able to access the extension
00028 anyway.
00029 Therefore the instance is obliged to call set_extension when it wants to add a
00030 private extension and clear_extension when it does not need it any more.
00031 
00032 To get access to an instance specifc extension the module must own a so called
00033 instance_specific_extension_accessor that provides the exclusive access rights.
00034 Assuming the instance_specific_extension_accessor of a given module is called m_accessor
00035 and the transaction of which the private extension is about to be accessed
00036 is called txn, then the calls have to be
00037 
00038 m_accessor(txn).set_extension(...);
00039 or
00040 m_accessor(txn).clear_extension(...);
00041 
00042 The owner of the private extension is responsible to allocate/deallocate
00043 the extension before/after setting/clearing the extension.
00044 */
00045  
00046 #ifndef __INSTANCE_SPECIFIC_EXTENSIONS_H__
00047 #define __INSTANCE_SPECIFIC_EXTENSIONS_H__
00048 
00049 #include "tlm.h"
00050 
00051 namespace tlm_utils {
00052 
00053 //Helper to do the numbering of private extension accessors
00054 inline unsigned int max_num_ispex_accessors(bool increment=false)
00055 {
00056     static unsigned int max_num = 0;
00057     if (increment) ++max_num;
00058     return max_num;
00059 }
00060 
00061 //Helper to do the index generation for private extensions
00062 inline unsigned int max_num_ispex(bool increment=false)
00063 {
00064     static unsigned int max_num = 0;
00065     if (increment) ++max_num;
00066     return max_num;
00067 }
00068 
00069 //The private extension base. Similar to normal extension base, but without clone and free
00070 class ispex_base
00071 {
00072 public:
00073     virtual ~ispex_base() {}
00074 protected:
00075     static unsigned int register_private_extension()
00076     {
00077         return (max_num_ispex(true) - 1);
00078     };
00079 };
00080 
00081 //The templated private extension. Similar to normal extension
00082 template <typename T>
00083 class
00084 instance_specific_extension : public ispex_base{
00085 public:
00086     virtual ~instance_specific_extension() {}
00087     const static unsigned int priv_id;
00088 };
00089 
00090 template <typename T>
00091 const
00092 unsigned int instance_specific_extension<T>::priv_id = ispex_base::register_private_extension();
00093 
00094 
00095 //this thing is basically a snippet of the generic_payload
00096 // it contains all the extension specific code (the extension API so to speak)
00097 // the differences are:
00098 // - it calls back to its owner whenever a real (==non-NULL) extension gets set for the first time
00099 // - it calls back to its owner whenever a living (==non-NULL) extension gets cleared
00100 template<typename U>
00101 class instance_specific_extensions_per_accessor{
00102 public:
00103 
00104   typedef void (U::*cb)();
00105 
00106   instance_specific_extensions_per_accessor(U* container, cb inc, cb dec): m_container(container), m_inc(inc), m_dec(dec){
00107   }
00108 
00109   template <typename T> T* set_extension(T* ext)
00110   {
00111       resize_extensions();
00112       T* tmp = static_cast<T*>(m_extensions[T::priv_id]);
00113       m_extensions[T::priv_id] = static_cast<ispex_base*>(ext);
00114       if (!tmp && ext) (m_container->*m_inc)();
00115       return tmp;
00116   }
00117   // non-templatized version with manual index:
00118   ispex_base* set_extension(unsigned int index,
00119                                     ispex_base* ext)
00120   {
00121       resize_extensions();
00122       ispex_base* tmp = m_extensions[index];
00123       m_extensions[index] = ext;
00124       if (!tmp && ext) (m_container->*m_inc)();
00125       return tmp;
00126   }
00127 
00128   // Check for an extension, ext will point to 0 if not present
00129   template <typename T> void get_extension(T*& ext) const
00130   {
00131       ext = static_cast<T*>(m_extensions[T::priv_id]);
00132   }
00133   // Non-templatized version:
00134    ispex_base* get_extension(unsigned int index) const
00135   {
00136       return m_extensions[index];
00137   }
00138 
00139   // Clear extension, the argument is needed to find the right index:
00140   template <typename T> void clear_extension(const T* ext)
00141   {
00142       resize_extensions();
00143       if (m_extensions[T::priv_id]) (m_container->*m_dec)();
00144       m_extensions[T::priv_id] = static_cast<ispex_base*>(0);
00145   }
00146   // Non-templatized version with manual index
00147   void clear_extension(unsigned int index)
00148   {
00149       if (index < m_extensions.size())
00150       {
00151           if (m_extensions[index]) (m_container->*m_dec)();
00152           m_extensions[index] = static_cast<ispex_base*>(0);
00153       }
00154   }
00155 
00156   // Make sure the extension array is large enough. Can be called once by
00157   // an initiator module (before issuing the first transaction) to make
00158   // sure that the extension array is of correct size. This is only needed
00159   // if the initiator cannot guarantee that the generic payload object is
00160   // allocated after C++ static construction time.
00161   void resize_extensions()
00162   {
00163       m_extensions.expand(max_num_ispex());
00164   }
00165   
00166 private:
00167   tlm::tlm_array<ispex_base*> m_extensions;
00168   U* m_container;
00169   cb m_inc, m_dec;
00170   
00171 };
00172 
00173 class instance_specific_extension_container;
00174 
00175 
00176 //the pool for the container, plain as can be
00177 class instance_specific_extension_container_pool{
00178   friend class instance_specific_extension_carrier;
00179   friend class instance_specific_extension_container;
00180   instance_specific_extension_container_pool() : unused(NULL){}
00181   inline ~instance_specific_extension_container_pool();
00182   inline static instance_specific_extension_container_pool& get_ispexcont_pool(){ static instance_specific_extension_container_pool tmp; return tmp;}
00183   inline instance_specific_extension_container* create();
00184   inline void free(instance_specific_extension_container*);
00185   
00186   instance_specific_extension_container* unused;
00187 };
00188 
00189 class instance_specific_extension_carrier;
00190 
00191 //this thing contains the vector of extensions per accessor
00192 //which can be really large so this one should be pool allocated
00193 // therefore it keeps a use_count of itself to automatically free itself
00194 // - to this end it provides callbacks to the extensions per accessor
00195 //   to increment and decrement the use_count
00196 class instance_specific_extension_container{
00197   friend class instance_specific_extension_container_pool;
00198   friend class instance_specific_extension_accessor;
00199   friend class instance_specific_extension_carrier;
00200   
00201   instance_specific_extension_container(): use_count(0), next(NULL){resize();}
00202   
00203   void resize(){
00204     m_ispex_per_accessor.resize(max_num_ispex_accessors());
00205     for (unsigned int i=0; i<m_ispex_per_accessor.size(); i++) {
00206       m_ispex_per_accessor[i]=new instance_specific_extensions_per_accessor<instance_specific_extension_container>(this, 
00207                                                                                    &instance_specific_extension_container::inc_use_count, 
00208                                                                                    &instance_specific_extension_container::dec_use_count
00209                                                                                    );
00210       m_ispex_per_accessor[i]->resize_extensions();
00211     }
00212   }
00213  
00214   ~instance_specific_extension_container(){
00215     for (unsigned int i=0; i<m_ispex_per_accessor.size(); i++) delete m_ispex_per_accessor[i];
00216   }
00217  
00218   void inc_use_count(){use_count++;}
00219   inline void dec_use_count();
00220   
00221   std::vector<instance_specific_extensions_per_accessor<instance_specific_extension_container>* > m_ispex_per_accessor; 
00222   unsigned int use_count;
00223   tlm::tlm_generic_payload* my_txn;
00224   instance_specific_extension_carrier* my_carrier;
00225   instance_specific_extension_container* next; //for pooling
00226 };
00227 
00228 
00229 inline instance_specific_extension_container_pool::~instance_specific_extension_container_pool(){
00230   while(unused) { instance_specific_extension_container* tmp=unused; unused=unused->next; delete tmp;}
00231 }
00232 
00233 instance_specific_extension_container* instance_specific_extension_container_pool::create(){
00234   if (!unused) {unused=new instance_specific_extension_container();}
00235   instance_specific_extension_container* tmp=unused;
00236   unused=unused->next;
00237   return tmp; 
00238 }
00239 
00240 void instance_specific_extension_container_pool::free(instance_specific_extension_container* cont){
00241   cont->next=unused;
00242   unused=cont;
00243 }
00244 
00245 //This is the class that actually sits in the extension array
00246 //we keep this small since that one gets allocated and deallocated all the times
00247 class instance_specific_extension_carrier: public tlm::tlm_extension<instance_specific_extension_carrier>{
00248   friend class instance_specific_extension_accessor;
00249 
00250 public:
00251   instance_specific_extension_carrier(){
00252     m_container=instance_specific_extension_container_pool::get_ispexcont_pool().create();
00253     m_container->my_carrier=this;
00254   }
00255   
00256   virtual tlm::tlm_extension_base* clone() const {
00257     //we don't clone since private info is instance specific and associated to a given txn (the original)
00258     //so the deep copied txn will be virgin in terms of private info
00259     return NULL;
00260   }
00261   void copy_from(tlm::tlm_extension_base const &){return;}
00262   void free(){return;}
00263 private:
00264   instance_specific_extension_container* m_container;
00265 };
00266 
00267 inline void instance_specific_extension_container::dec_use_count(){
00268   if ((--use_count)==0) { //if this container isn't used any more
00269     instance_specific_extension_container_pool::get_ispexcont_pool().free(this);  //we send it back to our pool
00270     //we have to do that manually, as we cannot rely on the fact that there is MM in the txn
00271     my_txn->clear_extension(my_carrier); //and remove it from the transaction's extension array
00272     delete my_carrier;
00273   }
00274 }
00275 
00276 
00277 //This class 'hides' all the instance specific extension stuff from the user
00278 // he instantiates one of those (e.g. instance_specific_extension_accessor extAcc;) and can then access
00279 // the private extensions
00280 //    extAcc(txn).extensionAPIFnCall()
00281 //  where extensionAPIFnCall is set_extension, get_extension, clear_extension,...
00282 class instance_specific_extension_accessor{
00283 public:
00284   instance_specific_extension_accessor(): m_index(max_num_ispex_accessors(true)-1){}
00285   
00286   template<typename T>
00287   inline instance_specific_extensions_per_accessor<instance_specific_extension_container>& operator()(T& txn){
00288     instance_specific_extension_carrier* carrier;
00289     txn.get_extension(carrier);
00290     if (!carrier){
00291       carrier=new instance_specific_extension_carrier();
00292       carrier->m_container->my_txn=&txn;
00293       txn.set_extension(carrier);
00294     }
00295     return *(carrier->m_container->m_ispex_per_accessor[m_index]);
00296   }
00297   
00298 protected:
00299   unsigned int m_index;
00300 };
00301 
00302 }
00303 
00304 #endif

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