| /***************************************************************************** |
| |
| Licensed to Accellera Systems Initiative Inc. (Accellera) under one or |
| more contributor license agreements. See the NOTICE file distributed |
| with this work for additional information regarding copyright ownership. |
| Accellera licenses this file to you under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with the |
| License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| implied. See the License for the specific language governing |
| permissions and limitations under the License. |
| |
| *****************************************************************************/ |
| |
| /* |
| Instance specific extensions, are extension that only a single instance of a |
| module may access. They are invisible to all other modules; they are private |
| to this instance so to speak. |
| |
| As they are only of value to a certain instance, this instance knows very |
| well when it needs them and when it does not need them any longer (usually |
| when a transaction passes through a module for the last time). It does not |
| have to care if anyone else in the system may still have a reference to the |
| transaction as this one is not able to access the extension anyway. |
| Therefore the instance is obliged to call set_extension when it wants to add a |
| private extension and clear_extension when it does not need it any more. |
| |
| To get access to an instance specifc extension the module must own a so called |
| instance_specific_extension_accessor that provides the exclusive access rights. |
| Assuming the instance_specific_extension_accessor of a given module is called |
| m_accessor and the transaction of which the private extension is about to be |
| accessed is called txn, then the calls have to be |
| |
| m_accessor(txn).set_extension(...); |
| or |
| m_accessor(txn).clear_extension(...); |
| |
| The owner of the private extension is responsible to allocate/deallocate |
| the extension before/after setting/clearing the extension. |
| */ |
| |
| #ifndef __SYSTEMC_EXT_TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H__ |
| #define __SYSTEMC_EXT_TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H__ |
| |
| #include "instance_specific_extensions_int.h" |
| |
| namespace tlm_utils |
| { |
| |
| // The templated private extension. Similar to normal extension. |
| template <typename T> |
| class instance_specific_extension : public ispex_base |
| { |
| public: |
| virtual ~instance_specific_extension() {} |
| const static unsigned int priv_id; |
| }; |
| |
| template <typename T> |
| const unsigned int instance_specific_extension<T>::priv_id = |
| ispex_base::register_private_extension(typeid(T)); |
| |
| // ---------------------------------------------------------------------------- |
| |
| // This is the class that actually sits in the extension array |
| // - We keep this small since that one gets allocated and deallocated all |
| // the times. |
| // - We keep the implementation in the header to avoid registration |
| // of the extension itself unless used in the model. |
| class instance_specific_extension_carrier : |
| public tlm::tlm_extension<instance_specific_extension_carrier> |
| { |
| friend class instance_specific_extension_accessor; |
| public: |
| instance_specific_extension_carrier() : m_container() {} |
| |
| virtual tlm::tlm_extension_base * |
| clone() const |
| { |
| // We don't clone since private info is instance specific and |
| // associated to a given txn (the original) so the deep copied txn |
| // will be virgin in terms of private info. |
| return NULL; |
| } |
| |
| void copy_from(tlm::tlm_extension_base const &) { return; } |
| void free() { return; } |
| |
| private: |
| instance_specific_extension_container *m_container; |
| }; |
| |
| // ---------------------------------------------------------------------------- |
| |
| template <typename T> |
| instance_specific_extensions_per_accessor & |
| instance_specific_extension_accessor::operator () (T &txn) |
| { |
| instance_specific_extension_carrier *carrier = NULL; |
| txn.get_extension(carrier); |
| if (!carrier) { |
| carrier = new instance_specific_extension_carrier(); |
| carrier->m_container = instance_specific_extension_container::create(); |
| carrier->m_container->attach_carrier( |
| carrier, &txn, &release_carrier<T>); |
| txn.set_extension(carrier); |
| } |
| return *carrier->m_container->get_accessor(m_index); |
| } |
| |
| template <typename T> |
| void |
| instance_specific_extension_accessor::release_carrier( |
| instance_specific_extension_carrier *carrier, void *txn) |
| { |
| T *typed_txn = static_cast<T *>(txn); |
| typed_txn->clear_extension(carrier); |
| delete carrier; |
| } |
| |
| } // namespace tlm_utils |
| |
| #endif /* __SYSTEMC_EXT_TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H__ */ |