tfhe_hpu_backend/ffi/sim/
ipc.rs1use ipc_channel::ipc::{self, IpcOneShotServer, IpcReceiver, IpcSender};
4use std::fs::OpenOptions;
5use std::io::{BufRead, BufReader, Write};
6use std::path::Path;
7use std::sync::{Arc, Mutex};
8
9use serde::{Deserialize, Serialize};
10
11use crate::entities::HpuPBSParameters;
12use crate::ffi::{self, SyncMode};
13
14#[derive(Debug, Serialize, Deserialize)]
16pub enum RegisterReq {
17 Read { addr: u64 },
18 Write { addr: u64, value: u32 },
19 PbsParams,
20}
21
22#[derive(Debug, Serialize, Deserialize)]
24pub enum RegisterAck {
25 Read(u32),
26 Write,
27 PbsParams(HpuPBSParameters),
28}
29
30#[derive(Debug, Serialize, Deserialize)]
32pub(crate) struct RegisterFfi {
33 pub(crate) req: IpcSender<RegisterReq>,
34 pub(crate) ack: IpcReceiver<RegisterAck>,
35}
36#[derive(Debug, Serialize, Deserialize)]
38pub struct RegisterSim {
39 pub req: IpcReceiver<RegisterReq>,
40 pub ack: IpcSender<RegisterAck>,
41}
42
43pub(crate) fn register_channel() -> (RegisterFfi, RegisterSim) {
44 let (req_tx, req_rx) = ipc::channel().unwrap();
45 let (ack_tx, ack_rx) = ipc::channel().unwrap();
46
47 (
48 RegisterFfi {
49 req: req_tx,
50 ack: ack_rx,
51 },
52 RegisterSim {
53 req: req_rx,
54 ack: ack_tx,
55 },
56 )
57}
58
59#[derive(Debug, Serialize, Deserialize)]
61pub enum MemoryReq {
62 Allocate {
63 mem_kind: ffi::MemKind,
64 size_b: usize,
65 },
66 Sync {
67 mem_kind: ffi::MemKind,
68 addr: u64,
69 mode: SyncMode,
70 data: Option<ipc::IpcSharedMemory>,
71 },
72 Release {
73 mem_kind: ffi::MemKind,
74 addr: u64,
75 },
76}
77
78#[derive(Debug, Serialize, Deserialize)]
80pub enum MemoryAck {
81 Allocate { addr: u64 },
82 Sync { data: Option<ipc::IpcSharedMemory> },
83 Release,
84}
85
86#[derive(Debug, Serialize, Deserialize)]
88pub(crate) struct MemoryFfi {
89 pub(crate) req: IpcSender<MemoryReq>,
90 pub(crate) ack: IpcReceiver<MemoryAck>,
91}
92#[derive(Debug, Clone, Serialize, Deserialize)]
95pub(crate) struct MemoryFfiWrapped(pub(crate) Arc<Mutex<MemoryFfi>>);
96
97impl From<MemoryFfi> for MemoryFfiWrapped {
98 fn from(value: MemoryFfi) -> Self {
99 Self(Arc::new(Mutex::new(value)))
100 }
101}
102
103#[derive(Debug, Serialize, Deserialize)]
105pub struct MemorySim {
106 pub req: IpcReceiver<MemoryReq>,
107 pub ack: IpcSender<MemoryAck>,
108}
109
110pub(crate) fn memory_channel() -> (MemoryFfi, MemorySim) {
111 let (req_tx, req_rx) = ipc::channel().unwrap();
112 let (ack_tx, ack_rx) = ipc::channel().unwrap();
113
114 (
115 MemoryFfi {
116 req: req_tx,
117 ack: ack_rx,
118 },
119 MemorySim {
120 req: req_rx,
121 ack: ack_tx,
122 },
123 )
124}
125
126#[derive(Debug, Serialize, Deserialize)]
129pub(crate) struct IpcFfi {
130 pub(crate) register: RegisterFfi,
131 pub(crate) memory: MemoryFfiWrapped,
132}
133
134impl IpcFfi {
135 pub fn new_bind_on(ipc_name: &str) -> IpcFfi {
139 let mut rd_f = BufReader::new(
141 OpenOptions::new()
142 .create(false)
143 .read(true)
144 .open(ipc_name)
145 .unwrap(),
146 );
147 let oneshot_name = {
149 let mut name = String::new();
150 rd_f.read_line(&mut name).unwrap();
151 name
152 };
153 tracing::debug!("Will bind through {oneshot_name}");
154
155 let bind_tx = IpcSender::connect(oneshot_name).unwrap();
157
158 let (ffi, sim) = ipc_channel();
160 bind_tx.send(sim).unwrap();
161
162 ffi
163 }
164}
165
166#[derive(Debug, Serialize, Deserialize)]
167pub struct IpcSim {
168 pub register: RegisterSim,
169 pub memory: MemorySim,
170}
171impl IpcSim {
172 pub fn new_bind_on(ipc_name: &str) -> IpcSim {
174 let (oneshot_server, oneshot_name) = IpcOneShotServer::new().unwrap();
176 let path = Path::new(ipc_name);
179 if let Some(dir_p) = path.parent() {
180 std::fs::create_dir_all(dir_p).unwrap();
181 }
182 let mut wr_f = OpenOptions::new()
184 .create(true)
185 .write(true)
186 .truncate(true)
187 .open(ipc_name)
188 .unwrap();
189 write!(wr_f, "{oneshot_name}").unwrap();
190
191 tracing::info!("Mockup waiting on IPC `{oneshot_name}`");
192 let (_, ipc_sim): (_, IpcSim) = oneshot_server.accept().unwrap();
193
194 ipc_sim
195 }
196}
197
198pub(crate) fn ipc_channel() -> (IpcFfi, IpcSim) {
199 let (register_ffi, register_sim) = register_channel();
200 let (memory_ffi, memory_sim) = memory_channel();
201
202 (
203 IpcFfi {
204 register: register_ffi,
205 memory: MemoryFfiWrapped::from(memory_ffi),
206 },
207 IpcSim {
208 register: register_sim,
209 memory: memory_sim,
210 },
211 )
212}