summaryrefslogtreecommitdiff
path: root/src/systemc/ext/tlm_core/2/generic_payload
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/ext/tlm_core/2/generic_payload')
-rw-r--r--src/systemc/ext/tlm_core/2/generic_payload/array.h98
-rw-r--r--src/systemc/ext/tlm_core/2/generic_payload/endian_conv.h941
-rw-r--r--src/systemc/ext/tlm_core/2/generic_payload/generic_payload.h28
-rw-r--r--src/systemc/ext/tlm_core/2/generic_payload/gp.h428
-rw-r--r--src/systemc/ext/tlm_core/2/generic_payload/helpers.h70
-rw-r--r--src/systemc/ext/tlm_core/2/generic_payload/phase.h117
6 files changed, 1682 insertions, 0 deletions
diff --git a/src/systemc/ext/tlm_core/2/generic_payload/array.h b/src/systemc/ext/tlm_core/2/generic_payload/array.h
new file mode 100644
index 000000000..1c6c724a4
--- /dev/null
+++ b/src/systemc/ext/tlm_core/2/generic_payload/array.h
@@ -0,0 +1,98 @@
+/*****************************************************************************
+
+ 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.
+
+ *****************************************************************************/
+
+#ifndef __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOADS_ARRAY_H__
+#define __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOADS_ARRAY_H__
+
+#include <vector>
+
+namespace tlm
+{
+
+// This implements a lean and fast array class that supports array expansion on
+// request. The class is primarily used in the tlm_generic_payload class for
+// storing the pointers to the extensions.
+//
+// Individual array elements can be accessed through the [] operators, and the
+// array length is returned by the size() method.
+//
+// The size can be dynamically expanded using the expand(uint) method. There
+// is no shrinking mechanism implemented, because the extension mechanism
+// does not require this feature. Bear in mind that calling the expand method
+// may invalidate all direct pointers into the array.
+
+
+// The tlm_array shall always be used with T=tlm_extension_base*.
+template <typename T>
+class tlm_array : private std::vector<T>
+{
+ private:
+ typedef std::vector<T> base_type;
+ typedef typename base_type::size_type size_type;
+
+ public:
+ tlm_array(size_type size=0) : base_type(size), m_entries() {}
+
+ // Operators for dereferencing:
+ using base_type::operator [];
+
+ // Array size:
+ using base_type::size;
+
+ // Expand the array if needed:
+ void
+ expand(size_type new_size)
+ {
+ if (new_size > size())
+ base_type::resize(new_size);
+ }
+
+ static const char *const kind_string;
+ const char *kind() const { return kind_string; }
+
+ // This function shall get a pointer to an array slot
+ // it stores this slot in a cache of active slots
+ void insert_in_cache(T *p) { m_entries.push_back(p - &(*this)[0]); }
+
+ // This functions clears all active slots of the array.
+ void
+ free_entire_cache()
+ {
+ while (m_entries.size()) {
+ // We make sure no one cleared the slot manually.
+ if ((*this)[m_entries.back()]) {
+ // ...and then we call free on the content of the slot
+ (*this)[m_entries.back()]->free();
+ }
+ // Afterwards we set the slot to NULL
+ (*this)[m_entries.back()] = nullptr;
+ m_entries.pop_back();
+ }
+ }
+
+ protected:
+ std::vector<size_type> m_entries;
+};
+
+template <typename T>
+const char *const tlm_array<T>::kind_string = "tlm_array";
+
+} // namespace tlm
+
+#endif /* __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOADS_ARRAY_H__ */
diff --git a/src/systemc/ext/tlm_core/2/generic_payload/endian_conv.h b/src/systemc/ext/tlm_core/2/generic_payload/endian_conv.h
new file mode 100644
index 000000000..50d5e6873
--- /dev/null
+++ b/src/systemc/ext/tlm_core/2/generic_payload/endian_conv.h
@@ -0,0 +1,941 @@
+/*****************************************************************************
+
+ 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.
+
+ *****************************************************************************/
+
+
+#ifndef __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_ENDIAN_CONV_H__
+#define __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_ENDIAN_CONV_H__
+
+#include <cstring> // std::memset
+
+#include "tlm_core/2/generic_payload/gp.h"
+
+namespace tlm
+{
+
+/*
+Tranaction-Level Modelling
+Endianness Helper Functions
+
+DESCRIPTION
+A set of functions for helping users to get the endianness
+right in their TLM models of system initiators. These functions are
+for use within an initiator. They can not be used as-is outside
+an initiator because the extension used to store context will not work
+if cascaded, and they do not respect the generic payload mutability
+rules. However this code may be easily copied and adapted for use
+in bridges, etc..
+
+These functions are not compulsory. There are other legitimate ways to
+achieve the same functionality. If extra information is available at
+compile time about the nature of an initiator's transactions, this can
+be exploited to accelerate simulations by creating further functions
+similar to those in this file. In general a functional transaction can be
+described in more than one way by a TLM-2 GP object.
+
+The functions convert the endianness of a GP object, either on request or
+response. They should only be used when the initiator's endianness
+does not match the host's endianness. They assume 'arithmetic mode'
+meaning that within a data word the byte order is always host-endian.
+For non-arithmetic mode initiators they can be used with a data word
+size of 1 byte.
+
+All the functions are templates, for example:
+
+template<class DATAWORD> inline void
+ to_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus)
+
+The template parameter provides the data word width. Having this as a class
+makes it easy to use it for copy and swap operations within the functions.
+If the assignment operator for this class is overloaded, the endianness
+conversion function may not have the desired effect.
+
+All the functions have the same signature except for different names.
+
+The principle is that a function to_hostendian_convtype() is called when the
+initiator-endian transaction is created, and the matching function
+from_hostendian_convtype() is called when the transaction is completed, for
+example before read data can be used. In some cases the from_ function is
+redundant but an empty function is provided anyway. It is strongly
+recommended that the from_ function is called, in case it ceases to be
+redundant in future versions of this code.
+
+No context needs to be managed outside the two functions, except that they
+must be called with the same template parameter and the same bus width.
+
+For initiator models that can not easily manage this context information,
+a single entry point for the from_ function is provided, which will be
+a little slower than calling the correct from_ function directly, as
+it can not be inlined.
+
+All functions assume power-of-2 bus and data word widths.
+
+Functions offered:
+
+0) A pair of functions that work for almost all TLM2 GP transactions. The
+only limitations are that data and bus widths should be powers of 2, and that
+the data length should be an integer number of streaming widths and that the
+streaming width should be an integer number of data words.
+These functions always allocate new data and byte enable buffers and copy
+data one byte at a time.
+ tlm_to_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus)
+ tlm_from_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus)
+
+1) A pair of functions that work for all transactions regardless of data and
+bus data sizes and address alignment except for the the following
+limitations:
+- byte-enables are supported only when byte-enable granularity is no finer
+than the data word (every data word is wholly enabled or wholly disabled)
+- byte-enable-length is not supported (if byte enables are present, the byte
+enable length must be equal to the data length).
+- streaming width is not supported
+- data word wider than bus word is not supported
+A new data buffer and a new byte enable buffer are always allocated. Byte
+enables are assumed to be needed even if not required for the original
+(unconverted) transaction. Data is copied to the new buffer on request
+(for writes) or on response (for reads). Copies are done word-by-word
+where possible.
+ tlm_to_hostendian_word(tlm_generic_payload *txn, int sizeof_databus)
+ tlm_from_hostendian_word(tlm_generic_payload *txn, int sizeof_databus)
+
+2) If the original transaction is both word and bus-aligned then this pair of
+functions can be used. It will complete faster than the generic function
+because the data reordering function is much simpler and no address
+conversion is required.
+The following limitations apply:
+- byte-enables are supported only when byte-enable granularity is no finer
+than the data word (every data word is wholly enabled or wholly disabled)
+- byte-enable-length is not supported (if byte enables are present, the byte
+enable length must be equal to the data length).
+- streaming width is not supported
+- data word wider than bus word is not supported
+- the transaction must be an integer number of bus words
+- the address must be aligned to the bus width
+ tlm_to_hostendian_aligned(tlm_generic_payload *txn, int sizeof_databus)
+ tlm_from_hostendian_aligned(tlm_generic_payload *txn, int sizeof_databus)
+
+3) For single word transactions that don't cross a bus word boundary it
+is always safe to work in-place and the conversion is very simple. Again,
+streaming width and byte-enable length are not supported, and byte-enables
+may not changes within a data word.
+ tlm_to_hostendian_single(tlm_generic_payload *txn, int sizeof_databus)
+ tlm_from_hostendian_single(tlm_generic_payload *txn, int sizeof_databus)
+
+4) A single entry point for accessing the correct from_ function without
+needing to store context.
+ tlm_from_hostendian(tlm_generic_payload *txn)
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// Generic Utilities
+
+class tlm_endian_context;
+
+class tlm_endian_context_pool
+{
+ public:
+ tlm_endian_context *first;
+ inline tlm_endian_context_pool();
+ inline ~tlm_endian_context_pool();
+ inline tlm_endian_context *pop();
+ inline void push(tlm_endian_context *c);
+};
+
+static tlm_endian_context_pool global_tlm_endian_context_pool;
+
+// an extension to keep the information needed for reconversion of response
+class tlm_endian_context : public tlm_extension<tlm_endian_context>
+{
+ public:
+ tlm_endian_context() : dbuf_size(0), bebuf_size(0) {}
+
+ ~tlm_endian_context() {
+ if (dbuf_size > 0)
+ delete [] new_dbuf;
+ if (bebuf_size > 0)
+ delete [] new_bebuf;
+ }
+
+ sc_dt::uint64 address; // Used by generic, word.
+ sc_dt::uint64 new_address; // Used by generic.
+ unsigned char *data_ptr; // Used by generic, word, aligned.
+ unsigned char *byte_enable; // Used by word.
+ int length; // Used by generic, word.
+ int stream_width; // Used by generic.
+
+ // Used by common entry point on response.
+ void (*from_f)(tlm_generic_payload *txn, unsigned int sizeof_databus);
+ int sizeof_databus;
+
+ // Reordering buffers for data and byte-enables.
+ unsigned char *new_dbuf, *new_bebuf;
+ int dbuf_size, bebuf_size;
+
+ void
+ establish_dbuf(int len)
+ {
+ if (len <= dbuf_size)
+ return;
+ if (dbuf_size > 0)
+ delete [] new_dbuf;
+ new_dbuf = new unsigned char[len];
+ dbuf_size = len;
+ }
+
+ void
+ establish_bebuf(int len)
+ {
+ if (len <= bebuf_size)
+ return;
+ if (bebuf_size > 0)
+ delete [] new_bebuf;
+ new_bebuf = new unsigned char[len];
+ bebuf_size = len;
+ }
+
+ // Required for extension management.
+ void free() { global_tlm_endian_context_pool.push(this); }
+ tlm_extension_base *clone() const { return 0; }
+ void copy_from(tlm_extension_base const &) { return; }
+
+ // For pooling.
+ tlm_endian_context *next;
+};
+
+// Assumptions about transaction contexts:
+// 1) only the address attribute of a transaction
+// is mutable. all other attributes are unchanged from the request to
+// response side conversion.
+// 2) the conversion functions in this file do not respect the mutability
+// rules and do not put the transaction back into its original state after
+// completion. so if the initiator has any cleaning up to do (eg of byte
+// enable buffers), it needs to store its own context. the transaction
+// returned to the initiator may contain pointers to data and byte enable
+// that can/must not be deleted.
+// 3) the conversion functions in this file use an extension to store
+// context information. they do not remove this extension. the initiator
+// should not remove it unless it deletes the generic payload
+// object.
+
+inline tlm_endian_context *
+establish_context(tlm_generic_payload *txn)
+{
+ tlm_endian_context *tc = txn->get_extension<tlm_endian_context>();
+ if (tc == 0) {
+ tc = global_tlm_endian_context_pool.pop();
+ txn->set_extension(tc);
+ }
+ return tc;
+}
+
+inline tlm_endian_context_pool::tlm_endian_context_pool() : first(0) {}
+
+inline tlm_endian_context_pool::~tlm_endian_context_pool()
+{
+ while (first != 0) {
+ tlm_endian_context *next = first->next;
+ delete first;
+ first = next;
+ }
+}
+
+tlm_endian_context *
+tlm_endian_context_pool::pop()
+{
+ if (first == 0)
+ return new tlm_endian_context;
+ tlm_endian_context *r = first;
+ first = first->next;
+ return r;
+}
+
+void tlm_endian_context_pool::push(tlm_endian_context *c)
+{
+ c->next = first;
+ first = c;
+}
+
+
+// A set of constants for efficient filling of byte enables.
+template <class D>
+class tlm_bool
+{
+ public:
+ static D TLM_TRUE;
+ static D TLM_FALSE;
+ static D
+ make_uchar_array(unsigned char c)
+ {
+ D d;
+ unsigned char *tmp = (unsigned char *)(&d);
+ for (ptrdiff_t i = 0; i != sizeof(D); i++)
+ tmp[i] = c; // 64BITFIX negligable risk but easy fix.
+ return d;
+ }
+
+ // Also provides an syntax-efficient tester, using a
+ // copy constuctor and an implicit cast to boolean.
+ tlm_bool(D &d) : b(*((unsigned char *)&d) != TLM_BYTE_DISABLED) {}
+ operator bool() const { return b; }
+ private:
+ bool b;
+};
+
+template<class D>
+D tlm_bool<D>::TLM_TRUE = tlm_bool<D>::make_uchar_array(TLM_BYTE_ENABLED);
+template<class D>
+D tlm_bool<D>::TLM_FALSE = tlm_bool<D>::make_uchar_array(TLM_BYTE_DISABLED);
+
+
+
+inline void
+copy_db0(unsigned char *src1, unsigned char *src2,
+ unsigned char *dest1, unsigned char *dest2)
+{
+ *dest1 = *src1;
+ *dest2 = *src2;
+}
+
+inline void
+copy_dbtrue0(unsigned char *src1, unsigned char * /* src2 */,
+ unsigned char *dest1, unsigned char *dest2)
+{
+ *dest1 = *src1;
+ *dest2 = TLM_BYTE_ENABLED;
+}
+
+inline void
+copy_btrue0(unsigned char * /* src1 */, unsigned char * /* src2 */,
+ unsigned char * /* dest1 */, unsigned char *dest2)
+{
+ *dest2 = TLM_BYTE_ENABLED;
+}
+
+inline void
+copy_b0(unsigned char * /* src1 */, unsigned char *src2,
+ unsigned char * /* dest1 */, unsigned char *dest2)
+{
+ *dest2 = *src2;
+}
+
+inline void
+copy_dbyb0(unsigned char *src1, unsigned char * /* src2 */,
+ unsigned char *dest1, unsigned char *dest2)
+{
+ if (*dest2 == TLM_BYTE_ENABLED)
+ *src1 = *dest1;
+}
+
+
+template <class D,
+ void COPY(unsigned char *he_d, unsigned char *he_b,
+ unsigned char *ie_d, unsigned char *ie_b)>
+inline void
+loop_generic0(int new_len, int new_stream_width, int orig_stream_width,
+ int sizeof_databus, sc_dt::uint64 orig_start_address,
+ sc_dt::uint64 new_start_address, int be_length,
+ unsigned char *ie_data, unsigned char *ie_be,
+ unsigned char *he_data, unsigned char *he_be)
+{
+ for (int orig_sword = 0, new_sword = 0; new_sword < new_len;
+ new_sword += new_stream_width, orig_sword += orig_stream_width) {
+ sc_dt::uint64 ie_addr = orig_start_address;
+ for (int orig_dword = orig_sword;
+ orig_dword < orig_sword + orig_stream_width;
+ orig_dword += sizeof(D)) {
+ for (int curr_byte = orig_dword + sizeof(D) - 1;
+ curr_byte >= orig_dword; curr_byte--) {
+ ptrdiff_t he_index = ((ie_addr++) ^ (sizeof_databus - 1)) -
+ new_start_address + new_sword; // 64BITFIX
+ COPY(ie_data + curr_byte,
+ // 64BITRISK no risk of overflow, always positive.
+ ie_be + (curr_byte % be_length),
+ he_data + he_index, he_be + he_index);
+ }
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function set (0): Response
+///////////////////////////////////////////////////////////////////////////////
+
+template <class DATAWORD>
+inline void
+tlm_from_hostendian_generic(tlm_generic_payload *txn,
+ unsigned int sizeof_databus)
+{
+ if (txn->is_read()) {
+ tlm_endian_context *tc =
+ txn->template get_extension<tlm_endian_context>();
+ loop_generic0<DATAWORD, &copy_dbyb0>(txn->get_data_length(),
+ txn->get_streaming_width(), tc->stream_width, sizeof_databus,
+ tc->address, tc->new_address, txn->get_data_length(),
+ tc->data_ptr, 0, txn->get_data_ptr(),
+ txn->get_byte_enable_ptr());
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function set (0): Request
+template <class DATAWORD>
+inline void
+tlm_to_hostendian_generic(tlm_generic_payload *txn,
+ unsigned int sizeof_databus)
+{
+ tlm_endian_context *tc = establish_context(txn);
+ tc->from_f = &(tlm_from_hostendian_generic<DATAWORD>);
+ tc->sizeof_databus = sizeof_databus;
+
+ // Calculate new size: nr stream words multiplied by big enough stream
+ // width.
+ int s_width = txn->get_streaming_width();
+ int length = txn->get_data_length();
+ if (s_width >= length)
+ s_width = length;
+ int nr_stream_words = length / s_width;
+
+ // Find out in which bus word the stream word starts and ends.
+ sc_dt::uint64 new_address = (txn->get_address() & ~(sizeof_databus - 1));
+ sc_dt::uint64 end_address = ((txn->get_address() + s_width - 1) &
+ ~(sizeof_databus - 1));
+
+ int new_stream_width = end_address - new_address + sizeof_databus;
+ int new_length = new_stream_width * nr_stream_words;
+
+ // Store context.
+ tc->data_ptr = txn->get_data_ptr();
+ tc->address = txn->get_address();
+ tc->new_address = new_address;
+ tc->stream_width = s_width;
+ unsigned char *orig_be = txn->get_byte_enable_ptr();
+ int orig_be_length = txn->get_byte_enable_length();
+
+ // Create data and byte-enable buffers.
+ txn->set_address(new_address);
+ tc->establish_dbuf(new_length);
+ txn->set_data_ptr(tc->new_dbuf);
+ tc->establish_bebuf(new_length);
+ txn->set_byte_enable_ptr(tc->new_bebuf);
+ std::memset(txn->get_byte_enable_ptr(), TLM_BYTE_DISABLED, new_length);
+ txn->set_streaming_width(new_stream_width);
+ txn->set_data_length(new_length);
+ txn->set_byte_enable_length(new_length);
+
+ // Copy data and/or byte enables.
+ if (txn->is_write()) {
+ if (orig_be == 0) {
+ loop_generic0<DATAWORD, &copy_dbtrue0>(
+ new_length, new_stream_width, s_width, sizeof_databus,
+ tc->address, new_address, new_length, tc->data_ptr, 0,
+ txn->get_data_ptr(), txn->get_byte_enable_ptr());
+ } else {
+ loop_generic0<DATAWORD, &copy_db0>(new_length, new_stream_width,
+ s_width, sizeof_databus, tc->address, new_address,
+ orig_be_length, tc->data_ptr, orig_be,
+ txn->get_data_ptr(), txn->get_byte_enable_ptr());
+ }
+ } else {
+ // Read transaction.
+ if (orig_be == 0) {
+ loop_generic0<DATAWORD, &copy_btrue0>(new_length,
+ new_stream_width, s_width, sizeof_databus, tc->address,
+ new_address, new_length, tc->data_ptr, 0,
+ txn->get_data_ptr(), txn->get_byte_enable_ptr());
+ } else {
+ loop_generic0<DATAWORD, &copy_b0>(new_length, new_stream_width,
+ s_width, sizeof_databus, tc->address, new_address,
+ orig_be_length, tc->data_ptr, orig_be,
+ txn->get_data_ptr(), txn->get_byte_enable_ptr());
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function set (1): Utilities
+///////////////////////////////////////////////////////////////////////////////
+
+template <class D>
+inline void
+copy_d1(unsigned char *src1, unsigned char *src2,
+ unsigned char *dest1, unsigned char *dest2)
+{
+ *((D *)dest1) = *((D *)src1);
+ *((D *)dest2) = tlm_bool<D>::TLM_TRUE;
+}
+
+template <class D>
+inline void
+copy_db1(unsigned char *src1, unsigned char *src2,
+ unsigned char *dest1, unsigned char *dest2)
+{
+ *((D *)dest1) = *((D *)src1);
+ *((D *)dest2) = *((D *)src2);
+}
+
+template <class D>
+inline void
+true_b1(unsigned char *src1, unsigned char *src2,
+ unsigned char *dest1, unsigned char *dest2)
+{
+ *((D *)dest2) = tlm_bool<D>::TLM_TRUE;
+}
+
+template <class D>
+inline void
+copy_b1(unsigned char *src1, unsigned char *src2,
+ unsigned char *dest1, unsigned char *dest2)
+{
+ *((D *)dest2) = *((D *)src2);
+}
+
+template <class D>
+inline void
+copy_dbyb1(unsigned char *src1, unsigned char *src2,
+ unsigned char *dest1, unsigned char *dest2)
+{
+ if (*src2 != TLM_BYTE_DISABLED)
+ *((D *)src1) = *((D *)dest1);
+}
+
+template <class D>
+inline void
+copy_dbytrue1(unsigned char *src1, unsigned char *src2,
+ unsigned char *dest1, unsigned char *dest2)
+{
+ *((D *)src1) = *((D *)dest1);
+}
+
+template<class D>
+inline void
+false_b1(unsigned char *dest1)
+{
+ *((D *)dest1) = tlm_bool<D>::TLM_FALSE;
+}
+
+template<class D>
+inline void
+no_b1(unsigned char *dest1)
+{}
+
+template<class D,
+ void COPY(unsigned char *src1, unsigned char *src2,
+ unsigned char *dest1, unsigned char *dest2),
+ void COPYuchar(unsigned char *src1, unsigned char *src2,
+ unsigned char *dest1, unsigned char *dest2),
+ void FILLFALSE(unsigned char *dest1),
+ void FILLFALSEuchar(unsigned char *dest1)>
+inline int
+loop_word1(int bytes_left, int len0, int lenN, int sizeof_databus,
+ unsigned char *start, unsigned char *end,
+ unsigned char *src, unsigned char *bsrc,
+ unsigned char *dest, unsigned char *bdest)
+{
+ ptrdiff_t d2b_src = bsrc - src; // 64BITFIX was int
+ ptrdiff_t d2b_dest = bdest - dest; // 64BITFIX was int
+ unsigned char *original_dest = dest;
+
+ while (true) {
+ // len0 bytes at start of a bus word.
+ if ((src >= start) && (src < end)) {
+ for (int i = 0; i < len0; i++) {
+ COPYuchar(src, src + d2b_src, dest, dest + d2b_dest);
+ src++;
+ dest++;
+ }
+ bytes_left -= len0;
+ if (bytes_left <= 0)
+ return int(dest - original_dest);
+ } else {
+ for (int i = 0; i < len0; i++) {
+ FILLFALSEuchar(dest + d2b_dest);
+ src++;
+ dest++;
+ }
+ }
+ src -= 2 * sizeof(D);
+
+ // Sequence of full data word fragments.
+ for (unsigned int i = 1; i < sizeof_databus / sizeof(D); i++) {
+ if ((src >= start) && (src < end)) {
+ COPY(src, src + d2b_src, dest, dest + d2b_dest);
+ bytes_left -= sizeof(D);
+ } else {
+ FILLFALSE(dest + d2b_dest);
+ }
+ dest += sizeof(D);
+ if (bytes_left <= 0)
+ return int(dest - original_dest);
+ src -= sizeof(D);
+ }
+
+ // lenN bytes at end of bus word.
+ if ((src >= start) && (src < end)) {
+ for (int i = 0; i < lenN; i++) {
+ COPYuchar(src, src + d2b_src, dest, dest + d2b_dest);
+ src++;
+ dest++;
+ }
+ bytes_left -= lenN;
+ if (bytes_left <= 0)
+ return int(dest - original_dest);
+ } else {
+ for (int i = 0; i < lenN; i++) {
+ FILLFALSEuchar(dest + d2b_dest);
+ src++;
+ dest++;
+ }
+ }
+ src += 2 * sizeof_databus;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function set (1): Response
+///////////////////////////////////////////////////////////////////////////////
+
+template <class DATAWORD>
+inline void
+tlm_from_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus)
+{
+ if (txn->is_read()) {
+ tlm_endian_context *tc =
+ txn->template get_extension<tlm_endian_context>();
+ sc_dt::uint64 b_mask = sizeof_databus - 1;
+ int d_mask = sizeof(DATAWORD) - 1;
+ int a_offset = static_cast<int>(tc->address & b_mask);
+ int len0 = (sizeof_databus - a_offset) & d_mask;
+ int lenN = sizeof(DATAWORD) - len0;
+ unsigned char *d_start = tc->data_ptr;
+ unsigned char *d_end =
+ ptrdiff_t(tc->length) + d_start; // 64BITFIX probably redundant
+ unsigned char *d =
+ ptrdiff_t(((sizeof_databus - a_offset) & ~d_mask) + lenN) +
+ d_start; // 64BITFIX probably redundant
+
+ // Iterate over transaction copying data qualified by byte-enables.
+ if (tc->byte_enable == 0) {
+ loop_word1<DATAWORD, &copy_dbytrue1<DATAWORD>,
+ &copy_dbytrue1<unsigned char>, &no_b1<DATAWORD>,
+ &no_b1<unsigned char>>(
+ tc->length, len0, lenN, sizeof_databus,
+ d_start, d_end, d, 0, txn->get_data_ptr(), 0);
+ } else {
+ loop_word1<DATAWORD, &copy_dbyb1<DATAWORD>,
+ &copy_dbyb1<unsigned char>, &no_b1<DATAWORD>,
+ &no_b1<unsigned char>>(
+ tc->length, len0, lenN, sizeof_databus,
+ d_start, d_end, d,
+ tc->byte_enable - d_start + d,
+ txn->get_data_ptr(), 0);
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function set (1): Request
+///////////////////////////////////////////////////////////////////////////////
+
+template <class DATAWORD>
+inline void
+tlm_to_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus)
+{
+ tlm_endian_context *tc = establish_context(txn);
+ tc->from_f = &(tlm_from_hostendian_word<DATAWORD>);
+ tc->sizeof_databus = sizeof_databus;
+
+ sc_dt::uint64 b_mask = sizeof_databus - 1;
+ int d_mask = sizeof(DATAWORD) - 1;
+ sc_dt::uint64 a_aligned = txn->get_address() & ~b_mask;
+ int a_offset = static_cast<int>(txn->get_address() & b_mask);
+ int len0 = (sizeof_databus - a_offset) & d_mask;
+ int lenN = sizeof(DATAWORD) - len0;
+ unsigned char *d_start = txn->get_data_ptr();
+ unsigned char *d_end =
+ ptrdiff_t(txn->get_data_length()) + d_start;
+ // 64BITFIX probably redundant.
+ unsigned char *d =
+ ptrdiff_t(((sizeof_databus - a_offset) & ~d_mask) + lenN) + d_start;
+ // 64BITFIX probably redundant.
+
+ // Create new data and byte enable buffers.
+ int long_enough = txn->get_data_length() + 2 * sizeof_databus;
+ tc->establish_dbuf(long_enough);
+ unsigned char *new_data = tc->new_dbuf;
+ tc->establish_bebuf(long_enough);
+ unsigned char *new_be = tc->new_bebuf;
+
+ if (txn->is_read()) {
+ tc->data_ptr = d_start;
+ tc->address = txn->get_address();
+ tc->byte_enable = txn->get_byte_enable_ptr();
+ tc->length = txn->get_data_length();
+ if (txn->get_byte_enable_ptr() == 0) {
+ // Iterate over transaction creating new byte enables from all-true
+ txn->set_data_length(
+ loop_word1<DATAWORD, &true_b1<DATAWORD>,
+ &true_b1<unsigned char>, &false_b1<DATAWORD>,
+ &false_b1<unsigned char>>(
+ txn->get_data_length(), len0, lenN,
+ sizeof_databus, d_start, d_end, d, 0,
+ new_data, new_be));
+ } else {
+ // iterate over transaction copying byte enables
+ txn->set_data_length(
+ loop_word1<DATAWORD, &copy_b1<DATAWORD>,
+ &copy_b1<unsigned char>, &false_b1<DATAWORD>,
+ &false_b1<unsigned char>>(
+ txn->get_data_length(), len0, lenN,
+ sizeof_databus, d_start, d_end, d,
+ txn->get_byte_enable_ptr() - d_start + d,
+ new_data, new_be));
+ }
+ } else {
+ // WRITE
+ if (txn->get_byte_enable_ptr() == 0) {
+ // Iterate over transaction copying data and creating new
+ // byte-enables.
+ txn->set_data_length(
+ loop_word1<DATAWORD, &copy_d1<DATAWORD>,
+ &copy_d1<unsigned char>, &false_b1<DATAWORD>,
+ &false_b1<unsigned char>>(
+ txn->get_data_length(), len0, lenN,
+ sizeof_databus, d_start, d_end, d, 0,
+ new_data, new_be));
+ } else {
+ // Iterate over transaction copying data and byte-enables.
+ txn->set_data_length(
+ loop_word1<DATAWORD, &copy_db1<DATAWORD>,
+ &copy_db1<unsigned char>, &false_b1<DATAWORD>,
+ &false_b1<unsigned char>>(
+ txn->get_data_length(), len0, lenN,
+ sizeof_databus, d_start, d_end, d,
+ txn->get_byte_enable_ptr() - d_start + d,
+ new_data, new_be));
+ }
+ }
+ txn->set_byte_enable_length(txn->get_data_length());
+ txn->set_streaming_width(txn->get_data_length());
+ txn->set_data_ptr(new_data);
+ txn->set_byte_enable_ptr(new_be);
+ txn->set_address(a_aligned);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function set (2): Utilities
+///////////////////////////////////////////////////////////////////////////////
+
+template <class D>
+inline void copy_d2(D *src1, D *src2, D *dest1, D *dest2) { *dest1 = *src1; }
+
+template <class D>
+inline void
+copy_db2(D *src1, D *src2, D *dest1, D *dest2)
+{
+ *dest1 = *src1;
+ *dest2 = *src2;
+}
+
+template <class D>
+inline void
+copy_dbyb2(D *src1, D *src2, D *dest1, D *dest2)
+{
+ if (tlm_bool<D>(*src2))
+ *dest1 = *src1;
+}
+
+template <class D, void COPY(D *src1, D *src2, D *dest1, D *dest2)>
+inline void
+loop_aligned2(D *src1, D *src2, D *dest1, D *dest2, int words,
+ int words_per_bus)
+{
+ // 64BITFIX was int and operands were cast to int.
+ ptrdiff_t src1to2 = (char *)src2 - (char *)src1;
+ // 64BITFIX was int and operands were cast to int.
+ ptrdiff_t dest1to2 = (char *)dest2 - (char *)dest1;
+
+ D *done = src1 + ptrdiff_t(words); // 64BITFIX.
+ D *bus_start = src1;
+ src1 += ptrdiff_t(words_per_bus - 1); // 64BITFIX.
+
+ while (true) {
+ COPY(src1, (D *)(src1to2 + (char *)src1), dest1,
+ (D *)(dest1to2 + (char *)dest1)); // 64BITFIX.
+ dest1++;
+ if ((--src1) < bus_start) {
+ bus_start += ptrdiff_t(words_per_bus); // 64BITFIX.
+ if (bus_start == done)
+ break;
+ src1 = bus_start + ptrdiff_t(words_per_bus - 1); // 64BITFIX.
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function set (2): Response
+///////////////////////////////////////////////////////////////////////////////
+
+template <class DATAWORD>
+inline void
+tlm_from_hostendian_aligned(
+ tlm_generic_payload *txn, unsigned int sizeof_databus)
+{
+ int words_per_bus = sizeof_databus / sizeof(DATAWORD);
+ if (words_per_bus == 1)
+ return;
+ int words = (txn->get_data_length()) / sizeof(DATAWORD);
+ tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>();
+
+ if (txn->get_byte_enable_ptr() == 0) {
+ // no byte enables
+ if (txn->is_read()) {
+ // RD without byte enables. Copy data to original buffer.
+ loop_aligned2<DATAWORD, &copy_d2<DATAWORD>>(
+ (DATAWORD *)(txn->get_data_ptr()), 0,
+ (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus);
+ }
+ } else {
+ // byte enables present
+ if (txn->is_read()) {
+ // RD with byte enables. Copy data qualified by byte-enables.
+ loop_aligned2<DATAWORD, &copy_dbyb2<DATAWORD>>(
+ (DATAWORD *)(txn->get_data_ptr()),
+ (DATAWORD *)(txn->get_byte_enable_ptr()),
+ (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus);
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function set (2): Request
+///////////////////////////////////////////////////////////////////////////////
+
+template <class DATAWORD>
+inline void
+tlm_to_hostendian_aligned(
+ tlm_generic_payload *txn, unsigned int sizeof_databus)
+{
+ tlm_endian_context *tc = establish_context(txn);
+ tc->from_f = &(tlm_from_hostendian_aligned<DATAWORD>);
+ tc->sizeof_databus = sizeof_databus;
+
+ int words_per_bus = sizeof_databus / sizeof(DATAWORD);
+ if (words_per_bus == 1)
+ return;
+ int words = (txn->get_data_length()) / sizeof(DATAWORD);
+
+ DATAWORD *original_be = (DATAWORD *)(txn->get_byte_enable_ptr());
+ DATAWORD *original_data = (DATAWORD *)(txn->get_data_ptr());
+
+ // Always allocate a new data buffer.
+ tc->establish_dbuf(txn->get_data_length());
+ txn->set_data_ptr(tc->new_dbuf);
+
+ if (original_be == 0) {
+ // No byte enables.
+ if (txn->is_write()) {
+ // WR no byte enables. Copy data.
+ loop_aligned2<DATAWORD, &copy_d2<DATAWORD>>(
+ original_data, 0, (DATAWORD *)(txn->get_data_ptr()), 0,
+ words, words_per_bus);
+ } else {
+ // RD no byte enables. Save original data pointer.
+ tc->data_ptr = (unsigned char *)original_data;
+ }
+ } else {
+ // Byte enables present.
+ // Allocate a new buffer for them.
+ tc->establish_bebuf(txn->get_data_length());
+ txn->set_byte_enable_ptr(tc->new_bebuf);
+ txn->set_byte_enable_length(txn->get_data_length());
+
+ if (txn->is_write()) {
+ // WR with byte enables. Copy data and BEs.
+ loop_aligned2<DATAWORD, &copy_db2<DATAWORD>>(
+ original_data, original_be,
+ (DATAWORD *)(txn->get_data_ptr()),
+ (DATAWORD *)(txn->get_byte_enable_ptr()),
+ words, words_per_bus);
+ } else {
+ // RD with byte enables. Save original data pointer.
+ tc->data_ptr = (unsigned char *)original_data;
+ // Copy byte enables to new buffer.
+ loop_aligned2<DATAWORD, &copy_d2<DATAWORD>>(
+ original_be, 0, (DATAWORD *)(txn->get_byte_enable_ptr()),
+ 0, words, words_per_bus);
+ }
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function set (3): Response
+///////////////////////////////////////////////////////////////////////////////
+
+template <class DATAWORD>
+inline void
+tlm_from_hostendian_single(
+ tlm_generic_payload *txn, unsigned int sizeof_databus)
+{}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function set (3): Request
+///////////////////////////////////////////////////////////////////////////////
+
+template <class DATAWORD>
+inline void
+tlm_to_hostendian_single(tlm_generic_payload *txn, unsigned int sizeof_databus)
+{
+ tlm_endian_context *tc = establish_context(txn);
+ tc->from_f = &(tlm_from_hostendian_single<DATAWORD>);
+ tc->sizeof_databus = sizeof_databus;
+
+ // Only need to change the address, always safe to work in-place.
+ sc_dt::uint64 mask = sizeof_databus - 1;
+ sc_dt::uint64 a = txn->get_address();
+ txn->set_address((a & ~mask) |
+ (sizeof_databus - (a & mask) - sizeof(DATAWORD)));
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// helper function which works for all responses
+///////////////////////////////////////////////////////////////////////////////
+
+inline void
+tlm_from_hostendian(tlm_generic_payload *txn)
+{
+ tlm_endian_context *tc = txn->get_extension<tlm_endian_context>();
+ (*(tc->from_f))(txn, tc->sizeof_databus);
+}
+
+} // namespace tlm
+
+#endif /* __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_ENDIAN_CONV_H__ */
diff --git a/src/systemc/ext/tlm_core/2/generic_payload/generic_payload.h b/src/systemc/ext/tlm_core/2/generic_payload/generic_payload.h
new file mode 100644
index 000000000..fb10b8809
--- /dev/null
+++ b/src/systemc/ext/tlm_core/2/generic_payload/generic_payload.h
@@ -0,0 +1,28 @@
+/*****************************************************************************
+
+ 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.
+
+ *****************************************************************************/
+
+#ifndef __SYSTEMC_EXT_TLM_CORE_2_GENERIC_GENERIC_PAYLOAD_H__
+#define __SYSTEMC_EXT_TLM_CORE_2_GENERIC_GENERIC_PAYLOAD_H__
+
+#include "tlm_core/2/generic_payload/endian_conv.h"
+#include "tlm_core/2/generic_payload/gp.h"
+#include "tlm_core/2/generic_payload/helpers.h"
+#include "tlm_core/2/generic_payload/phase.h"
+
+#endif /* __SYSTEMC_EXT_TLM_CORE_2_GENERIC_GENERIC_PAYLOAD_H__ */
diff --git a/src/systemc/ext/tlm_core/2/generic_payload/gp.h b/src/systemc/ext/tlm_core/2/generic_payload/gp.h
new file mode 100644
index 000000000..84bc25a01
--- /dev/null
+++ b/src/systemc/ext/tlm_core/2/generic_payload/gp.h
@@ -0,0 +1,428 @@
+/*****************************************************************************
+
+ 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.
+
+ *****************************************************************************/
+
+#ifndef __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_GP_H__
+#define __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_GP_H__
+
+#include <systemc>
+#include <typeinfo> // std::type_info
+
+#include "tlm_core/2/generic_payload/array.h"
+
+namespace tlm
+{
+
+class tlm_generic_payload;
+
+class tlm_mm_interface
+{
+ public:
+ virtual void free(tlm_generic_payload *) = 0;
+ virtual ~tlm_mm_interface() {}
+};
+
+//---------------------------------------------------------------------------
+// Classes and helpers for the extension mechanism
+//---------------------------------------------------------------------------
+// Helper function:
+unsigned int max_num_extensions();
+
+// This class can be used for storing pointers to the extension classes, used
+// in tlm_generic_payload:
+class tlm_extension_base
+{
+ public:
+ virtual tlm_extension_base *clone() const = 0;
+ virtual void free() { delete this; }
+ virtual void copy_from(tlm_extension_base const &) = 0;
+ protected:
+ virtual ~tlm_extension_base() {}
+ static unsigned int register_extension(const std::type_info &);
+};
+
+// Base class for all extension classes, derive your extension class in
+// the following way:
+// class my_extension : public tlm_extension<my_extension> { ...
+// This triggers proper extension registration during C++ static
+// contruction time. my_extension::ID will hold the unique index in the
+// tlm_generic_payload::m_extensions array.
+template <typename T>
+class tlm_extension : public tlm_extension_base
+{
+ public:
+ virtual tlm_extension_base *clone() const = 0;
+ virtual void copy_from(tlm_extension_base const &ext) = 0;
+ virtual ~tlm_extension() {}
+ const static unsigned int ID;
+};
+
+template <typename T>
+const unsigned int tlm_extension<T>::ID =
+ tlm_extension_base::register_extension(typeid(T));
+
+//---------------------------------------------------------------------------
+// enumeration types
+//---------------------------------------------------------------------------
+enum tlm_command
+{
+ TLM_READ_COMMAND,
+ TLM_WRITE_COMMAND,
+ TLM_IGNORE_COMMAND
+};
+
+enum tlm_response_status
+{
+ TLM_OK_RESPONSE = 1,
+ TLM_INCOMPLETE_RESPONSE = 0,
+ TLM_GENERIC_ERROR_RESPONSE = -1,
+ TLM_ADDRESS_ERROR_RESPONSE = -2,
+ TLM_COMMAND_ERROR_RESPONSE = -3,
+ TLM_BURST_ERROR_RESPONSE = -4,
+ TLM_BYTE_ENABLE_ERROR_RESPONSE = -5
+};
+
+enum tlm_gp_option
+{
+ TLM_MIN_PAYLOAD,
+ TLM_FULL_PAYLOAD,
+ TLM_FULL_PAYLOAD_ACCEPTED
+};
+
+#define TLM_BYTE_DISABLED 0x0
+#define TLM_BYTE_ENABLED 0xff
+
+//---------------------------------------------------------------------------
+// The generic payload class:
+//---------------------------------------------------------------------------
+
+extern template class tlm_array<tlm_extension_base *>;
+
+class tlm_generic_payload
+{
+ public:
+ tlm_generic_payload();
+ explicit tlm_generic_payload(tlm_mm_interface *mm);
+
+ void
+ acquire()
+ {
+ sc_assert(m_mm != 0);
+ m_ref_count++;
+ }
+
+ void
+ release()
+ {
+ sc_assert(m_mm != 0 && m_ref_count > 0);
+ if (--m_ref_count == 0)
+ m_mm->free(this);
+ }
+
+ int get_ref_count() const { return m_ref_count; }
+
+ void set_mm(tlm_mm_interface *mm) { m_mm = mm; }
+ bool has_mm() const { return m_mm != 0; }
+
+ void reset();
+
+ private:
+ // Disabled copy ctor and assignment operator.
+ tlm_generic_payload(const tlm_generic_payload &x);
+ tlm_generic_payload &operator = (const tlm_generic_payload &x);
+
+ public:
+ // Non-virtual deep-copying of the object.
+ void deep_copy_from(const tlm_generic_payload &other);
+
+ // 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 update_original_from(const tlm_generic_payload &other,
+ bool use_byte_enable_on_read=true);
+
+ void update_extensions_from(const tlm_generic_payload &other);
+
+ // 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 free_all_extensions();
+
+ virtual ~tlm_generic_payload();
+
+ //----------------
+ // API (including setters & getters).
+ //---------------
+
+ // Command related method.
+ bool is_read() const { return (m_command == TLM_READ_COMMAND); }
+ void set_read() { m_command = TLM_READ_COMMAND; }
+ bool is_write() const { return (m_command == TLM_WRITE_COMMAND); }
+ void set_write() { m_command = TLM_WRITE_COMMAND; }
+ tlm_command get_command() const { return m_command; }
+ void set_command(const tlm_command command) { m_command = command; }
+
+ // Address related methods.
+ sc_dt::uint64 get_address() const { return m_address; }
+ void set_address(const sc_dt::uint64 address) { m_address = address; }
+
+ // Data related methods.
+ unsigned char *get_data_ptr() const { return m_data; }
+ void set_data_ptr(unsigned char *data) { m_data = data; }
+
+ // Transaction length (in bytes) related methods.
+ unsigned int get_data_length() const { return m_length; }
+ void set_data_length(const unsigned int length) { m_length = length; }
+
+ // Response status related methods.
+ bool is_response_ok() const { return (m_response_status > 0); }
+ bool is_response_error() const { return (m_response_status <= 0); }
+ tlm_response_status
+ get_response_status() const
+ {
+ return m_response_status;
+ }
+ void
+ set_response_status(const tlm_response_status response_status)
+ {
+ m_response_status = response_status;
+ }
+ std::string get_response_string() const;
+
+ // Streaming related methods.
+ unsigned int get_streaming_width() const { return m_streaming_width; }
+ void
+ set_streaming_width(const unsigned int streaming_width)
+ {
+ m_streaming_width = streaming_width;
+ }
+
+ // Byte enable related methods.
+ unsigned char *get_byte_enable_ptr() const { return m_byte_enable; }
+ void
+ set_byte_enable_ptr(unsigned char *byte_enable)
+ {
+ m_byte_enable = byte_enable;
+ }
+ unsigned int
+ get_byte_enable_length() const
+ {
+ return m_byte_enable_length;
+ }
+ void
+ set_byte_enable_length(const unsigned int byte_enable_length)
+ {
+ m_byte_enable_length = byte_enable_length;
+ }
+
+ // This is the "DMI-hint" a slave can set this to true if it
+ // wants to indicate that a DMI request would be supported:
+ void
+ set_dmi_allowed(bool dmi_allowed)
+ {
+ m_dmi = dmi_allowed;
+ }
+ bool
+ is_dmi_allowed() const
+ {
+ return m_dmi;
+ }
+
+ // Use full set of attributes in DMI/debug?
+ tlm_gp_option get_gp_option() const { return m_gp_option; }
+ void set_gp_option(const tlm_gp_option gp_opt) { m_gp_option = gp_opt; }
+
+ private:
+ /* --------------------------------------------------------------------- */
+ /* Generic Payload attributes: */
+ /* --------------------------------------------------------------------- */
+ /* - m_command : Type of transaction. Three values supported: */
+ /* - TLM_WRITE_COMMAND */
+ /* - TLM_READ_COMMAND */
+ /* - TLM_IGNORE_COMMAND */
+ /* - m_address : Transaction base address (byte-addressing). */
+ /* - m_data : When m_command = TLM_WRITE_COMMAND contains a */
+ /* pointer to the data to be written in the target.*/
+ /* When m_command = TLM_READ_COMMAND contains a */
+ /* pointer where to copy the data read from the */
+ /* target. */
+ /* - m_length : Total number of bytes of the transaction. */
+ /* - m_response_status : This attribute indicates whether an error has */
+ /* occurred during the transaction. */
+ /* Values supported are: */
+ /* - TLM_OK_RESP */
+ /* - TLM_INCOMPLETE_RESP */
+ /* - TLM_GENERIC_ERROR_RESP */
+ /* - TLM_ADDRESS_ERROR_RESP */
+ /* - TLM_COMMAND_ERROR_RESP */
+ /* - TLM_BURST_ERROR_RESP */
+ /* - TLM_BYTE_ENABLE_ERROR_RESP */
+ /* */
+ /* - m_byte_enable : It can be used to create burst transfers where */
+ /* the address increment between each beat is greater */
+ /* than the word length of each beat, or to place */
+ /* words in selected byte lanes of a bus. */
+ /* - m_byte_enable_length : For a read or a write command, the target */
+ /* interpret the byte enable length attribute as the */
+ /* number of elements in the bytes enable array. */
+ /* - m_streaming_width : */
+ /* --------------------------------------------------------------------- */
+
+ sc_dt::uint64 m_address;
+ tlm_command m_command;
+ unsigned char *m_data;
+ unsigned int m_length;
+ tlm_response_status m_response_status;
+ bool m_dmi;
+ unsigned char *m_byte_enable;
+ unsigned int m_byte_enable_length;
+ unsigned int m_streaming_width;
+ tlm_gp_option m_gp_option;
+
+ public:
+ /* --------------------------------------------------------------------- */
+ /* Dynamic extension mechanism: */
+ /* --------------------------------------------------------------------- */
+ /* The extension mechanism is intended to enable initiator modules to */
+ /* optionally and transparently add data fields to the */
+ /* tlm_generic_payload. Target modules are free to check for extensions */
+ /* and may or may not react to the data in the extension fields. The */
+ /* definition of the extensions' semantics is solely in the */
+ /* responsibility of the user. */
+ /* */
+ /* The following rules apply: */
+ /* */
+ /* - Every extension class must be derived from tlm_extension, e.g.: */
+ /* class my_extension : public tlm_extension<my_extension> { ... } */
+ /* */
+ /* - A tlm_generic_payload object should be constructed after C++ */
+ /* static initialization time. This way it is guaranteed that the */
+ /* extension array is of sufficient size to hold all possible */
+ /* extensions. Alternatively, the initiator module can enforce a valid */
+ /* extension array size by calling the resize_extensions() method */
+ /* once before the first transaction with the payload object is */
+ /* initiated. */
+ /* */
+ /* - Initiators should use the the set_extension(e) or clear_extension(e)*/
+ /* methods for manipulating the extension array. The type of the */
+ /* argument must be a pointer to the specific registered extension */
+ /* type (my_extension in the above example) and is used to */
+ /* automatically locate the appropriate index in the array. */
+ /* */
+ /* - Targets can check for a specific extension by calling */
+ /* get_extension(e). e will point to zero if the extension is not */
+ /* present. */
+ /* */
+ /* --------------------------------------------------------------------- */
+
+ // Stick the pointer to an extension into the vector, return the
+ // previous value:
+ template <typename T>
+ T *
+ set_extension(T *ext)
+ {
+ return static_cast<T *>(set_extension(T::ID, ext));
+ }
+
+ // Non-templatized version with manual index:
+ tlm_extension_base *set_extension(
+ unsigned int index, tlm_extension_base *ext);
+
+ // Stick the pointer to an extension into the vector, return the
+ // previous value and schedule its release.
+ template <typename T>
+ T *
+ set_auto_extension(T *ext)
+ {
+ return static_cast<T *>(set_auto_extension(T::ID, ext));
+ }
+
+ // Non-templatized version with manual index:
+ tlm_extension_base *set_auto_extension(
+ unsigned int index, tlm_extension_base *ext);
+
+ // Check for an extension, ext will point to 0 if not present.
+ template <typename T>
+ void get_extension(T *& ext) const { ext = get_extension<T>(); }
+ template <typename T>
+ T *
+ get_extension() const
+ {
+ return static_cast<T*>(get_extension(T::ID));
+ }
+ // Non-templatized version with manual index:
+ tlm_extension_base *get_extension(unsigned int index) const;
+
+ // This call just removes the extension from the txn but does not
+ // call free() or tells the MM to do so it return false if there was
+ // active MM so you are now in an unsafe situation recommended use:
+ // when 100% sure there is no MM.
+ template <typename T>
+ void clear_extension(const T *ext) { clear_extension<T>(); }
+
+ // This call just removes the extension from the txn but does not
+ // call free() or tells the MM to do so it return false if there was
+ // active MM so you are now in an unsafe situation recommended use: when
+ // 100% sure there is no MM.
+ template <typename T>
+ void clear_extension() { clear_extension(T::ID); }
+
+ // This call removes the extension from the txn and does call free() or
+ // tells the MM to do so when the txn is finally done recommended use:
+ // when not sure there is no MM.
+ template <typename T>
+ void release_extension(T *ext)
+ {
+ release_extension<T>();
+ }
+
+ // This call removes the extension from the txn and does call free() or
+ // tells the MM to do so when the txn is finally done recommended use:
+ // when not sure there is no MM
+ template <typename T>
+ void release_extension()
+ {
+ release_extension(T::ID);
+ }
+
+ private:
+ // Non-templatized version with manual index
+ void clear_extension(unsigned int index);
+ // Non-templatized version with manual index
+ void release_extension(unsigned int index);
+
+ public:
+ // Make sure the extension array is large enough. Can be called once by
+ // an initiator module (before issuing the first transaction) to make
+ // sure that the extension array is of correct size. This is only needed
+ // if the initiator cannot guarantee that the generic payload object is
+ // allocated after C++ static construction time.
+ void resize_extensions();
+
+ private:
+ tlm_array<tlm_extension_base *> m_extensions;
+ tlm_mm_interface *m_mm;
+ unsigned int m_ref_count;
+};
+
+} // namespace tlm
+
+#endif /* __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_GP_H__ */
diff --git a/src/systemc/ext/tlm_core/2/generic_payload/helpers.h b/src/systemc/ext/tlm_core/2/generic_payload/helpers.h
new file mode 100644
index 000000000..4ec4faeeb
--- /dev/null
+++ b/src/systemc/ext/tlm_core/2/generic_payload/helpers.h
@@ -0,0 +1,70 @@
+/*****************************************************************************
+
+ 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.
+
+ *****************************************************************************/
+
+#ifndef __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_HELPERS_H__
+#define __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_HELPERS_H__
+
+namespace tlm
+{
+
+enum tlm_endianness { TLM_UNKNOWN_ENDIAN, TLM_LITTLE_ENDIAN, TLM_BIG_ENDIAN };
+
+inline tlm_endianness
+get_host_endianness()
+{
+ static tlm_endianness host_endianness = TLM_UNKNOWN_ENDIAN;
+
+ if (host_endianness == TLM_UNKNOWN_ENDIAN) {
+ unsigned int number = 1;
+ unsigned char *p_msb_or_lsb = (unsigned char *)&number;
+ host_endianness = (p_msb_or_lsb[0] == 0) ?
+ TLM_BIG_ENDIAN : TLM_LITTLE_ENDIAN;
+ }
+ return host_endianness;
+}
+
+inline bool
+host_has_little_endianness()
+{
+ static tlm_endianness host_endianness = TLM_UNKNOWN_ENDIAN;
+ static bool host_little_endian = false;
+
+ if (host_endianness == TLM_UNKNOWN_ENDIAN) {
+ unsigned int number = 1;
+ unsigned char *p_msb_or_lsb = (unsigned char *)&number;
+
+ host_little_endian = (p_msb_or_lsb[0] == 0) ? false : true;
+ }
+
+ return host_little_endian;
+}
+
+inline bool
+has_host_endianness(tlm_endianness endianness)
+{
+ if (host_has_little_endianness()) {
+ return endianness == TLM_LITTLE_ENDIAN;
+ } else {
+ return endianness == TLM_BIG_ENDIAN;
+ }
+}
+
+} // namespace tlm
+
+#endif /* __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_HELPERS_H__ */
diff --git a/src/systemc/ext/tlm_core/2/generic_payload/phase.h b/src/systemc/ext/tlm_core/2/generic_payload/phase.h
new file mode 100644
index 000000000..ca58b2f9d
--- /dev/null
+++ b/src/systemc/ext/tlm_core/2/generic_payload/phase.h
@@ -0,0 +1,117 @@
+/*****************************************************************************
+
+ 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.
+
+ *****************************************************************************/
+
+#ifndef __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_PHASE_H__
+#define __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_PHASE_H__
+
+#include <iostream>
+#include <typeinfo>
+#include <vector>
+
+#define SC_CONCAT_HELPER_(a, b) SC_CONCAT_HELPER_DEFERRED_(a, b)
+#define SC_CONCAT_HELPER_DEFERRED_(a, b) SC_CONCAT_HELPER_MORE_DEFERRED_(a, b)
+#define SC_CONCAT_HELPER_MORE_DEFERRED_(a, b) a ## b
+
+#define SC_STRINGIFY_HELPER_(a) SC_STRINGIFY_HELPER_DEFERRED_(a)
+#define SC_STRINGIFY_HELPER_DEFERRED_(a) SC_STRINGIFY_HELPER_MORE_DEFERRED_(a)
+#define SC_STRINGIFY_HELPER_MORE_DEFERRED_(a) #a
+
+namespace tlm
+{
+
+enum tlm_phase_enum
+{
+ UNINITIALIZED_PHASE = 0,
+ BEGIN_REQ = 1,
+ END_REQ,
+ BEGIN_RESP,
+ END_RESP
+};
+
+class tlm_phase
+{
+ public:
+ tlm_phase();
+ tlm_phase(unsigned int id);
+
+ tlm_phase(tlm_phase_enum standard);
+ tlm_phase &operator = (tlm_phase_enum standard);
+
+ operator unsigned int() const { return m_id; }
+ const char *get_name() const;
+
+ protected:
+ // Register extended phase.
+ tlm_phase(const std::type_info &type, const char *name);
+
+ private:
+ unsigned int m_id;
+};
+
+inline tlm_phase::tlm_phase() : m_id(UNINITIALIZED_PHASE) {}
+
+inline tlm_phase::tlm_phase(tlm_phase_enum standard) : m_id(standard) {}
+
+inline tlm_phase &
+tlm_phase::operator = (tlm_phase_enum standard)
+{
+ m_id = standard;
+ return *this;
+}
+
+inline std::ostream &
+operator << (std::ostream &s, const tlm_phase &p)
+{
+ s << p.get_name();
+ return s;
+}
+
+#define TLM_DECLARE_EXTENDED_PHASE(name_arg) \
+static class SC_CONCAT_HELPER_(tlm_phase_, name_arg) : \
+ public ::tlm::tlm_phase \
+{ \
+ typedef SC_CONCAT_HELPER_(tlm_phase_, name_arg) this_type; \
+ public: \
+ SC_CONCAT_HELPER_(tlm_phase_, name_arg)() : \
+ /* register extended phase */ \
+ ::tlm::tlm_phase(typeid(*this), SC_STRINGIFY_HELPER_(name_arg)) \
+ {} \
+ \
+ static const this_type &get_phase() \
+ /* needed only for IEEE 1666-2011 */ \
+ { \
+ static this_type this_; \
+ return this_; \
+ } \
+} const name_arg
+
+// for backwards-compatibility
+#define DECLARE_EXTENDED_PHASE(NameArg) TLM_DECLARE_EXTENDED_PHASE(NameArg)
+
+} // namespace tlm
+
+#undef SC_CONCAT_HELPER_
+#undef SC_CONCAT_HELPER_DEFERRED_
+#undef SC_CONCAT_HELPER_MORE_DEFERRED_
+
+#undef SC_STRINGIFY_HELPER_
+#undef SC_STRINGIFY_HELPER_DEFERRED_
+#undef SC_STRINGIFY_HELPER_MORE_DEFERRED_
+
+#endif /* __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_PHASE_H__ */