instance_specific_extensions.h revision 13513:bbf275465d3d
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 22module may access. They are invisible to all other modules; they are private 23to this instance so to speak. 24 25As they are only of value to a certain instance, this instance knows very 26well when it needs them and when it does not need them any longer (usually 27when a transaction passes through a module for the last time). It does not 28have to care if anyone else in the system may still have a reference to the 29transaction as this one is not able to access the extension anyway. 30Therefore the instance is obliged to call set_extension when it wants to add a 31private extension and clear_extension when it does not need it any more. 32 33To get access to an instance specifc extension the module must own a so called 34instance_specific_extension_accessor that provides the exclusive access rights. 35Assuming the instance_specific_extension_accessor of a given module is called 36m_accessor and the transaction of which the private extension is about to be 37accessed is called txn, then the calls have to be 38 39m_accessor(txn).set_extension(...); 40or 41m_accessor(txn).clear_extension(...); 42 43The owner of the private extension is responsible to allocate/deallocate 44the extension before/after setting/clearing the extension. 45*/ 46 47#ifndef __SYSTEMC_EXT_TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H__ 48#define __SYSTEMC_EXT_TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H__ 49 50#include "tlm_utils/instance_specific_extensions_int.h" 51 52namespace tlm_utils 53{ 54 55// The templated private extension. Similar to normal extension. 56template <typename T> 57class instance_specific_extension : public ispex_base 58{ 59 public: 60 virtual ~instance_specific_extension() {} 61 const static unsigned int priv_id; 62}; 63 64template <typename T> 65const unsigned int instance_specific_extension<T>::priv_id = 66 ispex_base::register_private_extension(typeid(T)); 67 68// ---------------------------------------------------------------------------- 69 70// This is the class that actually sits in the extension array 71// - We keep this small since that one gets allocated and deallocated all 72// the times. 73// - We keep the implementation in the header to avoid registration 74// of the extension itself unless used in the model. 75class instance_specific_extension_carrier : 76 public tlm::tlm_extension<instance_specific_extension_carrier> 77{ 78 friend class instance_specific_extension_accessor; 79 public: 80 instance_specific_extension_carrier() : m_container() {} 81 82 virtual tlm::tlm_extension_base * 83 clone() const 84 { 85 // We don't clone since private info is instance specific and 86 // associated to a given txn (the original) so the deep copied txn 87 // will be virgin in terms of private info. 88 return NULL; 89 } 90 91 void copy_from(tlm::tlm_extension_base const &) { return; } 92 void free() { return; } 93 94 private: 95 instance_specific_extension_container *m_container; 96}; 97 98// ---------------------------------------------------------------------------- 99 100template <typename T> 101instance_specific_extensions_per_accessor & 102instance_specific_extension_accessor::operator () (T &txn) 103{ 104 instance_specific_extension_carrier *carrier = NULL; 105 txn.get_extension(carrier); 106 if (!carrier) { 107 carrier = new instance_specific_extension_carrier(); 108 carrier->m_container = instance_specific_extension_container::create(); 109 carrier->m_container->attach_carrier( 110 carrier, &txn, &release_carrier<T>); 111 txn.set_extension(carrier); 112 } 113 return *carrier->m_container->get_accessor(m_index); 114} 115 116template <typename T> 117void 118instance_specific_extension_accessor::release_carrier( 119 instance_specific_extension_carrier *carrier, void *txn) 120{ 121 T *typed_txn = static_cast<T *>(txn); 122 typed_txn->clear_extension(carrier); 123 delete carrier; 124} 125 126} // namespace tlm_utils 127 128#endif /* __SYSTEMC_EXT_TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H__ */ 129