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