quic/qbox
Loading...
Searching...
No Matches
qemu-initiator-signal-socket.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_INITIATOR_SIGNAL_SOCKET_H
10#define _LIBQBOX_PORTS_INITIATOR_SIGNAL_SOCKET_H
11
12#include <functional>
13#include <cassert>
14
15#include <libqemu-cxx/libqemu-cxx.h>
16
17#include <ports/target-signal-socket.h>
18#include <ports/initiator-signal-socket.h>
19
20#include <libgssync.h>
21
22#include <ports/qemu-target-signal-socket.h>
23
39class QemuInitiatorSignalSocket : public InitiatorSignalSocket<bool>
40{
41protected:
42 qemu::Gpio m_proxy;
43 gs::runonsysc m_on_sysc;
44 QemuTargetSignalSocket* m_qemu_remote = nullptr;
45
46 void event_cb(bool val)
47 {
48 if (m_qemu_remote && (m_qemu_remote->get_gpio().same_inst_as(m_proxy))) {
49 /*
50 * We make sure to be in the same instance as the target socket.
51 * Otherwise we would need to hold the target's QEMU instance
52 * iothread lock. This would require us to unlock our own lock
53 * first to ensure we won't deadlock because of a race condition
54 * between two initiators trying to set a GPIO in one another.
55 * Don't bother with that. Instead, use the SystemC kernel as a
56 * synchronization point in this case.
57 */
58 m_qemu_remote->get_gpio().set(val);
59
60 m_on_sysc.run_on_sysc([this] { m_qemu_remote->notify(); }, false);
61
62 return;
63 }
64
65 if (!get_interface()) {
66 return;
67 }
68
69 m_proxy.get_inst().unlock_iothread();
70
71 m_on_sysc.run_on_sysc([this, val] { (*this)->write(val); });
72
73 m_proxy.get_inst().lock_iothread();
74 }
75
76 void init_qemu_to_sysc_gpio_proxy(qemu::Device& dev)
77 {
78 using namespace std::placeholders;
79
80 m_proxy = dev.get_inst().gpio_new();
81
82 auto cb = std::bind(&QemuInitiatorSignalSocket::event_cb, this, _1);
83 m_proxy.set_event_callback(cb);
84 }
85
86 void init_internal(qemu::Device& dev)
87 {
88 sc_core::sc_interface* iface;
91
92 init_qemu_to_sysc_gpio_proxy(dev);
93
94 iface = get_interface();
95
96 /* Check if we're bound to a TargetSignalSocket<bool> */
97 socket_iface = dynamic_cast<TargetSignalSocketProxy<bool>*>(iface);
98
99 if (socket_iface == nullptr) {
100 return;
101 }
102
103 /* Check if we're bound to a QemuTargetSignalSocket */
104 remote = dynamic_cast<QemuTargetSignalSocket*>(&socket_iface->get_parent());
105
106 if (remote == nullptr) {
107 return;
108 }
109
110 /*
111 * We could connect the GPIOs from within QEMU directly, but we don't
112 * know if the remote initialization is done yet. Instead, keep a
113 * pointer on the remote to change its GPIO directly in event_cb()
114 * instead of going through the SystemC kernel.
115 */
116 m_qemu_remote = remote;
117 }
118
119public:
120 QemuInitiatorSignalSocket(const char* name)
121 : InitiatorSignalSocket<bool>(name), m_on_sysc(sc_core::sc_gen_unique_name("run_on_sysc"))
122 {
123 }
124
125 ~QemuInitiatorSignalSocket() { m_proxy.set_event_callback(nullptr); }
126
138 {
139 init_internal(dev);
140 dev.connect_gpio_out(gpio_idx, m_proxy);
141 }
142
156 {
157 init_internal(dev);
158 dev.connect_gpio_out_named(gpio_name, gpio_idx, m_proxy);
159 }
160
174 {
175 init_internal(sbd);
176 sbd.connect_gpio_out(gpio_idx, m_proxy);
177 }
178};
179
180#endif
A QEMU output GPIO exposed as a InitiatorSignalSocket<bool>
Definition qemu-initiator-signal-socket.h:40
void init_sbd(qemu::SysBusDevice sbd, int gpio_idx)
Initialize this socket with a QEMU SysBusDevice, and a GPIO index.
Definition qemu-initiator-signal-socket.h:173
void init_named(qemu::Device dev, const char *gpio_name, int gpio_idx)
Initialize this socket with a device, a GPIO namespace, and a GPIO index.
Definition qemu-initiator-signal-socket.h:155
void init(qemu::Device dev, int gpio_idx)
Initialize this socket with a device and a GPIO index.
Definition qemu-initiator-signal-socket.h:137
A QEMU input GPIO exposed as a TargetSignalSocket<bool>
Definition qemu-target-signal-socket.h:29
void notify()
Force a notification on the default event.
Definition qemu-target-signal-socket.h:94
qemu::Gpio get_gpio()
Returns the GPIO wrapped by this socket.
Definition qemu-target-signal-socket.h:89
Definition target.h:160
Definition runonsysc.h:22
bool run_on_sysc(std::function< void()> job_entry, bool wait=true)
Run a job on the SystemC kernel thread.
Definition runonsysc.h:181
Definition libqemu-cxx.h:616
Definition libqemu-cxx.h:273
Definition libqemu-cxx.h:638