quic/qbox
Loading...
Searching...
No Matches
target.h
1/*
2 * This file is part of libqbox
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
4 * Author: GreenSocs 2021
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9#ifndef _LIBQBOX_PORTS_TARGET_H
10#define _LIBQBOX_PORTS_TARGET_H
11
12#include <tlm>
13
14#include "qemu-instance.h"
15#include "tlm-extensions/qemu-cpu-hint.h"
16#include "tlm-extensions/qemu-mr-hint.h"
17#include <tlm_sockets_buswidth.h>
18
19class TlmTargetToQemuBridge : public tlm::tlm_fw_transport_if<>
20{
21public:
23 using MemTxResult = qemu::MemoryRegion::MemTxResult;
24 using TlmPayload = tlm::tlm_generic_payload;
25
26protected:
28 std::shared_ptr<qemu::AddressSpace> m_as;
29
30 void init_as()
31 {
32 m_as = m_mr.get_inst().address_space_new();
33 m_as->init(m_mr, "qemu-target-socket");
34 }
35
36 qemu::Cpu push_current_cpu(TlmPayload& trans)
37 {
40
41 trans.get_extension(ext);
42
43 if (ext == nullptr) {
44 /* return an invalid object */
45 return ret;
46 }
47
48 qemu::Cpu initiator(ext->get_cpu());
49
50 if (initiator.get_inst_id() != m_mr.get_inst_id()) {
51 /* return an invalid object */
52 return ret;
53 }
54
55 ret = initiator.set_as_current();
56
57 return ret;
58 }
59
60 void pop_current_cpu(qemu::Cpu cpu)
61 {
62 if (!cpu.valid()) {
63 return;
64 }
65
66 cpu.set_as_current();
67 }
68
69public:
70 void init(qemu::SysBusDevice sbd, int mmio_idx)
71 {
72 m_mr = sbd.mmio_get_region(mmio_idx);
73 init_as();
74 }
75
76 void init_with_mr(qemu::MemoryRegion mr)
77 {
78 m_mr = mr;
79 init_as();
80 }
81
82 virtual void b_transport(TlmPayload& trans, sc_core::sc_time& t)
83 {
84 uint64_t addr = trans.get_address();
85 uint64_t* data = reinterpret_cast<uint64_t*>(trans.get_data_ptr());
86 unsigned int size = trans.get_data_length();
88 MemTxResult res;
90
91 if (trans.get_command() == tlm::TLM_IGNORE_COMMAND) {
92 trans.set_response_status(tlm::TLM_OK_RESPONSE);
93 return;
94 }
95
96 current_cpu_save = push_current_cpu(trans);
97
98 switch (trans.get_command()) {
99 case tlm::TLM_READ_COMMAND:
100 res = m_as->read(addr, data, size, attrs);
101 break;
102
103 case tlm::TLM_WRITE_COMMAND:
104 res = m_as->write(addr, data, size, attrs);
105 break;
106
107 default:
108 /* TLM_IGNORE_COMMAND already handled above */
109 assert(false);
110 return;
111 }
112
113 trans.set_extension(new QemuMrHintTlmExtension(m_mr, addr));
114
115 switch (res) {
116 case qemu::MemoryRegionOps::MemTxOK:
117 trans.set_response_status(tlm::TLM_OK_RESPONSE);
118 break;
119
120 case qemu::MemoryRegionOps::MemTxDecodeError:
121 trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
122 break;
123
124 case qemu::MemoryRegionOps::MemTxError:
125 trans.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
126 break;
127
128 default:
129 trans.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
130 break;
131 }
132
133 pop_current_cpu(current_cpu_save);
134 }
135
136 virtual tlm::tlm_sync_enum nb_transport_fw(TlmPayload& trans, tlm::tlm_phase& phase, sc_core::sc_time& t)
137 {
138 /* TODO: report an error */
139 abort();
140 return tlm::TLM_ACCEPTED;
141 }
142
143 virtual bool get_direct_mem_ptr(TlmPayload& trans, tlm::tlm_dmi& dmi_data) { return false; }
144
145 virtual unsigned int transport_dbg(TlmPayload& trans)
146 {
147 unsigned int size = trans.get_data_length();
148 sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
149 b_transport(trans, delay);
150 if (trans.get_response_status() == tlm::TLM_OK_RESPONSE)
151 return size;
152 else
153 return 0;
154 }
155};
156
157template <unsigned int BUSWIDTH = DEFAULT_TLM_BUSWIDTH>
159 : public tlm::tlm_target_socket<BUSWIDTH, tlm::tlm_base_protocol_types, 1, sc_core::SC_ZERO_OR_MORE_BOUND>
160{
161public:
162 using TlmTargetSocket = tlm::tlm_target_socket<BUSWIDTH, tlm::tlm_base_protocol_types, 1,
163 sc_core::SC_ZERO_OR_MORE_BOUND>;
164 using TlmPayload = tlm::tlm_generic_payload;
165
166protected:
167 TlmTargetToQemuBridge m_bridge;
168 QemuInstance& m_inst;
169 qemu::SysBusDevice m_sbd;
170
171public:
172 QemuTargetSocket(const char* name, QemuInstance& inst): TlmTargetSocket(name), m_inst(inst)
173 {
174 TlmTargetSocket::bind(m_bridge);
175 }
176
177 void init(qemu::SysBusDevice sbd, int mmio_idx) { m_bridge.init(sbd, mmio_idx); }
178
179 void init_with_mr(qemu::MemoryRegion mr) { m_bridge.init_with_mr(mr); }
180};
181
182#endif
Definition qemu-cpu-hint.h:17
This class encapsulates a libqemu-cxx qemu::LibQemu instance. It handles QEMU parameters and instance...
Definition qemu-instance.h:89
Definition qemu-mr-hint.h:17
Definition target.h:160
Definition target.h:20
Definition libqemu-cxx.h:664
Definition libqemu-cxx.h:362
Definition libqemu-cxx.h:638
Definition libqemu-cxx.h:325