instance_specific_extensions.h revision 13511:dc5864c73df3
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/* 21Instance specific extensions, are extension that only a single instance of a module 22may access. They are invisible to all other modules; they are private to this 23instance so to speak. 24 25As they are only of value to a certain instance, this instance knows very well 26when it needs them and when it does not need them any longer (usually when 27a transaction passes through a module for the last time). 28It does not have to care if anyone else in the system may still have a 29reference to the transaction as this one is not able to access the extension 30anyway. 31Therefore the instance is obliged to call set_extension when it wants to add a 32private extension and clear_extension when it does not need it any more. 33 34To get access to an instance specifc extension the module must own a so called 35instance_specific_extension_accessor that provides the exclusive access rights. 36Assuming the instance_specific_extension_accessor of a given module is called m_accessor 37and the transaction of which the private extension is about to be accessed 38is called txn, then the calls have to be 39 40m_accessor(txn).set_extension(...); 41or 42m_accessor(txn).clear_extension(...); 43 44The owner of the private extension is responsible to allocate/deallocate 45the extension before/after setting/clearing the extension. 46*/ 47 48#ifndef TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H_INCLUDED_ 49#define TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H_INCLUDED_ 50 51#include "tlm_utils/instance_specific_extensions_int.h" 52 53namespace tlm_utils { 54 55//The templated private extension. Similar to normal extension 56template <typename T> 57class instance_specific_extension : public ispex_base { 58public: 59 virtual ~instance_specific_extension() {} 60 const static unsigned int priv_id; 61}; 62 63template <typename T> 64const unsigned int instance_specific_extension<T>::priv_id 65 = ispex_base::register_private_extension(typeid(T)); 66 67// ---------------------------------------------------------------------------- 68 69// This is the class that actually sits in the extension array 70// - we keep this small since that one gets allocated and deallocated all the times 71// - we keep the implementation in the header to avoid registration 72// of the extension itself unless used in the model 73class instance_specific_extension_carrier 74 : public tlm::tlm_extension<instance_specific_extension_carrier> 75{ 76 friend class instance_specific_extension_accessor; 77public: 78 instance_specific_extension_carrier() 79 : m_container() 80 {} 81 82 virtual tlm::tlm_extension_base* clone() const { 83 //we don't clone since private info is instance specific and associated to a given txn (the original) 84 //so the deep copied txn will be virgin in terms of private info 85 return NULL; 86 } 87 88 void copy_from(tlm::tlm_extension_base const &) { return; } 89 void free() { return; } 90 91private: 92 instance_specific_extension_container* m_container; 93}; 94 95// ---------------------------------------------------------------------------- 96 97template<typename T> 98instance_specific_extensions_per_accessor& 99instance_specific_extension_accessor::operator()(T& txn) 100{ 101 instance_specific_extension_carrier* carrier = NULL; 102 txn.get_extension(carrier); 103 if (!carrier) { 104 carrier = new instance_specific_extension_carrier(); 105 carrier->m_container = instance_specific_extension_container::create(); 106 carrier->m_container->attach_carrier(carrier, &txn, &release_carrier<T>); 107 txn.set_extension(carrier); 108 } 109 return *carrier->m_container->get_accessor(m_index); 110} 111 112template<typename T> 113void 114instance_specific_extension_accessor:: 115 release_carrier(instance_specific_extension_carrier* carrier, void* txn) 116{ 117 T* typed_txn = static_cast<T*>(txn); 118 typed_txn->clear_extension(carrier); 119 delete carrier; 120} 121 122} // namespace tlm_utils 123 124#endif // TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H_INCLUDED_ 125