summaryrefslogtreecommitdiff
path: root/src/systemc/tlm_utils/instance_specific_extensions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/tlm_utils/instance_specific_extensions.cpp')
-rw-r--r--src/systemc/tlm_utils/instance_specific_extensions.cpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/systemc/tlm_utils/instance_specific_extensions.cpp b/src/systemc/tlm_utils/instance_specific_extensions.cpp
new file mode 100644
index 000000000..9406dc8da
--- /dev/null
+++ b/src/systemc/tlm_utils/instance_specific_extensions.cpp
@@ -0,0 +1,249 @@
+/*****************************************************************************
+
+ 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.
+
+ *****************************************************************************/
+
+#include "tlm_utils/instance_specific_extensions_int.h"
+#include "sysc/utils/sc_typeindex.h" // sc_typeindex
+
+#include <map>
+#include <iostream>
+
+namespace tlm {
+template class SC_API tlm_array<tlm_utils::ispex_base*>;
+} // namespace tlm
+
+namespace tlm_utils {
+/* anonymous */ namespace {
+class ispex_registry // copied from tlm_gp.cpp
+{
+ typedef unsigned int key_type;
+ typedef std::map<sc_core::sc_type_index, key_type> type_map;
+public:
+ static ispex_registry& instance()
+ {
+ if (!instance_) // don't cleanup registry
+ instance_ = new ispex_registry();
+ return *instance_;
+ }
+
+ unsigned int register_extension(sc_core::sc_type_index type)
+ {
+ type_map::const_iterator it = ids_.find( type );
+
+ if( it == ids_.end() ) { // new extension - generate/store ID
+ type_map::value_type v( type, static_cast<key_type>(ids_.size()) );
+ ids_.insert( v );
+ return v.second;
+ }
+ return it->second;
+ }
+
+ static unsigned int max_num_extensions()
+ { return (instance_) ? instance().ids_.size() : 0; }
+
+private:
+ static ispex_registry* instance_;
+ type_map ids_;
+ ispex_registry() /* = default */ {}
+
+}; // class ispex_registry
+
+ispex_registry* ispex_registry::instance_ = NULL;
+} // anonymous namespace
+
+unsigned int
+ispex_base::register_private_extension(const std::type_info& type)
+{
+ return ispex_registry::instance().register_extension(type);
+}
+
+//Helper to do the numbering of private extension accessors
+static unsigned int max_num_ispex_accessors(bool increment=false)
+{
+ static unsigned int max_num = 0;
+ if (increment) ++max_num;
+ return max_num;
+}
+
+// ----------------------------------------------------------------------------
+
+//the pool for the container, plain as can be
+class instance_specific_extension_container_pool
+{
+ instance_specific_extension_container_pool()
+ : unused(NULL){}
+
+ ~instance_specific_extension_container_pool();
+
+public:
+ static instance_specific_extension_container_pool& instance()
+ {
+ static instance_specific_extension_container_pool inst;
+ return inst;
+ }
+
+ instance_specific_extension_container* create();
+ void free(instance_specific_extension_container*);
+
+private:
+ instance_specific_extension_container* unused;
+}; // class instance_specific_extension_container_pool
+
+instance_specific_extension_container*
+instance_specific_extension_container_pool::create()
+{
+ if (!unused) {
+ unused =new instance_specific_extension_container();
+ }
+ instance_specific_extension_container* tmp = unused;
+ unused = unused->next;
+ return tmp;
+}
+
+void
+instance_specific_extension_container_pool::
+ free(instance_specific_extension_container* cont)
+{
+ cont->next=unused;
+ unused=cont;
+}
+
+instance_specific_extension_container_pool::
+ ~instance_specific_extension_container_pool()
+{
+ while(unused) {
+ instance_specific_extension_container* tmp = unused;
+ unused=unused->next;
+ delete tmp;
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+instance_specific_extension_container*
+instance_specific_extension_container::create()
+{
+ return instance_specific_extension_container_pool::instance().create();
+}
+
+instance_specific_extension_container::instance_specific_extension_container()
+ : use_count(0)
+ , m_txn(NULL)
+ , m_release_fn(NULL)
+ , m_carrier(NULL)
+ , next(NULL)
+{
+ resize();
+}
+
+void
+instance_specific_extension_container::
+ attach_carrier(instance_specific_extension_carrier* carrier,
+ void* txn, release_fn* rel_fn)
+{
+ m_txn = txn;
+ m_release_fn = rel_fn;
+ m_carrier = carrier;
+}
+
+void
+instance_specific_extension_container::resize()
+{
+ m_ispex_per_accessor.resize( max_num_ispex_accessors() );
+
+ for (unsigned int i=0; i < m_ispex_per_accessor.size(); ++i) {
+ m_ispex_per_accessor[i] = new instance_specific_extensions_per_accessor(this);
+ m_ispex_per_accessor[i]->resize_extensions();
+ }
+}
+
+instance_specific_extension_container::
+ ~instance_specific_extension_container()
+{
+ for (unsigned int i=0; i<m_ispex_per_accessor.size(); ++i)
+ delete m_ispex_per_accessor[i];
+}
+
+void
+instance_specific_extension_container::inc_use_count()
+{
+ use_count++;
+}
+
+void
+instance_specific_extension_container::dec_use_count()
+{
+ if ((--use_count)==0) { // if this container isn't used any more
+ // we release the carrier extension
+ m_release_fn(m_carrier, m_txn);
+ // we send it back to our pool
+ instance_specific_extension_container_pool::instance().free(this);
+ }
+}
+
+instance_specific_extensions_per_accessor*
+instance_specific_extension_container::get_accessor(unsigned int idx)
+{
+ return m_ispex_per_accessor[idx];
+}
+
+// ----------------------------------------------------------------------------
+
+// non-templatized version with manual index:
+ispex_base*
+instance_specific_extensions_per_accessor::
+ set_extension(unsigned int index, ispex_base* ext)
+{
+ resize_extensions();
+ ispex_base* tmp = m_extensions[index];
+ m_extensions[index] = ext;
+ if (!tmp && ext) m_container->inc_use_count();
+ return tmp;
+}
+
+ispex_base*
+instance_specific_extensions_per_accessor::
+ get_extension(unsigned int index) const
+{
+ return (index < m_extensions.size()) ? m_extensions[index] : NULL;
+}
+
+void
+instance_specific_extensions_per_accessor::
+ clear_extension(unsigned int index)
+{
+ if (index < m_extensions.size())
+ {
+ if (m_extensions[index]) m_container->dec_use_count();
+ m_extensions[index] = static_cast<ispex_base*>(0);
+ }
+}
+
+void
+instance_specific_extensions_per_accessor::resize_extensions()
+{
+ m_extensions.expand(ispex_registry::max_num_extensions());
+}
+
+// ----------------------------------------------------------------------------
+
+instance_specific_extension_accessor::instance_specific_extension_accessor()
+ : m_index(max_num_ispex_accessors(true)-1)
+{}
+
+} // namespace tlm_utils