summaryrefslogtreecommitdiff
path: root/src/systemc/tlm_core/2
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/tlm_core/2')
-rw-r--r--src/systemc/tlm_core/2/generic_payload/SConscript32
-rw-r--r--src/systemc/tlm_core/2/generic_payload/gp.cc355
-rw-r--r--src/systemc/tlm_core/2/generic_payload/phase.cc111
-rw-r--r--src/systemc/tlm_core/2/quantum/SConscript31
-rw-r--r--src/systemc/tlm_core/2/quantum/global_quantum.cc49
5 files changed, 578 insertions, 0 deletions
diff --git a/src/systemc/tlm_core/2/generic_payload/SConscript b/src/systemc/tlm_core/2/generic_payload/SConscript
new file mode 100644
index 000000000..bea993450
--- /dev/null
+++ b/src/systemc/tlm_core/2/generic_payload/SConscript
@@ -0,0 +1,32 @@
+# Copyright 2018 Google, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+Import('*')
+
+if env['USE_SYSTEMC']:
+ Source('gp.cc')
+ Source('phase.cc')
diff --git a/src/systemc/tlm_core/2/generic_payload/gp.cc b/src/systemc/tlm_core/2/generic_payload/gp.cc
new file mode 100644
index 000000000..ff3c92bd9
--- /dev/null
+++ b/src/systemc/tlm_core/2/generic_payload/gp.cc
@@ -0,0 +1,355 @@
+/*****************************************************************************
+
+ 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 <cstring> // std::memcpy et.al.
+#include <map>
+#include <systemc>
+#include <tlm>
+
+using sc_core::sc_type_index;
+
+namespace tlm
+{
+
+template class tlm_array<tlm_extension_base *>;
+
+//---------------------------------------------------------------------------
+// Classes for the extension mechanism
+//---------------------------------------------------------------------------
+
+namespace
+{
+
+class tlm_extension_registry
+{
+ typedef unsigned int key_type;
+ typedef std::map<sc_core::sc_type_index, key_type> type_map;
+ public:
+ static tlm_extension_registry &
+ instance()
+ {
+ if (!instance_) {
+ // Don't cleanup registry.
+ instance_ = new tlm_extension_registry();
+ }
+ return *instance_;
+ }
+
+ unsigned int
+ register_extension(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 tlm_extension_registry *instance_;
+ type_map ids_;
+ tlm_extension_registry() {}
+
+};
+
+tlm_extension_registry *tlm_extension_registry::instance_ = NULL;
+
+} // anonymous namespace
+
+unsigned int
+max_num_extensions()
+{
+ return tlm_extension_registry::max_num_extensions();
+}
+
+unsigned int
+tlm_extension_base::register_extension(const std::type_info &type)
+{
+ return tlm_extension_registry::instance().register_extension(type);
+}
+
+//---------------------------------------------------------------------------
+// The generic payload class:
+//---------------------------------------------------------------------------
+
+tlm_generic_payload::tlm_generic_payload() : m_address(0),
+ m_command(TLM_IGNORE_COMMAND), m_data(0), m_length(0),
+ m_response_status(TLM_INCOMPLETE_RESPONSE), m_dmi(false), m_byte_enable(0),
+ m_byte_enable_length(0), m_streaming_width(0),
+ m_gp_option(TLM_MIN_PAYLOAD), m_extensions(max_num_extensions()), m_mm(0),
+ m_ref_count(0)
+{}
+
+tlm_generic_payload::tlm_generic_payload(tlm_mm_interface *mm): m_address(0),
+ m_command(TLM_IGNORE_COMMAND), m_data(0), m_length(0),
+ m_response_status(TLM_INCOMPLETE_RESPONSE), m_dmi(false), m_byte_enable(0),
+ m_byte_enable_length(0), m_streaming_width(0),
+ m_gp_option(TLM_MIN_PAYLOAD), m_extensions(max_num_extensions()), m_mm(mm),
+ m_ref_count(0)
+{}
+
+void
+tlm_generic_payload::reset()
+{
+ // Should the other members be reset too?
+ m_gp_option = TLM_MIN_PAYLOAD;
+ m_extensions.free_entire_cache();
+};
+
+// Non-virtual deep-copying of the object.
+void
+tlm_generic_payload::deep_copy_from(const tlm_generic_payload &other)
+{
+ m_command = other.get_command();
+ m_address = other.get_address();
+ m_length = other.get_data_length();
+ m_response_status = other.get_response_status();
+ m_byte_enable_length = other.get_byte_enable_length();
+ m_streaming_width = other.get_streaming_width();
+ m_gp_option = other.get_gp_option();
+ m_dmi = other.is_dmi_allowed();
+
+ // Deep copy data.
+ // There must be enough space in the target transaction!
+ if (m_data && other.m_data) {
+ std::memcpy(m_data, other.m_data, m_length);
+ }
+ // Deep copy byte enables.
+ // There must be enough space in the target transaction!
+ if (m_byte_enable && other.m_byte_enable) {
+ std::memcpy(m_byte_enable, other.m_byte_enable, m_byte_enable_length);
+ }
+ // Deep copy extensions (sticky and non-sticky).
+ if (m_extensions.size() < other.m_extensions.size()) {
+ m_extensions.expand(other.m_extensions.size());
+ }
+ for (unsigned int i = 0; i < other.m_extensions.size(); i++) {
+ if (other.m_extensions[i]) {
+ // Original has extension i.
+ if (!m_extensions[i]) {
+ // We don't: clone.
+ tlm_extension_base *ext = other.m_extensions[i]->clone();
+ if (ext) { // Extension may not be clonable.
+ if (has_mm()) {
+ // mm can take care of removing cloned extensions.
+ set_auto_extension(i, ext);
+ } else {
+ // no mm, user will call free_all_extensions().
+ set_extension(i, ext);
+ }
+ }
+ } else {
+ // We already have such extension. Copy original over it.
+ m_extensions[i]->copy_from(*other.m_extensions[i]);
+ }
+ }
+ }
+}
+
+// To update the state of the original generic payload from a deep copy.
+// Assumes that "other" was created from the original by calling
+// deep_copy_from. Argument use_byte_enable_on_read determines whether to use
+// or ignores byte enables when copying back the data array on a read command.
+
+void
+tlm_generic_payload::update_original_from(
+ const tlm_generic_payload &other, bool use_byte_enable_on_read)
+{
+ // Copy back extensions that are present on the original.
+ update_extensions_from(other);
+
+ // Copy back the response status and DMI hint attributes.
+ m_response_status = other.get_response_status();
+ m_dmi = other.is_dmi_allowed();
+
+ // Copy back the data array for a read command only deep_copy_from allowed
+ // null pointers, and so will we.
+ // We assume the arrays are the same size.
+ // We test for equal pointers in case the original and the copy share the
+ // same array.
+
+ if (is_read() && m_data && other.m_data && m_data != other.m_data) {
+ if (m_byte_enable && use_byte_enable_on_read) {
+ if (m_byte_enable_length == 8 && m_length % 8 == 0) {
+ // Optimized implementation copies 64-bit words by masking.
+ for (unsigned int i = 0; i < m_length; i += 8) {
+ typedef sc_dt::uint64 *u;
+ *reinterpret_cast<u>(&m_data[i]) &=
+ ~*reinterpret_cast<u>(m_byte_enable);
+ *reinterpret_cast<u>(&m_data[i]) |=
+ *reinterpret_cast<u>(&other.m_data[i]) &
+ *reinterpret_cast<u>(m_byte_enable);
+ }
+ } else if (m_byte_enable_length == 4 && m_length % 4 == 0) {
+ // Optimized implementation copies 32-bit words by masking.
+ for (unsigned int i = 0; i < m_length; i += 4) {
+ typedef unsigned int *u;
+ *reinterpret_cast<u>(&m_data[i]) &=
+ ~*reinterpret_cast<u>(m_byte_enable);
+ *reinterpret_cast<u>(&m_data[i]) |=
+ *reinterpret_cast<u>(&other.m_data[i]) &
+ *reinterpret_cast<u>(m_byte_enable);
+ }
+ } else {
+ // Unoptimized implementation.
+ for (unsigned int i = 0; i < m_length; i++) {
+ if (m_byte_enable[i % m_byte_enable_length])
+ m_data[i] = other.m_data[i];
+ }
+ }
+ } else {
+ std::memcpy(m_data, other.m_data, m_length);
+ }
+ }
+}
+
+void
+tlm_generic_payload::update_extensions_from(const tlm_generic_payload &other)
+{
+ // Deep copy extensions that are already present.
+ sc_assert(m_extensions.size() <= other.m_extensions.size());
+ for (unsigned int i = 0; i < m_extensions.size(); i++) {
+ if (other.m_extensions[i]) {
+ // Original has extension i.
+ if (m_extensions[i]) {
+ // We have it too. Copy.
+ m_extensions[i]->copy_from(*other.m_extensions[i]);
+ }
+ }
+ }
+}
+
+// Free all extensions. Useful when reusing a cloned transaction that doesn't
+// have memory manager. Normal and sticky extensions are freed and extension
+// array cleared.
+void
+tlm_generic_payload::free_all_extensions()
+{
+ m_extensions.free_entire_cache();
+ for (unsigned int i = 0; i < m_extensions.size(); i++) {
+ if (m_extensions[i]) {
+ m_extensions[i]->free();
+ m_extensions[i] = 0;
+ }
+ }
+}
+
+tlm_generic_payload::~tlm_generic_payload()
+{
+ for (unsigned int i = 0; i < m_extensions.size(); i++) {
+ if (m_extensions[i])
+ m_extensions[i]->free();
+ }
+}
+
+//----------------
+// API (including setters & getters)
+//---------------
+
+std::string
+tlm_generic_payload::get_response_string() const
+{
+ switch (m_response_status) {
+ case TLM_OK_RESPONSE:
+ return "TLM_OK_RESPONSE";
+ case TLM_INCOMPLETE_RESPONSE:
+ return "TLM_INCOMPLETE_RESPONSE";
+ case TLM_GENERIC_ERROR_RESPONSE:
+ return "TLM_GENERIC_ERROR_RESPONSE";
+ case TLM_ADDRESS_ERROR_RESPONSE:
+ return "TLM_ADDRESS_ERROR_RESPONSE";
+ case TLM_COMMAND_ERROR_RESPONSE:
+ return "TLM_COMMAND_ERROR_RESPONSE";
+ case TLM_BURST_ERROR_RESPONSE:
+ return "TLM_BURST_ERROR_RESPONSE";
+ case TLM_BYTE_ENABLE_ERROR_RESPONSE:
+ return "TLM_BYTE_ENABLE_ERROR_RESPONSE";
+ }
+ return "TLM_UNKNOWN_RESPONSE";
+}
+
+/* --------------------------------------------------------------------- */
+/* Dynamic extension mechanism: */
+/* --------------------------------------------------------------------- */
+
+tlm_extension_base *
+tlm_generic_payload::set_extension(unsigned int index, tlm_extension_base *ext)
+{
+ sc_assert(index < m_extensions.size());
+ tlm_extension_base *tmp = m_extensions[index];
+ m_extensions[index] = ext;
+ return tmp;
+}
+
+tlm_extension_base *
+tlm_generic_payload::set_auto_extension(
+ unsigned int index, tlm_extension_base *ext)
+{
+ sc_assert(index < m_extensions.size());
+ tlm_extension_base *tmp = m_extensions[index];
+ m_extensions[index] = ext;
+ if (!tmp)
+ m_extensions.insert_in_cache(&m_extensions[index]);
+ sc_assert(m_mm != 0);
+ return tmp;
+}
+
+tlm_extension_base *
+tlm_generic_payload::get_extension(unsigned int index) const
+{
+ sc_assert(index < m_extensions.size());
+ return m_extensions[index];
+}
+
+void
+tlm_generic_payload::clear_extension(unsigned int index)
+{
+ sc_assert(index < m_extensions.size());
+ m_extensions[index] = static_cast<tlm_extension_base *>(0);
+}
+
+void
+tlm_generic_payload::release_extension(unsigned int index)
+{
+ sc_assert(index < m_extensions.size());
+ if (m_mm) {
+ m_extensions.insert_in_cache(&m_extensions[index]);
+ } else {
+ m_extensions[index]->free();
+ m_extensions[index] = static_cast<tlm_extension_base *>(nullptr);
+ }
+}
+
+void
+tlm_generic_payload::resize_extensions()
+{
+ m_extensions.expand(max_num_extensions());
+}
+
+} // namespace tlm
diff --git a/src/systemc/tlm_core/2/generic_payload/phase.cc b/src/systemc/tlm_core/2/generic_payload/phase.cc
new file mode 100644
index 000000000..2c8b1e1a0
--- /dev/null
+++ b/src/systemc/tlm_core/2/generic_payload/phase.cc
@@ -0,0 +1,111 @@
+/*****************************************************************************
+
+ 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 <cstring>
+#include <map>
+#include <systemc>
+#include <tlm>
+
+using sc_core::sc_string_view;
+using sc_core::sc_type_index;
+
+namespace tlm
+{
+
+namespace
+{
+
+struct tlm_phase_registry
+{
+ typedef unsigned int key_type;
+
+ static tlm_phase_registry &
+ instance()
+ {
+ static tlm_phase_registry inst;
+ return inst;
+ }
+
+ unsigned int
+ register_phase(sc_type_index type, sc_string_view name)
+ {
+ type_map::const_iterator it = ids_.find(type);
+
+ if (name.empty()) {
+ SC_REPORT_FATAL( sc_core::SC_ID_INTERNAL_ERROR_,
+ "unexpected empty tlm_phase name" );
+ return UNINITIALIZED_PHASE;
+ }
+
+ if (it == ids_.end()) {
+ // new phase - generate/store ID and name
+ type_map::value_type v(type, static_cast<key_type>(names_.size()));
+ names_.push_back(name_table::value_type(name.data(), name.size()));
+ ids_.insert(v);
+ return v.second;
+ }
+
+ if (names_[it->second] != name) {
+ SC_REPORT_FATAL(sc_core::SC_ID_INTERNAL_ERROR_,
+ "tlm_phase registration failed: duplicate type info" );
+ sc_core::sc_abort();
+ }
+ return it->second;
+ }
+
+ const char *
+ get_name(key_type id) const
+ {
+ sc_assert(id < names_.size());
+ return names_[id].c_str();
+ }
+
+ private:
+ typedef std::map<sc_type_index, key_type> type_map;
+ typedef std::vector<std::string> name_table;
+
+ type_map ids_;
+ name_table names_;
+
+ tlm_phase_registry() : names_(END_RESP + 1)
+ {
+ names_[UNINITIALIZED_PHASE] = "UNINITIALIZED_PHASE";
+ names_[BEGIN_REQ] = "BEGIN_REQ";
+ names_[END_REQ] = "END_REQ";
+ names_[BEGIN_RESP] = "BEGIN_RESP";
+ names_[END_RESP] = "END_RESP";
+ }
+};
+
+} // anonymous namespace
+
+tlm_phase::tlm_phase(unsigned int id) : m_id(id)
+{}
+
+tlm_phase::tlm_phase(const std::type_info &type, const char *name) :
+ m_id(tlm_phase_registry::instance().register_phase(type, name))
+{}
+
+const char *
+tlm_phase::get_name() const
+{
+ return tlm_phase_registry::instance().get_name(m_id);
+}
+
+} // namespace tlm
diff --git a/src/systemc/tlm_core/2/quantum/SConscript b/src/systemc/tlm_core/2/quantum/SConscript
new file mode 100644
index 000000000..a1580471f
--- /dev/null
+++ b/src/systemc/tlm_core/2/quantum/SConscript
@@ -0,0 +1,31 @@
+# Copyright 2018 Google, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+Import('*')
+
+if env['USE_SYSTEMC']:
+ Source('global_quantum.cc')
diff --git a/src/systemc/tlm_core/2/quantum/global_quantum.cc b/src/systemc/tlm_core/2/quantum/global_quantum.cc
new file mode 100644
index 000000000..7ba44e3cb
--- /dev/null
+++ b/src/systemc/tlm_core/2/quantum/global_quantum.cc
@@ -0,0 +1,49 @@
+/*****************************************************************************
+
+ 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 <systemc>
+#include <tlm>
+
+namespace tlm
+{
+
+tlm_global_quantum::tlm_global_quantum() :
+ m_global_quantum(sc_core::SC_ZERO_TIME)
+{}
+
+tlm_global_quantum &
+tlm_global_quantum::instance()
+{
+ static tlm_global_quantum instance_;
+ return instance_;
+}
+
+sc_core::sc_time
+tlm_global_quantum::compute_local_quantum()
+{
+ if (m_global_quantum != sc_core::SC_ZERO_TIME) {
+ const sc_core::sc_time current = sc_core::sc_time_stamp();
+ const sc_core::sc_time g_quant = m_global_quantum;
+ return g_quant - (current % g_quant);
+ } else {
+ return sc_core::SC_ZERO_TIME;
+ }
+}
+
+} // namespace tlm