diff options
Diffstat (limited to 'src/systemc/ext/tlm_core/tlm_2')
17 files changed, 2875 insertions, 0 deletions
diff --git a/src/systemc/ext/tlm_core/tlm_2/README.txt b/src/systemc/ext/tlm_core/tlm_2/README.txt new file mode 100644 index 000000000..cb02af2d8 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/README.txt @@ -0,0 +1,111 @@ +TLM-2.0 interoperability layer header files +=========================================== + +Dir: include/tlm_core/tlm_2/ + +SubDirs: tlm_2_interfaces/ + tlm_generic_payload/ + tlm_quantum/ + tlm_sockets + +Files: README.txt + tlm_version.h + + +Comments +======== + +User code should only #include the tlm or tlm.h header file in the include/ +directory and avoid including any of the include files in this directory +directly. All objects defined in this file hierarchy are in the tlm namespace. + +tlm_version.h contains the definitions for the version string and integer values + +The header files are organizated, by subdirectory, as follows: + + +tlm_2_interfaces/ +----------------- + +Contains the TLM-2.0 core interfaces + +Files: + tlm_2_interfaces.h (includes the other header files in this directory ) + tlm_fw_bw_ifs.h (defines the TLM 2.0 interface API's: + tlm_fw_nonblocking_transport_if + tlm_bw_nonblocking_transport_if + tlm_blocking_transport_if + tlm_fw_direct_mem_if + tlm_bw_direct_mem_if + tlm_transport_dbg_if + the enumeration type + tlm_sync_enum + and the TLM 2.0 standard interfaces using the API's + tlm_fw_transport_if + tlm_bw_transport_if ) + tlm_dmi.h (defines tlm_dmi) + + +tlm_generic_payload/ +-------------------- + +Contains the TLM-2.0 generic payload and associated classes and helper functions + +Files: + tlm_generic_payload.h ( includes the other header files in this directory) + tlm_gp.h (defines the TLM 2.0 generic payload classes: + tlm_generic_payload + tlm_extension + tlm_extension_base + tlm_mm_interface + and the enumeration types + tlm_command + tlm_response_status ) + tlm_array.h (defines array class used by the extention + mechanism ) + tlm_endian_conv.h (defines the implementation for the endianness + helper functions: + tlm_to_hostendian_generic() + tlm_from_hostendian_generic() + tlm_to_hostendian_word() + tlm_from_hostendian_word() + tlm_to_hostendian_aligned() + tlm_from_hostendian_aligned() + tlm_to_hostendian_single() + tlm_from_hostendian_single() ) + + tlm_helpers.h (defines the helper functions to determine the + hostendianness: + get_host_endianness() + host_has_little_endianness() + has_host_endianness() + and defines the enumeration type: + tlm_endianness + tlm_phase.h (defines tlm_phase as an extendable enum type) + + +tlm_sockets/ +------------ + +Contains the standard TLM-2.0 initiator and target sockets (which are used as +the base classes for the convenience sockets in tlm_utils) + +Files: + tlm_sockets.h (includes the other header files in this directory) + tlm_initiator_socket.h (defines the initiator sockets: + tlm_initiator_socket_base + tlm_initiator_socket_b + tlm_initiator_socket + tlm_target_socket.h (defines the target sockets: + tlm_target_socket_base + tlm_target_socket_b + tlm_target_socket + + +tlm_quantum/ +------------ +This contains the global quantum. (The quantum keeper is in tlm_utils) + +Files: + tlm_quantum.h ( includes the other header file in this directory ) + tlm_global_quantum.h ( defines tlm_global_quantum ) diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h new file mode 100644 index 000000000..8a0c543c8 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h @@ -0,0 +1,27 @@ +/***************************************************************************** + + 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 __TLM_2_INTERFACES_H__ +#define __TLM_2_INTERFACES_H__ + +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h" +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" + +#endif + diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h new file mode 100644 index 000000000..d7c3304eb --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h @@ -0,0 +1,114 @@ +/***************************************************************************** + + 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 __TLM_DMI_H__ +#define __TLM_DMI_H__ + +#include <systemc> + +namespace tlm { + +class tlm_dmi +{ + public: + + // Enum for indicating the access granted to the initiator. + // The initiator uses gp.m_command to indicate it intention (read/write) + // The target is allowed to promote DMI_ACCESS_READ or DMI_ACCESS_WRITE + // requests to dmi_access_read_write. + + enum dmi_access_e + { DMI_ACCESS_NONE = 0x00 // no access + , DMI_ACCESS_READ = 0x01 // read access + , DMI_ACCESS_WRITE = 0x02 // write access + , DMI_ACCESS_READ_WRITE = DMI_ACCESS_READ | DMI_ACCESS_WRITE // read/write access + }; + + tlm_dmi (void) + { + init(); + } + + void init (void) + { + m_dmi_ptr = 0x0; + m_dmi_start_address = 0x0; + m_dmi_end_address = (sc_dt::uint64)(-1); + m_dmi_access = DMI_ACCESS_NONE; + m_dmi_read_latency = sc_core::SC_ZERO_TIME; + m_dmi_write_latency = sc_core::SC_ZERO_TIME; + } + + unsigned char* get_dmi_ptr (void) const {return m_dmi_ptr;} + sc_dt::uint64 get_start_address (void) const {return m_dmi_start_address;} + sc_dt::uint64 get_end_address (void) const {return m_dmi_end_address;} + sc_core::sc_time get_read_latency (void) const {return m_dmi_read_latency;} + sc_core::sc_time get_write_latency (void) const {return m_dmi_write_latency;} + dmi_access_e get_granted_access (void) const {return m_dmi_access;} + bool is_none_allowed (void) const {return m_dmi_access == DMI_ACCESS_NONE;} + bool is_read_allowed (void) const {return (m_dmi_access & DMI_ACCESS_READ) == DMI_ACCESS_READ;} + bool is_write_allowed (void) const {return (m_dmi_access & DMI_ACCESS_WRITE) == DMI_ACCESS_WRITE;} + bool is_read_write_allowed (void) const {return (m_dmi_access & DMI_ACCESS_READ_WRITE) == DMI_ACCESS_READ_WRITE;} + + void set_dmi_ptr (unsigned char* p) {m_dmi_ptr = p;} + void set_start_address (sc_dt::uint64 addr) {m_dmi_start_address = addr;} + void set_end_address (sc_dt::uint64 addr) {m_dmi_end_address = addr;} + void set_read_latency (sc_core::sc_time t) {m_dmi_read_latency = t;} + void set_write_latency (sc_core::sc_time t) {m_dmi_write_latency = t;} + void set_granted_access (dmi_access_e a) {m_dmi_access = a;} + void allow_none (void) {m_dmi_access = DMI_ACCESS_NONE;} + void allow_read (void) {m_dmi_access = DMI_ACCESS_READ;} + void allow_write (void) {m_dmi_access = DMI_ACCESS_WRITE;} + void allow_read_write (void) {m_dmi_access = DMI_ACCESS_READ_WRITE;} + + private: + + // If the forward call is successful, the target returns the dmi_ptr, + // which must point to the data element corresponding to the + // dmi_start_address. The data is organized as a byte array with the + // endianness of the target (endianness member of the tlm_dmi struct). + + unsigned char* m_dmi_ptr; + + // The absolute start and end addresses of the DMI region. If the decoder + // logic in the interconnect changes the address field e.g. by masking, the + // interconnect is responsible to transform the relative address back to an + // absolute address again. + + sc_dt::uint64 m_dmi_start_address; + sc_dt::uint64 m_dmi_end_address; + + // Granted access + + dmi_access_e m_dmi_access; + + // These members define the latency of read/write transactions. The + // initiator must initialize these members to zero before requesting a + // dmi pointer, because both the interconnect as well as the target can + // add to the total transaction latency. + // Depending on the 'type' attribute only one, or both of these attributes + // will be valid. + + sc_core::sc_time m_dmi_read_latency; + sc_core::sc_time m_dmi_write_latency; +}; + +} // namespace tlm + +#endif /* TLM_DMI_HEADER */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h new file mode 100644 index 000000000..59e81c658 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h @@ -0,0 +1,223 @@ +/***************************************************************************** + + 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 __TLM_FW_BW_IFS_H__ +#define __TLM_FW_BW_IFS_H__ + +#include <systemc> +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h" +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h" + +namespace tlm { + +enum tlm_sync_enum { TLM_ACCEPTED, TLM_UPDATED, TLM_COMPLETED }; + +//////////////////////////////////////////////////////////////////////////// +// Basic interfaces +//////////////////////////////////////////////////////////////////////////// +template <typename TRANS = tlm_generic_payload, + typename PHASE = tlm_phase> +class tlm_fw_nonblocking_transport_if : public virtual sc_core::sc_interface { +public: + virtual tlm_sync_enum nb_transport_fw(TRANS& trans, + PHASE& phase, + sc_core::sc_time& t) = 0; +}; + +template <typename TRANS = tlm_generic_payload, + typename PHASE = tlm_phase> +class tlm_bw_nonblocking_transport_if : public virtual sc_core::sc_interface { +public: + virtual tlm_sync_enum nb_transport_bw(TRANS& trans, + PHASE& phase, + sc_core::sc_time& t) = 0; +}; + +template <typename TRANS = tlm_generic_payload> +class tlm_blocking_transport_if : public virtual sc_core::sc_interface { +public: + virtual void b_transport(TRANS& trans, + sc_core::sc_time& t) = 0; +}; + +////////////////////////////////////////////////////////////////////////// +// DMI interfaces for getting and invalidating DMI pointers: +////////////////////////////////////////////////////////////////////////// + +// The semantics of the forward interface are as follows: +// +// - An initiator that wants to get direct access to a target's memory region +// can call the get_direct_mem_ptr method with the 'trans' parameter set to +// the address that it wants to gain access to. It sets the trans.m_command +// to specify if the initiator intended use (read or write) +// to the target's DMI region. The initiator is responsible for calling the +// method with a freshly initialized tlm_dmi object either by using a newly +// constructed object, or by calling an existing object's init() method. +// - Although a reference to a complete 'TRANS' type is passed to the get_ +// direct_mem_ptr call, only the address command, and extension fields are of +// interest in most cases. +// - Read and write ranges are not necessarily identical. If they are, a target +// can specify that the range is valid for all accesses with the tlm_data +// m_type attribute in the. +// - The interconnect, if any, needs to decode the address and forward the +// call to the corresponding target. It needs to handle the address exactly +// as the target would expect on a transaction call, e.g. mask the address +// according to the target's address width. +// - If the target supports DMI access for the given address, it sets the +// data fields in the DMI struct and returns true. +// - If a target does not support DMI access it needs to return false. +// The target can either set the correct address range in the DMI struct +// to indicate the memory region where DMI is disallowed, or it can specify +// the complete address range if it doesn't know it's memory range. In this +// case the interconnect is responsible for clipping the address range to +// the correct range that the target serves. +// - The interconnect must always translate the addresses to the initiator's +// address space. This must be the inverse operation of what the +// interconnect needed to do when forwarding the call. In case the +// component wants to change any member of the tlm_dmi object, e.g. for +// its own latency to the target's latency, it must only do so *after* the +// target has been called. The target is always allowed to overwrite all +// values in the tlm_dmi object. +// - In case the slave returned with an invalid region the bus/interconnect +// must fill in the complete address region for the particular slave in the +// DMI data structure. +// +// DMI hint optimization: +// +// Initiators may use the DMI hint in the tlm_generic_payload to avoid +// unnecessary DMI attempts. The recommended sequence of interface +// method calls would be: +// +// - The initiator first tries to check if it has a valid DMI region for the +// address that it wants to access next. +// - If not, it performs a normal transaction. +// - If the DMI hint in this transaction is true, the initiator can try and +// get the DMI region. +// +// Note that the DMI hint optimization is completely optional and every +// initiator model is free to ignore the DMI hint. However, a target is +// required to set the DMI hint to true if a DMI request on the given address +// with the given transaction type (read or write) would have succeeded. + +template <typename TRANS = tlm_generic_payload> +class tlm_fw_direct_mem_if : public virtual sc_core::sc_interface +{ +public: + virtual bool get_direct_mem_ptr(TRANS& trans, + tlm_dmi& dmi_data) = 0; +}; + +// The semantics of the backwards call is as follows: +// +// - An interconnect component or a target is required to invalidate all +// affected DMI regions whenever any change in the regions take place. +// The exact rule is that a component must invalidate all those DMI regions +// that it already reported, if it would answer the same DMI request +// with any member of the tlm_dmi data structure set differently. +// - An interconnect component must forward the invalidate_direct_mem_ptr call +// to all initiators that could potentially have a DMI pointer to the region +// specified in the method arguments. A safe implementation is to call +// every attached initiator. +// - An interconnect component must transform the address region of an +// incoming invalidate_direct_mem_ptr to the corresponding address space +// for the initiators. Basically, this is the same address transformation +// that the interconnect does on the DMI ranges on the forward direction. +// - Each initiator must check if it has a pointer to the given region and +// throw this away. It is recommended that the initiator throws away all DMI +// regions that have any overlap with the given regions, but this is not a +// hard requirement. +// +// - A full DMI pointer invalidation, e.g. for a bus remap can be signaled +// by setting the range: 0x0 - 0xffffffffffffffffull = (sc_dt::uint64)-1 +// - An initiator must throw away all DMI pointers in this case. +// +// - Under no circumstances a model is allowed to call the get_direct_mem_ptr +// from within the invalidate_direct_mem_ptr method, directly or indirectly. +// +class tlm_bw_direct_mem_if : public virtual sc_core::sc_interface +{ +public: + virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) = 0; +}; + +///////////////////////////////////////////////////////////////////// +// debug interface for memory access +///////////////////////////////////////////////////////////////////// +// +// This interface can be used to gain access to a targets memory or registers +// in a non-intrusive manner. No side effects, waits or event notifications +// must happen in the course of the method. +// +// Semantics: +// - The initiator calls the transport_dbg method with transaction 'trans' as +// argument. The commonly used parts of trans for debug are: +// . address: The start address that it wants to peek or poke. +// . length: The number of bytes that it requests to read or write. +// . command: Indicates a read or write access. +// . data: A pointer to the initiator-allocated data buffer, which must +// be at least num_bytes large. The data is always organized in +// the endianness of the machine. +// . extensions: Any extension that could affect the transaction. +// - The interconnect, if any, will decode the address and forward the call to +// the appropriate target. +// - The target must return the number of successfully transmitted bytes, where +// this number must be <= num_bytes. Thus, a target can safely return 0 if it +// does not support debug transactions. +// +template <typename TRANS = tlm_generic_payload> +class tlm_transport_dbg_if : public virtual sc_core::sc_interface +{ +public: + // The return value of defines the number of bytes successfully + // transferred. + virtual unsigned int transport_dbg(TRANS& trans) = 0; +}; + +//////////////////////////////////////////////////////////////////////////// +// Combined interfaces +//////////////////////////////////////////////////////////////////////////// + +struct tlm_base_protocol_types +{ + typedef tlm_generic_payload tlm_payload_type; + typedef tlm_phase tlm_phase_type; +}; + +// The forward interface: +template <typename TYPES = tlm_base_protocol_types> +class tlm_fw_transport_if + : public virtual tlm_fw_nonblocking_transport_if<typename TYPES::tlm_payload_type, + typename TYPES::tlm_phase_type> + , public virtual tlm_blocking_transport_if<typename TYPES::tlm_payload_type> + , public virtual tlm_fw_direct_mem_if<typename TYPES::tlm_payload_type> + , public virtual tlm_transport_dbg_if<typename TYPES::tlm_payload_type> +{}; + +// The backward interface: +template <typename TYPES = tlm_base_protocol_types> +class tlm_bw_transport_if + : public virtual tlm_bw_nonblocking_transport_if<typename TYPES::tlm_payload_type, + typename TYPES::tlm_phase_type> + , public virtual tlm_bw_direct_mem_if +{}; + +} // namespace tlm + +#endif /* __TLM_FW_BW_IFS_H__ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h new file mode 100644 index 000000000..1a49b0895 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h @@ -0,0 +1,126 @@ +/***************************************************************************** + + 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 TLM_CORE_TLM2_TLM_ARRAY_H_INCLUDED_ +#define TLM_CORE_TLM2_TLM_ARRAY_H_INCLUDED_ + +#include <vector> + +#if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) +#pragma warning(push) +#pragma warning(disable: 4251) // DLL import for std::string,vector +#endif + +namespace tlm { + +// +// To the LRM writer: the below class is an artifact of the tlm_generic_payload +// implementation and not part of the core TLM standard +// + + +// 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> +{ + typedef std::vector<T> base_type; + typedef typename base_type::size_type size_type; +public: + + // constructor: + tlm_array(size_type size = 0) + : base_type(size) + , m_entries() + { + //m_entries.reserve(size); // optional + } + + // copy constructor: + // tlm_array(const tlm_array& orig) = default; + + // destructor: + // ~tlm_array() = default; + + // 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); + //m_entries.reserve(new_size); // optional + } + } + + static const char* const kind_string; + const char* kind() const { return kind_string; } + + //this function shall get a pointer to a array slot + // it stores this slot in a cache of active slots + void insert_in_cache(T* p) + { + //sc_assert( (p-&(*this)[0]) < size() ); + m_entries.push_back( p-&(*this)[0] ); + } + + //this functions clears all active slots of the array + void free_entire_cache() + { + while(m_entries.size()) + { + if ((*this)[m_entries.back()]) //we make sure no one cleared the slot manually + (*this)[m_entries.back()]->free();//...and then we call free on the content of the slot + (*this)[m_entries.back()]=0; //afterwards we set the slot to NULL + m_entries.pop_back(); + } + } + +protected: + std::vector<size_type> m_entries; +}; + +template <typename T> +const char* const tlm_array<T>::kind_string = "tlm_array"; + +#if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) +#pragma warning(pop) +#endif + +} // namespace tlm + +#endif /* TLM_CORE_TLM2_TLM_ARRAY_H_INCLUDED_ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h new file mode 100644 index 000000000..cf17a1ffb --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h @@ -0,0 +1,791 @@ +/***************************************************************************** + + 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 __TLM_ENDIAN_CONV_H__ +#define __TLM_ENDIAN_CONV_H__ + +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h" + +#include <cstring> // std::memset + +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) +*/ + + + +#ifndef uchar +#define uchar unsigned char +#else +#define TLM_END_CONV_DONT_UNDEF_UCHAR +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// 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 + uchar *data_ptr; // used by generic, word, aligned + uchar *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 + uchar *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 uchar[len]; + dbuf_size = len; + } + void establish_bebuf(int len) { + if(len <= bebuf_size) return; + if(bebuf_size > 0) delete [] new_bebuf; + new_bebuf = new uchar[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(uchar c) { + D d; + uchar *tmp = (uchar *)(&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(*((uchar*)&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); + + + +/////////////////////////////////////////////////////////////////////////////// +// function set (0): Utilities +inline void copy_db0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *dest1 = *src1; + *dest2 = *src2; +} + +inline void copy_dbtrue0(uchar *src1, uchar * /* src2 */, uchar *dest1, uchar *dest2) { + *dest1 = *src1; + *dest2 = TLM_BYTE_ENABLED; +} + +inline void copy_btrue0(uchar * /* src1 */, uchar * /* src2 */, uchar * /* dest1 */, uchar *dest2) { + *dest2 = TLM_BYTE_ENABLED; +} + +inline void copy_b0(uchar * /* src1 */, uchar *src2, uchar * /* dest1 */, uchar *dest2) { + *dest2 = *src2; +} + +inline void copy_dbyb0(uchar *src1, uchar * /* src2 */, uchar *dest1, uchar *dest2) { + if(*dest2 == TLM_BYTE_ENABLED) *src1 = *dest1; +} + + +template<class D, + void COPY(uchar *he_d, uchar *he_b, uchar *ie_d, uchar *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, + uchar *ie_data, uchar *ie_be, uchar *he_data, uchar *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, + ie_be+(curr_byte % be_length), // 64BITRISK no risk of overflow, always positive // + 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, ©_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; + uchar *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, ©_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, ©_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, ©_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, ©_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(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest1) = *((D *)src1); + *((D *)dest2) = tlm_bool<D>::TLM_TRUE; +} + +template<class D> +inline void copy_db1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest1) = *((D *)src1); + *((D *)dest2) = *((D *)src2); +} + +template<class D> +inline void true_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest2) = tlm_bool<D>::TLM_TRUE; +} + +template<class D> +inline void copy_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest2) = *((D *)src2); +} + +template<class D> +inline void copy_dbyb1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + if(*src2 != TLM_BYTE_DISABLED) *((D *)src1) = *((D *)dest1); +} + +template<class D> +inline void copy_dbytrue1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)src1) = *((D *)dest1); +} + +template<class D> inline void false_b1(uchar *dest1) { + *((D *)dest1) = tlm_bool<D>::TLM_FALSE; +} + +template<class D> inline void no_b1(uchar *dest1) { +} + +template<class D, + void COPY(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2), + void COPYuchar(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2), + void FILLFALSE(uchar *dest1), void FILLFALSEuchar(uchar *dest1)> +inline int loop_word1( + int bytes_left, int len0, int lenN, int sizeof_databus, + uchar *start, uchar *end, uchar *src, uchar *bsrc, uchar *dest, uchar *bdest) { + ptrdiff_t d2b_src = bsrc - src; // 64BITFIX was int // + ptrdiff_t d2b_dest = bdest - dest; // 64BITFIX was int // + uchar *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; + uchar *d_start = tc->data_ptr; + uchar *d_end = ptrdiff_t(tc->length) + d_start; // 64BITFIX probably redundant // + uchar *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, ©_dbytrue1<DATAWORD>, + ©_dbytrue1<uchar>, &no_b1<DATAWORD>, &no_b1<uchar> >( + tc->length, len0, lenN, sizeof_databus, d_start, d_end, d, + 0, txn->get_data_ptr(), 0); + } else { + loop_word1<DATAWORD, ©_dbyb1<DATAWORD>, + ©_dbyb1<uchar>, &no_b1<DATAWORD>, &no_b1<uchar> >( + 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; + uchar *d_start = txn->get_data_ptr(); + uchar *d_end = ptrdiff_t(txn->get_data_length()) + d_start; // 64BITFIX probably redundant // + uchar *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); + uchar *new_data = tc->new_dbuf; + tc->establish_bebuf(long_enough); + uchar *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<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( + 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, ©_b1<DATAWORD>, + ©_b1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( + 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, ©_d1<DATAWORD>, + ©_d1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( + 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, ©_db1<DATAWORD>, + ©_db1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( + 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) { + ptrdiff_t src1to2 = (char *)src2 - (char *)src1; // 64BITFIX was int and operands were cast to int // + ptrdiff_t dest1to2 = (char *)dest2 - (char *)dest1; // 64BITFIX was int and operands were cast to int // + + 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, ©_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, ©_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, ©_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 = (uchar *)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, ©_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 = (uchar *)original_data; + // Copy byte enables to new buffer + loop_aligned2<DATAWORD, ©_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) { + // nothing needs to be done here +} + + +/////////////////////////////////////////////////////////////////////////////// +// 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); +} + + +#ifndef TLM_END_CONV_DONT_UNDEF_UCHAR +#undef uchar +#endif + +} // namespace tlm + + +#endif // multiple-inclusion protection + diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h new file mode 100644 index 000000000..3e25e56f2 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h @@ -0,0 +1,29 @@ +/***************************************************************************** + + 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 __TLM_GENERIC_PAYLOAD_H__ +#define __TLM_GENERIC_PAYLOAD_H__ + +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h" +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h" +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h" +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h" + +#endif + diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h new file mode 100644 index 000000000..99bb1e969 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h @@ -0,0 +1,402 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +// 12-Jan-2009 John Aynsley Bug fix. has_mm() and get_ref_count() should both be const +// 23-Mar-2009 John Aynsley Add method update_original_from() +// 20-Apr-2009 John Aynsley Bug fix for 64-bit machines: unsigned long int -> unsigned int +// 5-May-2011 JA and Philipp Hartmann Add tlm_gp_option, set_gp_option, get_gp_option +// 11-May-2011 John Aynsley Add run-time check to release() + + +#ifndef TLM_CORE_TLM2_TLM_GP_H_INCLUDED_ +#define TLM_CORE_TLM2_TLM_GP_H_INCLUDED_ + +#include "sysc/kernel/sc_cmnhdr.h" // SC_API +#include "sysc/utils/sc_report.h" // sc_assert +#include "sysc/datatypes/int/sc_nbdefs.h" // sc_dt::uint64 + +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_array.h" + +#include <typeinfo> // std::type_info + +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: +SC_API unsigned int max_num_extensions(); + +// This class can be used for storing pointers to the extension classes, used +// in tlm_generic_payload: +class SC_API 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: +//--------------------------------------------------------------------------- + +SC_API_TEMPLATE_DECL_ tlm_array<tlm_extension_base*>; + +class SC_API tlm_generic_payload { + +public: + //--------------- + // Constructors + //--------------- + + // Default constructor + 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) /* = delete */; + tlm_generic_payload& operator= (const tlm_generic_payload& x) /* = delete */; + +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(); + + //-------------- + // Destructor + //-------------- + 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 /* TLM_CORE_TLM2_TLM_GP_H_INCLUDED_ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h new file mode 100644 index 000000000..da3abb4f9 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h @@ -0,0 +1,80 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/* --------------------------------------------------------------------------------------- + @file tlm_helpers.h + + @brief + + Original Authors: + Charles Wilson, ESLX + +--------------------------------------------------------------------------------------- */ + +#ifndef __TLM_HELPERS_H__ +#define __TLM_HELPERS_H__ + +//#include <sys/param.h> +//#include <cstring> + +namespace tlm { + +enum tlm_endianness { TLM_UNKNOWN_ENDIAN, TLM_LITTLE_ENDIAN, TLM_BIG_ENDIAN }; + +inline tlm_endianness get_host_endianness(void) +{ + 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(void) +{ + 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 /* __TLM_HELPERS_H__ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h new file mode 100644 index 000000000..a06ccc443 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h @@ -0,0 +1,108 @@ +/***************************************************************************** + + 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 TLM_CORE_TLM2_TLM_PHASE_H_INCLUDED_ +#define TLM_CORE_TLM2_TLM_PHASE_H_INCLUDED_ + +#include <string> +#include <iostream> +#include <typeinfo> +#include <vector> + +#include "sysc/kernel/sc_cmnhdr.h" // SC_API +#include "sysc/kernel/sc_macros.h" // SC_CONCAT_HELPER_, SC_STRINGIFY_HELPER_ + +namespace tlm { + +enum SC_API tlm_phase_enum +{ + UNINITIALIZED_PHASE=0, + BEGIN_REQ=1, + END_REQ, + BEGIN_RESP, + END_RESP +}; + +class SC_API tlm_phase +{ +public: + tlm_phase(); + tlm_phase(unsigned int id); // TODO: should be dropped + + 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 + +#endif /* TLM_CORE_TLM2_TLM_PHASE_H_INCLUDED_ */ +// Taf! diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h b/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h new file mode 100644 index 000000000..5c08acf28 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h @@ -0,0 +1,82 @@ +/***************************************************************************** + + 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 TLM_CORE_TLM2_TLM_GLOBAL_QUANTUM_H_INCLUDED_ +#define TLM_CORE_TLM2_TLM_GLOBAL_QUANTUM_H_INCLUDED_ + +#include "sysc/kernel/sc_time.h" + +namespace tlm { + +// +// tlm_global_quantum class +// +// The global quantum is the maximum time an initiator can run ahead of +// SystemC time. All initiators should synchronize on timingpoints that +// are multiples of the global quantum value. +// +// sc_set_time_resolution can only be called before the first +// sc_time object is created. This means that after setting the +// global quantum it will not be possible to call sc_set_time_resolution. +// If sc_set_time_resolution must be called this must be done before +// the global quantum is set. +// + +class SC_API tlm_global_quantum +{ +public: + // + // Returns a reference to the tlm_global_quantum singleton + // + static tlm_global_quantum& instance(); + +public: + + // + // Setter/getter for the global quantum + // + void set(const sc_core::sc_time& t) + { + m_global_quantum = t; + } + + const sc_core::sc_time& get() const + { + return m_global_quantum; + } + + // + // This function will calculate the maximum value for the next local + // quantum for an initiator. All initiators should synchronize on + // integer multiples of the global quantum value. The value for the + // local quantum of an initiator can be smaller, but should never be + // greater than the value returned by this method. + // + sc_core::sc_time compute_local_quantum(); + +protected: + tlm_global_quantum(); + +protected: + sc_core::sc_time m_global_quantum; +}; + +} // namespace tlm + +#endif // TLM_CORE_TLM2_TLM_GLOBAL_QUANTUM_H_INCLUDED_ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h b/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h new file mode 100644 index 000000000..f06a4633a --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h @@ -0,0 +1,25 @@ +/***************************************************************************** + + 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 TLM_CORE_TLM2_TLM_QUANTUM_H_INCLUDED_ +#define TLM_CORE_TLM2_TLM_QUANTUM_H_INCLUDED_ + +#include "tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h" + +#endif // TLM_CORE_TLM2_TLM_QUANTUM_H_INCLUDED_ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h new file mode 100644 index 000000000..c847835d7 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h @@ -0,0 +1,56 @@ +/***************************************************************************** + + 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 TLM_CORE_TLM_BASE_SOCKET_IF_H_INCLUDED_ +#define TLM_CORE_TLM_BASE_SOCKET_IF_H_INCLUDED_ + +#include "sysc/utils/sc_typeindex.h" + +namespace tlm { + +enum tlm_socket_category +{ + TLM_UNKNOWN_SOCKET = 0, + TLM_INITIATOR_SOCKET = 0x1, + TLM_TARGET_SOCKET = 0x2, + + TLM_MULTI_SOCKET = 0x10, + + TLM_MULTI_INITIATOR_SOCKET = TLM_INITIATOR_SOCKET | TLM_MULTI_SOCKET, + TLM_MULTI_TARGET_SOCKET = TLM_TARGET_SOCKET | TLM_MULTI_SOCKET +}; + +class tlm_base_socket_if +{ +public: + virtual sc_core::sc_port_base & get_port_base() = 0; + virtual sc_core::sc_port_base const & get_port_base() const = 0; + virtual sc_core::sc_export_base & get_export_base() = 0; + virtual sc_core::sc_export_base const & get_export_base() const = 0; + virtual unsigned int get_bus_width() const = 0; + virtual sc_core::sc_type_index get_protocol_types() const = 0; + virtual tlm_socket_category get_socket_category() const = 0; + +protected: + virtual ~tlm_base_socket_if() {} +}; + +} // namespace tlm + +#endif // TLM_CORE_TLM_BASE_SOCKET_IF_H_INCLUDED_ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h new file mode 100644 index 000000000..b703ec210 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h @@ -0,0 +1,240 @@ +/***************************************************************************** + + 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 TLM_CORE_TLM_INITIATOR_SOCKET_H_INCLUDED_ +#define TLM_CORE_TLM_INITIATOR_SOCKET_H_INCLUDED_ + +#include "tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h" +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" + +#if defined(__clang__) || \ + (defined(__GNUC__) && ((__GNUC__ * 1000 + __GNUC_MINOR__) >= 4006)) +// ignore warning about deliberately hidden "bind()" overloads +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#endif + +namespace tlm { + +template <unsigned int BUSWIDTH = 32, + typename FW_IF = tlm_fw_transport_if<>, + typename BW_IF = tlm_bw_transport_if<> > +class tlm_base_initiator_socket_b +{ +public: + virtual ~tlm_base_initiator_socket_b() {} + + virtual sc_core::sc_port_b<FW_IF> & get_base_port() = 0; + virtual sc_core::sc_port_b<FW_IF> const & get_base_port() const = 0; + virtual BW_IF & get_base_interface() = 0; + virtual BW_IF const & get_base_interface() const = 0; + virtual sc_core::sc_export<BW_IF> & get_base_export() = 0; + virtual sc_core::sc_export<BW_IF> const & get_base_export() const = 0; +}; + + +template <unsigned int BUSWIDTH, + typename FW_IF, + typename BW_IF> class tlm_base_target_socket_b; + +template <unsigned int BUSWIDTH, + typename FW_IF, + typename BW_IF, + int N, + sc_core::sc_port_policy POL> class tlm_base_target_socket; + +template <unsigned int BUSWIDTH = 32, + typename FW_IF = tlm_fw_transport_if<>, + typename BW_IF = tlm_bw_transport_if<>, + int N = 1, + sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND> +class tlm_base_initiator_socket : public tlm_base_socket_if, + public tlm_base_initiator_socket_b<BUSWIDTH, FW_IF, BW_IF>, + public sc_core::sc_port<FW_IF, N, POL> +{ +public: + typedef FW_IF fw_interface_type; + typedef BW_IF bw_interface_type; + typedef sc_core::sc_port<fw_interface_type,N,POL> port_type; + + typedef sc_core::sc_export<bw_interface_type> export_type; + + typedef tlm_base_target_socket_b<BUSWIDTH, + fw_interface_type, + bw_interface_type> base_target_socket_type; + typedef tlm_base_initiator_socket_b<BUSWIDTH, + fw_interface_type, + bw_interface_type> base_type; + + template <unsigned int, typename, typename, int, sc_core::sc_port_policy> + friend class tlm_base_target_socket; + +public: + tlm_base_initiator_socket() + : port_type(sc_core::sc_gen_unique_name("tlm_base_initiator_socket")) + , m_export(sc_core::sc_gen_unique_name("tlm_base_initiator_socket_export")) + { + } + + explicit tlm_base_initiator_socket(const char* name) + : port_type(name) + , m_export(sc_core::sc_gen_unique_name((std::string(name) + "_export").c_str())) + { + } + + virtual const char* kind() const + { + return "tlm_base_initiator_socket"; + } + + // + // Bind initiator socket to target socket + // - Binds the port of the initiator socket to the export of the target + // socket + // - Binds the port of the target socket to the export of the initiator + // socket + // + virtual void bind(base_target_socket_type& s) + { + // initiator.port -> target.export + (get_base_port())(s.get_base_interface()); + // target.port -> initiator.export + (s.get_base_port())(get_base_interface()); + } + + void operator() (base_target_socket_type& s) + { + bind(s); + } + + // + // Bind initiator socket to initiator socket (hierarchical bind) + // - Binds both the export and the port + // + virtual void bind(base_type& s) + { + // port + (get_base_port())(s.get_base_port()); + // export + (s.get_base_export())(get_base_export()); + } + + void operator() (base_type& s) + { + bind(s); + } + + // + // Bind interface to socket + // - Binds the interface to the export of this socket + // + virtual void bind(bw_interface_type& ifs) + { + (get_base_export())(ifs); + } + + void operator() (bw_interface_type& s) + { + bind(s); + } + + // Implementation of tlm_base_socket_if functions + virtual sc_core::sc_port_base & get_port_base() + { return *this; } + virtual sc_core::sc_port_base const & get_port_base() const + { return *this; } + virtual sc_core::sc_export_base & get_export_base() + { return m_export; } + virtual sc_core::sc_export_base const & get_export_base() const + { return m_export; } + virtual unsigned int get_bus_width() const + { return BUSWIDTH; } + virtual tlm_socket_category get_socket_category() const + { return TLM_INITIATOR_SOCKET; } + + // Implementation of tlm_base_target_socket_b functions + virtual sc_core::sc_port_b<FW_IF> & get_base_port() + { return *this; } + virtual sc_core::sc_port_b<FW_IF> const & get_base_port() const + { return *this; } + + virtual BW_IF & get_base_interface() + { return m_export; } + virtual BW_IF const & get_base_interface() const + { return m_export; } + + virtual sc_core::sc_export<BW_IF> & get_base_export() + { return m_export; } + virtual sc_core::sc_export<BW_IF> const & get_base_export() const + { return m_export; } + +protected: + export_type m_export; +}; + +// +// Convenience socket classes +// + +template <unsigned int BUSWIDTH = 32, + typename TYPES = tlm_base_protocol_types, + int N = 1, + sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND> +class tlm_initiator_socket : + public tlm_base_initiator_socket<BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N, POL> +{ +public: + tlm_initiator_socket() : + tlm_base_initiator_socket<BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N, POL>() + { + } + + explicit tlm_initiator_socket(const char* name) : + tlm_base_initiator_socket<BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N, POL>(name) + { + } + + virtual const char* kind() const + { + return "tlm_initiator_socket"; + } + + virtual sc_core::sc_type_index get_protocol_types() const + { + return typeid(TYPES); + } +}; + +} // namespace tlm + +#if defined(__clang__) || \ + (defined(__GNUC__) && ((__GNUC__ * 1000 + __GNUC_MINOR__) >= 4006)) +#pragma GCC diagnostic pop +#endif + +#endif // TLM_CORE_TLM_INITIATOR_SOCKET_H_INCLUDED_ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h new file mode 100644 index 000000000..013e29286 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h @@ -0,0 +1,26 @@ +/***************************************************************************** + + 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 __TLM_SOCKETS_H__ +#define __TLM_SOCKETS_H__ + +#include "tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h" +#include "tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h" + +#endif /* __TLM_SOCKETS_H__ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h new file mode 100644 index 000000000..030643294 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h @@ -0,0 +1,255 @@ +/***************************************************************************** + + 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 TLM_CORE_TLM_TARGET_SOCKET_H_INCLUDED_ +#define TLM_CORE_TLM_TARGET_SOCKET_H_INCLUDED_ + +#include "tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h" +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" + + +namespace tlm { + +template <unsigned int BUSWIDTH = 32, + typename FW_IF = tlm_fw_transport_if<>, + typename BW_IF = tlm_bw_transport_if<> > +class tlm_base_target_socket_b +{ +public: + virtual ~tlm_base_target_socket_b() {} + + virtual sc_core::sc_port_b<BW_IF> & get_base_port() = 0; + virtual sc_core::sc_export<FW_IF> & get_base_export() = 0; + virtual FW_IF & get_base_interface() = 0; +}; + +template <unsigned int BUSWIDTH, + typename FW_IF, + typename BW_IF> class tlm_base_initiator_socket_b; + +template <unsigned int BUSWIDTH, + typename FW_IF, + typename BW_IF, + int N, + sc_core::sc_port_policy POL> class tlm_base_initiator_socket; + +template <unsigned int BUSWIDTH = 32, + typename FW_IF = tlm_fw_transport_if<>, + typename BW_IF = tlm_bw_transport_if<>, + int N = 1, + sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND> +class tlm_base_target_socket : public tlm_base_socket_if, + public tlm_base_target_socket_b<BUSWIDTH, FW_IF, BW_IF>, + public sc_core::sc_export<FW_IF> +{ +public: + typedef FW_IF fw_interface_type; + typedef BW_IF bw_interface_type; + typedef sc_core::sc_port<bw_interface_type, N , POL> port_type; + + typedef sc_core::sc_export<fw_interface_type> export_type; + typedef tlm_base_initiator_socket_b<BUSWIDTH, + fw_interface_type, + bw_interface_type> base_initiator_socket_type; + + typedef tlm_base_target_socket_b<BUSWIDTH, + fw_interface_type, + bw_interface_type> base_type; + + template <unsigned int, typename, typename, int, sc_core::sc_port_policy> + friend class tlm_base_initiator_socket; + +public: + tlm_base_target_socket() + : export_type(sc_core::sc_gen_unique_name("tlm_base_target_socket")) + , m_port(sc_core::sc_gen_unique_name("tlm_base_target_socket_port")) + { + } + + explicit tlm_base_target_socket(const char* name) + : export_type(name) + , m_port(sc_core::sc_gen_unique_name((std::string(name) + "_port").c_str())) + { + } + + virtual const char* kind() const + { + return "tlm_base_target_socket"; + } + + // + // Bind target socket to initiator socket + // - Binds the port of the initiator socket to the export of the target + // socket + // - Binds the port of the target socket to the export of the initiator + // socket + // + virtual void bind(base_initiator_socket_type& s) + { + // initiator.port -> target.export + (s.get_base_port())(get_base_interface()); + // target.port -> initiator.export + get_base_port()(s.get_base_interface()); + } + + void operator() (base_initiator_socket_type& s) + { + bind(s); + } + + // + // Bind target socket to target socket (hierarchical bind) + // - Binds both the export and the port + // + virtual void bind(base_type& s) + { + // export + (get_base_export())(s.get_base_export()); + // port + (s.get_base_port())(get_base_port()); + } + + void operator() (base_type& s) + { + bind(s); + } + + // + // Bind interface to socket + // - Binds the interface to the export + // + virtual void bind(fw_interface_type& ifs) + { + export_type* exp = &get_base_export(); + if( this == exp ) { + export_type::bind( ifs ); // non-virtual function call + } else { + exp->bind( ifs ); + } + } + + void operator() (fw_interface_type& s) + { + bind(s); + } + + // + // Forward to 'size()' of port class + // + int size() const + { + return m_port.size(); + } + + // + // Forward to 'operator->()' of port class + // + bw_interface_type* operator->() + { + return m_port.operator->(); + } + + // + // Forward to 'operator[]()' of port class + // + bw_interface_type* operator[](int i) + { + return m_port.operator[](i); + } + + // Implementation of tlm_base_socket_if functions + virtual sc_core::sc_port_base & get_port_base() + { return m_port; } + virtual sc_core::sc_port_base const & get_port_base() const + { return m_port; } + virtual sc_core::sc_export_base & get_export_base() + { return *this; } + virtual sc_core::sc_export_base const & get_export_base() const + { return *this; } + virtual unsigned int get_bus_width() const + { return BUSWIDTH; } + virtual tlm_socket_category get_socket_category() const + { return TLM_TARGET_SOCKET; } + + // Implementation of tlm_base_target_socket_b functions + virtual sc_core::sc_port_b<BW_IF> & get_base_port() + { return m_port; } + virtual sc_core::sc_port_b<BW_IF> const & get_base_port() const + { return m_port; } + + virtual FW_IF & get_base_interface() + { return *this; } + virtual FW_IF const & get_base_interface() const + { return *this; } + + virtual sc_core::sc_export<FW_IF> & get_base_export() + { return *this; } + virtual sc_core::sc_export<FW_IF> const & get_base_export() const + { return *this; } + +protected: + port_type m_port; +}; + + +// +// Convenience blocking and non-blocking socket classes +// + +template <unsigned int BUSWIDTH = 32, + typename TYPES = tlm_base_protocol_types, + int N = 1, + sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND> +class tlm_target_socket : + public tlm_base_target_socket <BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N, POL> +{ +public: + tlm_target_socket() : + tlm_base_target_socket<BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N, POL>() + { + } + + explicit tlm_target_socket(const char* name) : + tlm_base_target_socket<BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N, POL>(name) + { + } + + virtual const char* kind() const + { + return "tlm_target_socket"; + } + + virtual sc_core::sc_type_index get_protocol_types() const + { + return typeid(TYPES); + } +}; + +} // namespace tlm + +#endif // TLM_CORE_TLM_TARGET_SOCKET_H_INCLUDED_ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_version.h b/src/systemc/ext/tlm_core/tlm_2/tlm_version.h new file mode 100644 index 000000000..3cf230077 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_version.h @@ -0,0 +1,180 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/* --------------------------------------------------------------------------------------- + @file tlm_version.h + + @brief TLM version header + + Original Author: + Charles Wilson, XtremeEDA Corporation + + @description + This header contains preprocessor and compiler symbols to allow for the determination + of the TLM version information. This conforms to IEEE 1666-2005 section 8.5.5 - 8.5.7 + . + The following are provided: + . + preprocessor: TLM_VERSION_MAJOR numeric + TLM_VERSION_MINOR numeric + TLM_VERSION_PATCH numeric + TLM_VERSION_ORIGINATOR string ([A-Z][a-z][0-9]_) + TLM_VERSION_RELEASE_DATE ISO8601 date (YYYYMMDD) + TLM_VERSION_PRERELEASE string ([A-Z][a-z][0-9]_) + TLM_IS_PRERELEASE bool (1,0) + TLM_VERSION string {2.0.0_DR3-TLMWG} + TLM_COPYRIGHT string + . + compiler: tlm_version_major const unsigned int + tlm_version_minor const unsigned int + tlm_version_patch const unsigned int + tlm_version_originator const std::string + tlm_version_release_date const std::string + tlm_version_prerelease const std::string + tlm_is_prerelease const bool + tlm_version const string + tlm_copyright const string + . + accessors: inline const char* tlm_release (void) + inline const char* tlm_version (void) + inline const char* tlm_copyright (void) + +--------------------------------------------------------------------------------------- */ + +#ifndef __TLM_VERSION_H__ +#define __TLM_VERSION_H__ + +namespace tlm +{ + +#define TLM_VERSION_MAJOR 2 ///< version major level ( numeric ) +#define TLM_VERSION_MINOR 0 ///< version minor level ( numeric ) +#define TLM_VERSION_PATCH 4 ///< version patch level ( numeric ) +#define TLM_VERSION_ORIGINATOR "Accellera" ///< TLM creator string +#define TLM_VERSION_SEPARATOR "." ///< version string separator + +#define TLM_IS_PRERELEASE 0 ///< pre-release flag ( 1 / 0 ) + +#if TLM_IS_PRERELEASE +# define TLM_VERSION_PRERELEASE "pub_rev" ///< pre-release version string +#else +# define TLM_VERSION_PRERELEASE "" ///< pre-release version string +#endif + +#define TLM_VERSION_RELEASE_YEAR "2017" ///< release year ( YYYY ) +#define TLM_VERSION_RELEASE_MONTH "10" ///< release month ( MM ) +#define TLM_VERSION_RELEASE_DAY "12" ///< release day ( DD ) + +#define TLM_COPYRIGHT \ + "Copyright (c) 1996-" TLM_VERSION_RELEASE_YEAR " by all Contributors\n" \ + "ALL RIGHTS RESERVED" + +/************************** do not modify below this line *******************************/ + +/******************************* preprocessor symbols ***********************************/ + +#define TLM_VERSION_RELEASE_DATE TLM_VERSION_RELEASE_YEAR \ + TLM_VERSION_RELEASE_MONTH \ + TLM_VERSION_RELEASE_DAY + +#define TLM_VERSION_STR(x) TLM_VERSION_STR_HELPER(x) +#define TLM_VERSION_STR_HELPER(x) #x + +#define TLM_VERSION_STRING_MAJOR TLM_VERSION_STR(TLM_VERSION_MAJOR) +#define TLM_VERSION_STRING_MINOR TLM_VERSION_STR(TLM_VERSION_MINOR) +#define TLM_VERSION_STRING_PATCH TLM_VERSION_STR(TLM_VERSION_PATCH) + +#define TLM_VERSION_STRING_MMP TLM_VERSION_STRING_MAJOR TLM_VERSION_SEPARATOR \ + TLM_VERSION_STRING_MINOR TLM_VERSION_SEPARATOR \ + TLM_VERSION_STRING_PATCH + +#define TLM_VERSION_STRING_PRE_START "_" +#define TLM_VERSION_STRING_PRE_END "-" + +#if ( TLM_IS_PRERELEASE == 1 ) + +#define TLM_VERSION_STRING_PRERELEASE TLM_VERSION_PRERELEASE +#define TLM_VERSION_STRING_RELEASE_DATE "" + +#else /* TLM_IS_PRERELEASE == 1 */ + +#define TLM_VERSION_STRING_PRERELEASE "" +#define TLM_VERSION_STRING_RELEASE_DATE TLM_VERSION_RELEASE_DATE + +#endif /* TLM_IS_PRERELEASE == 1 */ + +#define TLM_VERSION_STRING TLM_VERSION_STRING_MMP \ + TLM_VERSION_STRING_PRE_START \ + TLM_VERSION_STRING_PRERELEASE \ + TLM_VERSION_STRING_PRE_END \ + TLM_VERSION_ORIGINATOR + +#define TLM_VERSION_STRING_2 "TLM " \ + TLM_VERSION_STRING_MMP \ + " --- " \ + TLM_VERSION_RELEASE_YEAR \ + "-" \ + TLM_VERSION_RELEASE_MONTH \ + "-" \ + TLM_VERSION_RELEASE_DAY + +#define TLM_VERSION TLM_VERSION_STRING + +/********************************* compiler symbols **************************************/ + +const unsigned int tlm_version_major ( TLM_VERSION_MAJOR ); +const unsigned int tlm_version_minor ( TLM_VERSION_MINOR ); +const unsigned int tlm_version_patch ( TLM_VERSION_PATCH ); + +const bool tlm_is_prerelease ( TLM_IS_PRERELEASE ); + +const std::string tlm_version_string ( TLM_VERSION_STRING ); +const std::string tlm_version_originator ( TLM_VERSION_ORIGINATOR ); +const std::string tlm_version_prerelease ( TLM_VERSION_PRERELEASE ); +const std::string tlm_version_release_date ( TLM_VERSION_STRING_RELEASE_DATE ); +const std::string tlm_copyright_string ( TLM_COPYRIGHT ); +const std::string tlm_version_string_2 ( TLM_VERSION_STRING_2 ); + +inline const char* +tlm_release +( void +) +{ + return tlm_version_string.c_str (); +} + +inline const char* +tlm_version +( void +) +{ + return tlm_version_string_2.c_str (); +} + +inline const char* +tlm_copyright +( void +) +{ + return tlm_copyright_string.c_str (); +} + +} // namespace tlm + +#endif /* __TLM_VERSION_H__ */ |