diff options
Diffstat (limited to 'src/systemc/ext/tlm_utils/passthrough_target_socket.h')
-rw-r--r-- | src/systemc/ext/tlm_utils/passthrough_target_socket.h | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/src/systemc/ext/tlm_utils/passthrough_target_socket.h b/src/systemc/ext/tlm_utils/passthrough_target_socket.h new file mode 100644 index 000000000..b2c97aed5 --- /dev/null +++ b/src/systemc/ext/tlm_utils/passthrough_target_socket.h @@ -0,0 +1,477 @@ +/***************************************************************************** + + 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_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_ +#define TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_ + +#include <tlm> +#include "tlm_utils/convenience_socket_bases.h" + +namespace tlm_utils { + +template< typename MODULE, unsigned int BUSWIDTH, typename TYPES + , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND > +class passthrough_target_socket_b + : public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL> + , protected passthrough_socket_base +{ +public: + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type; + typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type; + typedef tlm::tlm_target_socket<BUSWIDTH,TYPES,1,POL> base_type; + +public: + static const char* default_name() + { return sc_core::sc_gen_unique_name("passthrough_target_socket"); } + + explicit passthrough_target_socket_b(const char* n = default_name()) + : base_type(n) + , m_process(this) + { + bind(m_process); + } + + using base_type::bind; + + // REGISTER_XXX + void register_nb_transport_fw(MODULE* mod, + sync_enum_type (MODULE::*cb)(transaction_type&, + phase_type&, + sc_core::sc_time&)) + { + m_process.set_nb_transport_ptr(mod, cb); + } + + void register_b_transport(MODULE* mod, + void (MODULE::*cb)(transaction_type&, + sc_core::sc_time&)) + { + m_process.set_b_transport_ptr(mod, cb); + } + + void register_transport_dbg(MODULE* mod, + unsigned int (MODULE::*cb)(transaction_type&)) + { + m_process.set_transport_dbg_ptr(mod, cb); + } + + void register_get_direct_mem_ptr(MODULE* mod, + bool (MODULE::*cb)(transaction_type&, + tlm::tlm_dmi&)) + { + m_process.set_get_direct_mem_ptr(mod, cb); + } + +private: + class process + : public tlm::tlm_fw_transport_if<TYPES> + , protected convenience_socket_cb_holder + { + public: + typedef sync_enum_type (MODULE::*NBTransportPtr)(transaction_type&, + phase_type&, + sc_core::sc_time&); + typedef void (MODULE::*BTransportPtr)(transaction_type&, + sc_core::sc_time&); + typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type&); + typedef bool (MODULE::*GetDirectMem_ptr)(transaction_type&, + tlm::tlm_dmi&); + + explicit process(passthrough_socket_base* owner) + : convenience_socket_cb_holder(owner), m_mod(0) + , m_nb_transport_ptr(0) + , m_b_transport_ptr(0) + , m_transport_dbg_ptr(0) + , m_get_direct_mem_ptr(0) + { + } + + void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p) + { + if (m_nb_transport_ptr) { + display_warning("non-blocking callback already registered"); + return; + } + sc_assert(!m_mod || m_mod == mod); + m_mod = mod; + m_nb_transport_ptr = p; + } + + void set_b_transport_ptr(MODULE* mod, BTransportPtr p) + { + if (m_b_transport_ptr) { + display_warning("blocking callback already registered"); + return; + } + sc_assert(!m_mod || m_mod == mod); + m_mod = mod; + m_b_transport_ptr = p; + } + + void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) + { + if (m_transport_dbg_ptr) { + display_warning("debug callback already registered"); + return; + } + sc_assert(!m_mod || m_mod == mod); + m_mod = mod; + m_transport_dbg_ptr = p; + } + + void set_get_direct_mem_ptr(MODULE* mod, GetDirectMem_ptr p) + { + if (m_get_direct_mem_ptr) { + display_warning("get DMI pointer callback already registered"); + return; + } + sc_assert(!m_mod || m_mod == mod); + m_mod = mod; + m_get_direct_mem_ptr = p; + } + + sync_enum_type nb_transport_fw(transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + if (m_nb_transport_ptr) { + // forward call + sc_assert(m_mod); + return (m_mod->*m_nb_transport_ptr)(trans, phase, t); + } + display_error("no non-blocking callback registered"); + return tlm::TLM_COMPLETED; + } + + void b_transport(transaction_type& trans, sc_core::sc_time& t) + { + if (m_b_transport_ptr) { + // forward call + sc_assert(m_mod); + return (m_mod->*m_b_transport_ptr)(trans, t); + } + display_error("no blocking callback registered"); + } + + unsigned int transport_dbg(transaction_type& trans) + { + if (m_transport_dbg_ptr) { + // forward call + sc_assert(m_mod); + return (m_mod->*m_transport_dbg_ptr)(trans); + } + // No debug support + return 0; + } + + bool get_direct_mem_ptr(transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + if (m_get_direct_mem_ptr) { + // forward call + sc_assert(m_mod); + return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data); + } + // No DMI support + dmi_data.allow_read_write(); + dmi_data.set_start_address(0x0); + dmi_data.set_end_address((sc_dt::uint64)-1); + return false; + } + + private: + MODULE* m_mod; + NBTransportPtr m_nb_transport_ptr; + BTransportPtr m_b_transport_ptr; + TransportDbgPtr m_transport_dbg_ptr; + GetDirectMem_ptr m_get_direct_mem_ptr; + }; + +private: + const sc_core::sc_object* get_socket() const { return this; } +private: + process m_process; +}; + +template< typename MODULE, unsigned int BUSWIDTH = 32 + , typename TYPES = tlm::tlm_base_protocol_types > +class passthrough_target_socket + : public passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES> +{ + typedef passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES> socket_b; +public: + passthrough_target_socket() : socket_b() {} + explicit passthrough_target_socket(const char* name) : socket_b(name) {} +}; + +template< typename MODULE, unsigned int BUSWIDTH = 32 + , typename TYPES = tlm::tlm_base_protocol_types > +class passthrough_target_socket_optional + : public passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND> +{ + typedef passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND> socket_b; +public: + passthrough_target_socket_optional() : socket_b() {} + explicit passthrough_target_socket_optional(const char* name) : socket_b(name) {} +}; + +//ID Tagged version +template< typename MODULE, unsigned int BUSWIDTH, typename TYPES + , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND > +class passthrough_target_socket_tagged_b + : public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL> + , protected passthrough_socket_base +{ +public: + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type; + typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type; + typedef tlm::tlm_target_socket<BUSWIDTH,TYPES,1,POL> base_type; + + static const char* default_name() + { return sc_core::sc_gen_unique_name("passthrough_target_socket_tagged"); } + +public: + explicit passthrough_target_socket_tagged_b(const char* n = default_name()) + : base_type(n) + , m_process(this) + { + bind(m_process); + } + + using base_type::bind; + + // REGISTER_XXX + void register_nb_transport_fw(MODULE* mod, + sync_enum_type (MODULE::*cb)(int id, + transaction_type&, + phase_type&, + sc_core::sc_time&), + int id) + { + m_process.set_nb_transport_ptr(mod, cb); + m_process.set_nb_transport_user_id(id); + } + + void register_b_transport(MODULE* mod, + void (MODULE::*cb)(int id, + transaction_type&, + sc_core::sc_time&), + int id) + { + m_process.set_b_transport_ptr(mod, cb); + m_process.set_b_transport_user_id(id); + } + + void register_transport_dbg(MODULE* mod, + unsigned int (MODULE::*cb)(int id, + transaction_type&), + int id) + { + m_process.set_transport_dbg_ptr(mod, cb); + m_process.set_transport_dbg_user_id(id); + } + + void register_get_direct_mem_ptr(MODULE* mod, + bool (MODULE::*cb)(int id, + transaction_type&, + tlm::tlm_dmi&), + int id) + { + m_process.set_get_direct_mem_ptr(mod, cb); + m_process.set_get_dmi_user_id(id); + } + +private: + class process + : public tlm::tlm_fw_transport_if<TYPES> + , protected convenience_socket_cb_holder + { + public: + typedef sync_enum_type (MODULE::*NBTransportPtr)(int id, + transaction_type&, + phase_type&, + sc_core::sc_time&); + typedef void (MODULE::*BTransportPtr)(int id, + transaction_type&, + sc_core::sc_time&); + typedef unsigned int (MODULE::*TransportDbgPtr)(int id, + transaction_type&); + typedef bool (MODULE::*GetDirectMem_ptr)(int id, + transaction_type&, + tlm::tlm_dmi&); + + process(passthrough_socket_base* owner) + : convenience_socket_cb_holder(owner), m_mod(0) + , m_nb_transport_ptr(0) + , m_b_transport_ptr(0) + , m_transport_dbg_ptr(0) + , m_get_direct_mem_ptr(0) + , m_nb_transport_user_id(0) + , m_b_transport_user_id(0) + , m_transport_dbg_user_id(0) + , m_get_dmi_user_id(0) + { + } + + void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; } + void set_b_transport_user_id(int id) { m_b_transport_user_id = id; } + void set_transport_dbg_user_id(int id) { m_transport_dbg_user_id = id; } + void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; } + + void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p) + { + if (m_nb_transport_ptr) { + display_warning("non-blocking callback already registered"); + return; + } + sc_assert(!m_mod || m_mod == mod); + m_mod = mod; + m_nb_transport_ptr = p; + } + + void set_b_transport_ptr(MODULE* mod, BTransportPtr p) + { + if (m_b_transport_ptr) { + display_warning("blocking callback already registered"); + return; + } + sc_assert(!m_mod || m_mod == mod); + m_mod = mod; + m_b_transport_ptr = p; + } + + void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) + { + if (m_transport_dbg_ptr) { + display_warning("debug callback already registered"); + return; + } + sc_assert(!m_mod || m_mod == mod); + m_mod = mod; + m_transport_dbg_ptr = p; + } + + void set_get_direct_mem_ptr(MODULE* mod, GetDirectMem_ptr p) + { + if (m_get_direct_mem_ptr) { + display_warning("get DMI pointer callback already registered"); + return; + } + sc_assert(!m_mod || m_mod == mod); + m_mod = mod; + m_get_direct_mem_ptr = p; + } + + sync_enum_type nb_transport_fw(transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + if (m_nb_transport_ptr) { + // forward call + sc_assert(m_mod); + return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t); + } + display_error("no non-blocking callback registered"); + return tlm::TLM_COMPLETED; + } + + void b_transport(transaction_type& trans, sc_core::sc_time& t) + { + if (m_b_transport_ptr) { + // forward call + sc_assert(m_mod); + return (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t); + } + display_error("no blocking callback registered"); + } + + unsigned int transport_dbg(transaction_type& trans) + { + if (m_transport_dbg_ptr) { + // forward call + sc_assert(m_mod); + return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans); + } + // No debug support + return 0; + } + + bool get_direct_mem_ptr(transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + if (m_get_direct_mem_ptr) { + // forward call + sc_assert(m_mod); + return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data); + } + // No DMI support + dmi_data.allow_read_write(); + dmi_data.set_start_address(0x0); + dmi_data.set_end_address((sc_dt::uint64)-1); + return false; + } + + private: + MODULE* m_mod; + NBTransportPtr m_nb_transport_ptr; + BTransportPtr m_b_transport_ptr; + TransportDbgPtr m_transport_dbg_ptr; + GetDirectMem_ptr m_get_direct_mem_ptr; + int m_nb_transport_user_id; + int m_b_transport_user_id; + int m_transport_dbg_user_id; + int m_get_dmi_user_id; + }; + +private: + const sc_core::sc_object* get_socket() const { return this; } +private: + process m_process; +}; + +template< typename MODULE, unsigned int BUSWIDTH = 32 + , typename TYPES = tlm::tlm_base_protocol_types > +class passthrough_target_socket_tagged + : public passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES> +{ + typedef passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES> socket_b; +public: + passthrough_target_socket_tagged() : socket_b() {} + explicit passthrough_target_socket_tagged(const char* name) : socket_b(name) {} +}; + +template< typename MODULE, unsigned int BUSWIDTH = 32 + , typename TYPES = tlm::tlm_base_protocol_types > +class passthrough_target_socket_tagged_optional + : public passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND> +{ + typedef passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND> socket_b; +public: + passthrough_target_socket_tagged_optional() : socket_b() {} + explicit passthrough_target_socket_tagged_optional(const char* name) : socket_b(name) {} +}; + +} // namespace tlm_utils +#endif // TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_ |