| /***************************************************************************** |
| |
| 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_ |