summaryrefslogtreecommitdiff
path: root/src/systemc/ext/tlm_utils/instance_specific_extensions.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/ext/tlm_utils/instance_specific_extensions.h')
-rw-r--r--src/systemc/ext/tlm_utils/instance_specific_extensions.h124
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_