diff options
Diffstat (limited to 'src/systemc/ext/tlm_utils/instance_specific_extensions.h')
-rw-r--r-- | src/systemc/ext/tlm_utils/instance_specific_extensions.h | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/systemc/ext/tlm_utils/instance_specific_extensions.h b/src/systemc/ext/tlm_utils/instance_specific_extensions.h new file mode 100644 index 000000000..5d9f66b13 --- /dev/null +++ b/src/systemc/ext/tlm_utils/instance_specific_extensions.h @@ -0,0 +1,124 @@ +/***************************************************************************** + + 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 TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H_INCLUDED_ +#define TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H_INCLUDED_ + +#include "tlm_utils/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 // TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H_INCLUDED_ |