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 void end_of_simulation() { m_proxy.set_event_callback(nullptr); }
86
87 void init_internal(qemu::Device& dev)
88 {
89 sc_core::sc_interface* iface;
92
93 init_qemu_to_sysc_gpio_proxy(dev);
94
95 iface = get_interface();
96
97 /* Check if we're bound to a TargetSignalSocket<bool> */
98 socket_iface = dynamic_cast<TargetSignalSocketProxy<bool>*>(iface);
99
100 if (socket_iface == nullptr) {
101 return;
102 }
103
104 /* Check if we're bound to a QemuTargetSignalSocket */
105 remote = dynamic_cast<QemuTargetSignalSocket*>(&socket_iface->get_parent());
106
107 if (remote == nullptr) {
108 return;
109 }
110
111 /*
112 * We could connect the GPIOs from within QEMU directly, but we don't
113 * know if the remote initialization is done yet. Instead, keep a
114 * pointer on the remote to change its GPIO directly in event_cb()
115 * instead of going through the SystemC kernel.
116 */
117 m_qemu_remote = remote;
118 }
119
120public:
121 QemuInitiatorSignalSocket(const char* name)
122 : InitiatorSignalSocket<bool>(name), m_on_sysc(sc_core::sc_gen_unique_name("run_on_sysc"))
123 {
124 }
125
126 ~QemuInitiatorSignalSocket() { m_proxy.set_event_callback(nullptr); }
127
139 {
140 init_internal(dev);
141 dev.connect_gpio_out(gpio_idx, m_proxy);
142 }
143
157 {
158 init_internal(dev);
159 dev.connect_gpio_out_named(gpio_name, gpio_idx, m_proxy);
160 }
161
175 {
176 init_internal(sbd);
177 sbd.connect_gpio_out(gpio_idx, m_proxy);
178 }
179};
180
181#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:174
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:156
void init(qemu::Device dev, int gpio_idx)
Initialize this socket with a device and a GPIO index.
Definition qemu-initiator-signal-socket.h:138
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:23
bool run_on_sysc(std::function< void()> job_entry, bool wait=true)
Run a job on the SystemC kernel thread.
Definition runonsysc.h:211
Definition libqemu-cxx.h:623
Definition libqemu-cxx.h:275
Definition libqemu-cxx.h:645