|
1 | 1 | /* |
2 | | - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All Rights Reserved. |
3 | | - * Author: GreenSocs 2022 |
| 2 | + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All Rights Reserved. |
4 | 3 | * |
5 | 4 | * SPDX-License-Identifier: BSD-3-Clause |
6 | 5 | */ |
|
16 | 15 | #include <tlm_utils/simple_initiator_socket.h> |
17 | 16 | #include <tlm_utils/simple_target_socket.h> |
18 | 17 | #include <cci_configuration> |
| 18 | +#include <scp/report.h> |
19 | 19 |
|
20 | 20 | #include <libgsutils.h> |
21 | 21 | #include <module_factory_registery.h> |
|
27 | 27 | * @brief A Addrtr component that can add addrtr to a virtual platform project to manage the various |
28 | 28 | * transactions |
29 | 29 | * |
30 | | - * @details This component models a addrtr. It has a single multi-target socket so any other |
| 30 | + * @details This component models a addrtr. It has a single target socket so another |
31 | 31 | * component with an initiator socket can connect to this component. It behaves as follows: |
32 | | - * - Manages exclusive accesses, adding this addrtr as a 'hop' in the exclusive access extension |
33 | | - * (see GreenSocs/libgsutils). |
34 | | - * - Manages connections to multiple initiators and targets with the method `add_initiator` and |
35 | | - * `add_target`. |
36 | | - * - Allows to manage read and write transactions with `b_transport` and `transport_dbg` methods. |
37 | | - * - Supports passing through DMI requests with the method `get_direct_mem_ptr`. |
38 | | - * - Handles invalidation of multiple DMI pointers with the method `invalidate_direct_mem_ptr` |
39 | | - * which passes the invalidate back to *all* initiators. |
40 | | - * - It checks for each transaction if the address is valid or not and returns an error if the |
41 | | - * address is invalid with the method `decode_address`. |
| 32 | + * translate the target_socket address to the mapped_base_addr (CCI parameter) and reinitiate the transaction |
| 33 | + * using the initiator_socket. |
42 | 34 | */ |
43 | 35 |
|
44 | 36 | class addrtr : public sc_core::sc_module |
45 | 37 | { |
46 | 38 | private: |
47 | | - sc_dt::uint64 addr_fw(sc_dt::uint64 addr) { return addr + offset; } |
48 | | - sc_dt::uint64 addr_bw(sc_dt::uint64 addr) { return addr - offset; } |
49 | | - void translate_fw(tlm::tlm_generic_payload& trans) { trans.set_address(addr_fw(trans.get_address())); } |
50 | | - void translate_bw(tlm::tlm_generic_payload& trans) { trans.set_address(addr_bw(trans.get_address())); } |
| 39 | + SCP_LOGGER(); |
| 40 | + |
| 41 | + sc_dt::uint64 addr_fw(sc_dt::uint64 addr) |
| 42 | + { |
| 43 | + auto offset = addr - m_base_addr; |
| 44 | + return p_mapped_base_addr.get_value() + offset; |
| 45 | + } |
| 46 | + |
| 47 | + sc_dt::uint64 addr_bw(sc_dt::uint64 addr) |
| 48 | + { |
| 49 | + auto offset = addr - p_mapped_base_addr.get_value(); |
| 50 | + return m_base_addr + offset; |
| 51 | + } |
| 52 | + |
| 53 | + uint64_t map_txn_addr(tlm::tlm_generic_payload& trans) |
| 54 | + { |
| 55 | + uint64_t addr = trans.get_address(); |
| 56 | + uint64_t len = trans.get_data_length(); |
| 57 | + uint64_t mapped_addr = addr; |
| 58 | + if ((addr >= m_base_addr) && ((addr + len - 1) < (m_base_addr + m_mapping_size))) { |
| 59 | + mapped_addr = addr_fw(addr); |
| 60 | + trans.set_address(mapped_addr); |
| 61 | + } else { |
| 62 | + SCP_FATAL(()) << "The txn [addr: 0x" << std::hex << addr << "] len: 0x" << std::hex << len |
| 63 | + << ", doesn't belong to the target_socket base address: 0x" << std::hex << m_base_addr |
| 64 | + << " size: 0x" << std::hex << m_mapping_size; |
| 65 | + } |
| 66 | + return mapped_addr; |
| 67 | + } |
| 68 | + |
| 69 | + void map_dmi_start_end_addr(uint64_t& start_addr, uint64_t& end_addr) |
| 70 | + { |
| 71 | + if (start_addr < p_mapped_base_addr.get_value()) { |
| 72 | + start_addr = m_base_addr; |
| 73 | + } else if ((start_addr >= p_mapped_base_addr.get_value()) && |
| 74 | + (start_addr < (p_mapped_base_addr.get_value() + m_mapping_size))) { |
| 75 | + start_addr = addr_bw(start_addr); |
| 76 | + } else { |
| 77 | + SCP_FATAL(()) << "DMI granted start address 0x" << std::hex << start_addr |
| 78 | + << " is bigger than the mapped area 0x" << std::hex << p_mapped_base_addr.get_value() |
| 79 | + << " size: 0x" << std::hex << m_mapping_size; |
| 80 | + } |
| 81 | + if (end_addr >= (p_mapped_base_addr.get_value() + m_mapping_size)) { |
| 82 | + end_addr = m_base_addr + m_mapping_size; |
| 83 | + } else if ((end_addr > start_addr) && (end_addr < (p_mapped_base_addr.get_value() + m_mapping_size))) { |
| 84 | + end_addr = addr_bw(end_addr); |
| 85 | + } else { |
| 86 | + SCP_FATAL(()) << "DMI granted end address 0x" << std::hex << start_addr |
| 87 | + << " is smaller than the mapped area 0x" << std::hex << p_mapped_base_addr.get_value() |
| 88 | + << " size: 0x" << std::hex << m_mapping_size; |
| 89 | + } |
| 90 | + } |
51 | 91 |
|
52 | 92 | void b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) |
53 | 93 | { |
54 | | - translate_fw(trans); |
55 | | - back_socket->b_transport(trans, delay); |
56 | | - translate_bw(trans); |
| 94 | + uint64_t orig_addr = trans.get_address(); |
| 95 | + uint64_t mapped_addr = map_txn_addr(trans); |
| 96 | + SCP_DEBUG(()) << "b_transport to addr: 0x" << std::hex << orig_addr << " will be mapped to addr: 0x" << std::hex |
| 97 | + << mapped_addr; |
| 98 | + initiator_socket->b_transport(trans, delay); |
| 99 | + trans.set_address(orig_addr); |
57 | 100 | } |
58 | 101 |
|
59 | 102 | unsigned int transport_dbg(tlm::tlm_generic_payload& trans) |
60 | 103 | { |
61 | | - sc_dt::uint64 addr = trans.get_address(); |
62 | | - |
63 | | - translate_fw(trans); |
64 | | - unsigned int r = back_socket->transport_dbg(trans); |
65 | | - translate_bw(trans); |
66 | | - return r; |
| 104 | + uint64_t orig_addr = trans.get_address(); |
| 105 | + uint64_t mapped_addr = map_txn_addr(trans); |
| 106 | + SCP_DEBUG(()) << "transport_dbg to addr: 0x" << std::hex << orig_addr << " will be mapped to addr: 0x" |
| 107 | + << std::hex << mapped_addr; |
| 108 | + unsigned int ret = initiator_socket->transport_dbg(trans); |
| 109 | + trans.set_address(orig_addr); |
| 110 | + return ret; |
67 | 111 | } |
68 | 112 |
|
69 | 113 | bool get_direct_mem_ptr(tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data) |
70 | 114 | { |
71 | | - sc_dt::uint64 addr = trans.get_address(); |
72 | | - |
73 | | - translate_fw(trans); |
74 | | - bool r = back_socket->get_direct_mem_ptr(trans, dmi_data); |
75 | | - translate_bw(trans); |
76 | | - return r; |
| 115 | + uint64_t orig_addr = trans.get_address(); |
| 116 | + uint64_t mapped_addr = map_txn_addr(trans); |
| 117 | + bool ret = initiator_socket->get_direct_mem_ptr(trans, dmi_data); |
| 118 | + trans.set_address(orig_addr); |
| 119 | + if (ret) { |
| 120 | + uint64_t start_addr = dmi_data.get_start_address(); |
| 121 | + uint64_t end_addr = dmi_data.get_end_address(); |
| 122 | + map_dmi_start_end_addr(start_addr, end_addr); |
| 123 | + dmi_data.set_start_address(start_addr); |
| 124 | + dmi_data.set_end_address(end_addr); |
| 125 | + SCP_DEBUG(()) << "DMI was granted to range 0x" << std::hex << start_addr << " - 0x" << std::hex << end_addr; |
| 126 | + } |
| 127 | + return ret; |
77 | 128 | } |
78 | 129 |
|
79 | 130 | void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) |
80 | 131 | { |
81 | | - front_socket->invalidate_direct_mem_ptr(addr_bw(start), addr_bw(end)); |
| 132 | + uint64_t start_addr = start; |
| 133 | + uint64_t end_addr = end; |
| 134 | + map_dmi_start_end_addr(start_addr, end_addr); |
| 135 | + SCP_DEBUG(()) << "invalidate_direct_mem_ptr request to range 0x" << std::hex << start_addr << " - 0x" |
| 136 | + << std::hex << end_addr; |
| 137 | + target_socket->invalidate_direct_mem_ptr(start_addr, end_addr); |
82 | 138 | } |
83 | 139 |
|
| 140 | +private: |
| 141 | + cci::cci_broker_handle m_broker; |
| 142 | + uint64_t m_base_addr; |
| 143 | + uint64_t m_mapping_size; |
| 144 | + |
84 | 145 | public: |
85 | | - tlm_utils::simple_target_socket<addrtr, DEFAULT_TLM_BUSWIDTH> front_socket; |
86 | | - tlm_utils::simple_initiator_socket<addrtr, DEFAULT_TLM_BUSWIDTH> back_socket; |
87 | | - cci::cci_param<uint64_t> offset; |
| 146 | + tlm_utils::simple_target_socket<addrtr, DEFAULT_TLM_BUSWIDTH> target_socket; |
| 147 | + tlm_utils::simple_initiator_socket<addrtr, DEFAULT_TLM_BUSWIDTH> initiator_socket; |
| 148 | + cci::cci_param<uint64_t> p_mapped_base_addr; |
88 | 149 |
|
| 150 | +public: |
89 | 151 | explicit addrtr(const sc_core::sc_module_name& nm) |
90 | | - : sc_core::sc_module(nm), back_socket("initiator"), front_socket("target"), offset("offset", 0) |
| 152 | + : sc_core::sc_module(nm) |
| 153 | + , m_broker(cci::cci_get_broker()) |
| 154 | + , initiator_socket("initiator_socket") |
| 155 | + , target_socket("target_socket") |
| 156 | + , p_mapped_base_addr("mapped_base_addr", 0, "base adress for mapping") |
91 | 157 | { |
92 | | - front_socket.register_b_transport(this, &addrtr::b_transport); |
93 | | - front_socket.register_transport_dbg(this, &addrtr::transport_dbg); |
94 | | - front_socket.register_get_direct_mem_ptr(this, &addrtr::get_direct_mem_ptr); |
95 | | - back_socket.register_invalidate_direct_mem_ptr(this, &addrtr::invalidate_direct_mem_ptr); |
| 158 | + SCP_TRACE(())("addrtr constructor"); |
| 159 | + target_socket.register_b_transport(this, &addrtr::b_transport); |
| 160 | + target_socket.register_transport_dbg(this, &addrtr::transport_dbg); |
| 161 | + target_socket.register_get_direct_mem_ptr(this, &addrtr::get_direct_mem_ptr); |
| 162 | + initiator_socket.register_invalidate_direct_mem_ptr(this, &addrtr::invalidate_direct_mem_ptr); |
| 163 | + m_base_addr = gs::cci_get<uint64_t>(m_broker, |
| 164 | + std::string(sc_core::sc_module::name()) + ".target_socket.address"); |
| 165 | + m_mapping_size = gs::cci_get<uint64_t>(m_broker, |
| 166 | + std::string(sc_core::sc_module::name()) + ".target_socket.size"); |
96 | 167 | } |
97 | 168 |
|
98 | 169 | addrtr() = delete; |
|
0 commit comments