diff options
author | Gabe Black <gabeblack@google.com> | 2019-01-02 21:16:38 -0800 |
---|---|---|
committer | Gabe Black <gabeblack@google.com> | 2019-01-09 01:32:41 +0000 |
commit | 77165ae17ffa3c93b333e52e633b6237b1aca996 (patch) | |
tree | 2200fa6b5b0dd940eef48ad5669dcb0667cc0e9e /src/systemc/tlm_utils/instance_specific_extensions.cc | |
parent | 275d2779656fd2dd72762b2eb16a738d1b3b2b18 (diff) | |
download | gem5-77165ae17ffa3c93b333e52e633b6237b1aca996.tar.xz |
systemc: Rename tlm .cpp files to .cc and add SConscripts.
Change-Id: Ia30192b441dd34bc7165c6335386c88c0015fdf6
Reviewed-on: https://gem5-review.googlesource.com/c/15295
Reviewed-by: Anthony Gutierrez <anthony.gutierrez@amd.com>
Maintainer: Anthony Gutierrez <anthony.gutierrez@amd.com>
Diffstat (limited to 'src/systemc/tlm_utils/instance_specific_extensions.cc')
-rw-r--r-- | src/systemc/tlm_utils/instance_specific_extensions.cc | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/systemc/tlm_utils/instance_specific_extensions.cc b/src/systemc/tlm_utils/instance_specific_extensions.cc new file mode 100644 index 000000000..c0836cd67 --- /dev/null +++ b/src/systemc/tlm_utils/instance_specific_extensions.cc @@ -0,0 +1,266 @@ +/***************************************************************************** + + 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 <iostream> +#include <map> +#include <systemc> +#include <tlm> + +namespace tlm +{ + +template class tlm_array<tlm_utils::ispex_base *>; + +} // namespace tlm + +namespace tlm_utils +{ + +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() {} +}; + +ispex_registry *ispex_registry::instance_ = nullptr; + +} // 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(nullptr) {} + ~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; +}; + +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] : nullptr; +} + +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 *>(nullptr); + } +} + +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 |