1use parameters::HpuNttPrime;
7
8use super::*;
9use crate::entities::*;
10
11pub const NTT_CORE_ARCH_OFS: u32 = 5 << 8;
14pub const MOD_NTT_NAME_OFS: u32 = 6 << 8;
15pub const APPLICATION_NAME_OFS: u32 = 7 << 8;
16pub const SIMULATION_CODE: u32 = 1;
17
18impl FromRtl for HpuParameters {
19 fn from_rtl(ffi_hw: &mut ffi::HpuHw, regmap: &FlatRegmap) -> Self {
20 let pbs_params = HpuPBSParameters::from_rtl(ffi_hw, regmap);
21 let ntt_params = HpuNttParameters::from_rtl(ffi_hw, regmap);
22 let ks_params = HpuKeyswitchParameters::from_rtl(ffi_hw, regmap);
23 let pc_params = HpuPcParameters::from_rtl(ffi_hw, regmap);
24 let regf_params = HpuRegfileParameters::from_rtl(ffi_hw, regmap);
25 let isc_params = HpuIscParameters::from_rtl(ffi_hw, regmap);
26 Self {
27 pbs_params,
28 ntt_params,
29 ks_params,
30 pc_params,
31 regf_params,
32 isc_params,
33 }
34 }
35}
36
37impl FromRtl for HpuKeyswitchParameters {
38 fn from_rtl(ffi_hw: &mut ffi::HpuHw, regmap: &FlatRegmap) -> Self {
39 let ks_shape = regmap
40 .register()
41 .get("info::ks_structure")
42 .expect("Unknown register, check regmap definition");
43 let shape_val = ffi_hw.read_reg(*ks_shape.offset() as u64);
44 let shape_fields = ks_shape.as_field(shape_val);
45
46 let ks_info = regmap
47 .register()
48 .get("info::ks_crypto_param")
49 .expect("Unknown register, check regmap definition");
50 let info_val = ffi_hw.read_reg(*ks_info.offset() as u64);
51 let info_fields = ks_info.as_field(info_val);
52
53 Self {
54 width: *info_fields.get("mod_ksk_w").expect("Unknown field") as usize,
55 lbx: *shape_fields.get("x").expect("Unknown field") as usize,
56 lby: *shape_fields.get("y").expect("Unknown field") as usize,
57 lbz: *shape_fields.get("z").expect("Unknown field") as usize,
58 }
59 }
60}
61impl FromRtl for HpuNttParameters {
62 fn from_rtl(ffi_hw: &mut ffi::HpuHw, regmap: &FlatRegmap) -> Self {
63 let core_arch = HpuNttCoreArch::from_rtl(ffi_hw, regmap);
64
65 let ntt_internal = regmap
67 .register()
68 .get("info::ntt_structure")
69 .expect("Unknown register, check regmap definition");
70 let internal_val = ffi_hw.read_reg(*ntt_internal.offset() as u64);
71 let internal_fields = ntt_internal.as_field(internal_val);
72
73 let radix = *internal_fields.get("radix").expect("Unknown field") as usize;
74 let psi = *internal_fields.get("psi").expect("Unknown field") as usize;
75 let delta = *internal_fields.get("delta").expect("Unknown field") as usize;
76
77 let ntt_pbs_nb = regmap
79 .register()
80 .get("info::ntt_pbs")
81 .expect("Unknown register, check regmap definition");
82 let pbs_nb_val = ffi_hw.read_reg(*ntt_pbs_nb.offset() as u64);
83 let pbs_nb_fields = ntt_pbs_nb.as_field(pbs_nb_val);
84
85 let batch_pbs_nb = *pbs_nb_fields.get("batch_pbs_nb").expect("Unknown field") as usize;
86 let total_pbs_nb = *pbs_nb_fields.get("total_pbs_nb").expect("Unknown field") as usize;
87
88 let ntt_modulo = regmap
91 .register()
92 .get("info::ntt_modulo")
93 .expect("Unknown register, check regmap definition");
94 let ntt_modulo_val = ffi_hw.read_reg(*ntt_modulo.offset() as u64);
95
96 let prime_modulus = {
97 let field_code = ntt_modulo_val & (!0xFF_u32);
99 assert_eq!(
100 field_code, MOD_NTT_NAME_OFS,
101 "Invalid register encoding. Check register map definition"
102 );
103 match (ntt_modulo_val & 0xFF) as u8 {
104 enum_id if enum_id == HpuNttPrime::GF64 as u8 => HpuNttPrime::GF64,
105 enum_id if enum_id == HpuNttPrime::Solinas3_32_17_13 as u8 => {
106 HpuNttPrime::Solinas3_32_17_13
107 }
108 enum_id if enum_id == HpuNttPrime::Solinas2_44_14 as u8 => {
109 HpuNttPrime::Solinas2_44_14
110 }
111 _ => panic!("Unknown NttModName encoding"),
112 }
113 };
114
115 let pbs_params = HpuPBSParameters::from_rtl(ffi_hw, regmap);
119 let stg_nb = pbs_params.polynomial_size.ilog(radix) as usize;
120
121 Self {
122 core_arch,
123 min_pbs_nb: None, batch_pbs_nb,
125 total_pbs_nb,
126 ct_width: pbs_params.ciphertext_width as u32,
127 radix,
128 stg_nb,
129 prime_modulus,
130 psi,
131 delta,
132 }
133 }
134}
135
136impl FromRtl for HpuNttCoreArch {
137 fn from_rtl(ffi_hw: &mut ffi::HpuHw, regmap: &FlatRegmap) -> Self {
138 let ntt_core_arch = regmap
141 .register()
142 .get("info::ntt_architecture")
143 .expect("Unknown register, check regmap definition");
144 let ntt_core_arch_val = ffi_hw.read_reg(*ntt_core_arch.offset() as u64);
145
146 let field_code = ntt_core_arch_val & (!0xFF_u32);
148 assert_eq!(
149 field_code, NTT_CORE_ARCH_OFS,
150 "Invalid register encoding. Check register map definition"
151 );
152
153 match ntt_core_arch_val & 0xFF {
154 3 => Self::WmmCompactPcg,
156 4 => Self::WmmUnfoldPcg,
157 5 => {
158 let radix_cut = regmap
161 .register()
162 .get("info::ntt_rdx_cut")
163 .expect("Unknown register, check regmap definition");
164 let radix_cut_val = ffi_hw.read_reg(*radix_cut.offset() as u64);
165 let cut_l = (0..(u32::BITS / 4))
166 .map(|ofst| ((radix_cut_val >> (ofst * 4)) & 0xf) as u8)
167 .filter(|x| *x != 0)
168 .collect::<Vec<u8>>();
169 Self::GF64(cut_l)
170 }
171 _ => panic!("Unknown NttCoreArch encoding"),
172 }
173 }
174}
175
176impl FromRtl for HpuPcParameters {
177 fn from_rtl(ffi_hw: &mut ffi::HpuHw, regmap: &FlatRegmap) -> Self {
178 let hbm_pc = regmap
180 .register()
181 .get("info::hbm_axi4_nb")
182 .expect("Unknown register, check regmap definition");
183 let hbm_pc_val = ffi_hw.read_reg(*hbm_pc.offset() as u64);
184 let hbm_pc_fields = hbm_pc.as_field(hbm_pc_val);
185
186 let ksk_pc = *hbm_pc_fields.get("ksk_pc").expect("Unknown field") as usize;
187 let bsk_pc = *hbm_pc_fields.get("bsk_pc").expect("Unknown field") as usize;
188 let pem_pc = *hbm_pc_fields.get("pem_pc").expect("Unknown field") as usize;
189
190 let ksk_bytes_w = {
192 let ksk_axi4_data_w = regmap
193 .register()
194 .get("info::hbm_axi4_dataw_ksk")
195 .expect("Unknown register, check regmap definition");
196 let ksk_axi4_data_w_val = ffi_hw.read_reg(*ksk_axi4_data_w.offset() as u64);
197 ksk_axi4_data_w_val.div_ceil(u8::BITS) as usize
199 };
200 let bsk_bytes_w = {
201 let bsk_axi4_data_w = regmap
202 .register()
203 .get("info::hbm_axi4_dataw_bsk")
204 .expect("Unknown register, check regmap definition");
205 let bsk_axi4_data_w_val = ffi_hw.read_reg(*bsk_axi4_data_w.offset() as u64);
206 bsk_axi4_data_w_val.div_ceil(u8::BITS) as usize
208 };
209 let pem_bytes_w = {
210 let pem_axi4_data_w = regmap
211 .register()
212 .get("info::hbm_axi4_dataw_pem")
213 .expect("Unknown register, check regmap definition");
214 let pem_axi4_data_w_val = ffi_hw.read_reg(*pem_axi4_data_w.offset() as u64);
215 pem_axi4_data_w_val.div_ceil(u8::BITS) as usize
217 };
218 let glwe_bytes_w = {
219 let glwe_axi4_data_w = regmap
220 .register()
221 .get("info::hbm_axi4_dataw_glwe")
222 .expect("Unknown register, check regmap definition");
223 let glwe_axi4_data_w_val = ffi_hw.read_reg(*glwe_axi4_data_w.offset() as u64);
224 glwe_axi4_data_w_val.div_ceil(u8::BITS) as usize
226 };
227
228 Self {
229 ksk_pc,
230 bsk_pc,
231 pem_pc,
232 ksk_bytes_w,
233 bsk_bytes_w,
234 pem_bytes_w,
235 glwe_bytes_w,
236 }
237 }
238}
239
240impl FromRtl for HpuRegfileParameters {
241 fn from_rtl(ffi_hw: &mut ffi::HpuHw, regmap: &FlatRegmap) -> Self {
242 let regf = regmap
243 .register()
244 .get("info::regf_structure")
245 .expect("Unknown register, check regmap definition");
246 let regf_val = ffi_hw.read_reg(*regf.offset() as u64);
247 let regf_fields = regf.as_field(regf_val);
248
249 Self {
250 reg_nb: *regf_fields.get("reg_nb").expect("Unknown field") as usize,
251 coef_nb: *regf_fields.get("coef_nb").expect("Unknown field") as usize,
252 }
253 }
254}
255
256impl FromRtl for HpuIscParameters {
257 fn from_rtl(ffi_hw: &mut ffi::HpuHw, regmap: &FlatRegmap) -> Self {
258 let isc = regmap
259 .register()
260 .get("info::isc_structure")
261 .expect("Unknown register, check regmap definition");
262 let isc_val = ffi_hw.read_reg(*isc.offset() as u64);
263 let isc_fields = isc.as_field(isc_val);
264
265 Self {
266 min_iop_size: *isc_fields.get("min_iop_size").expect("Unknown field") as usize,
267 depth: *isc_fields.get("depth").expect("Unknown field") as usize,
268 }
269 }
270}
271
272pub const CONCRETE_BOOLEAN: HpuPBSParameters = HpuPBSParameters {
275 lwe_dimension: 586,
276 glwe_dimension: 2,
277 polynomial_size: 512,
278 lwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(0.00000000007069849454709433),
279 glwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(
280 0.0000000000000000000029403601535432533,
281 ),
282 pbs_base_log: 8,
283 pbs_level: 2,
284 ks_base_log: 5,
285 ks_level: 4,
286 message_width: 1,
287 carry_width: 0,
288 ciphertext_width: 32,
289 log2_p_fail: -64.0,
290 modulus_switch_type: parameters::HpuModulusSwitchType::Standard,
291};
292
293pub const MSG2_CARRY2: HpuPBSParameters = HpuPBSParameters {
294 lwe_dimension: 742,
295 glwe_dimension: 1,
296 polynomial_size: 2048,
297 lwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(9.039_924_320_497_611e-6_f64),
298 glwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(3.1529314934984704e-16_f64),
299 pbs_base_log: 19,
300 pbs_level: 1,
301 ks_base_log: 3,
302 ks_level: 5,
303 message_width: 2,
304 carry_width: 2,
305 ciphertext_width: u64::BITS as usize,
306 log2_p_fail: -64.0,
307 modulus_switch_type: parameters::HpuModulusSwitchType::Standard,
308};
309
310pub const MSG2_CARRY2_64B: HpuPBSParameters = HpuPBSParameters {
311 lwe_dimension: 710,
312 glwe_dimension: 2,
313 polynomial_size: 1024,
314 lwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(1.630_783_646_854_603e-5_f64),
315 glwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(3.1529314934984704e-16_f64),
316 pbs_base_log: 25,
317 pbs_level: 1,
318 ks_base_log: 2,
319 ks_level: 7,
320 message_width: 2,
321 carry_width: 2,
322 ciphertext_width: u64::BITS as usize,
323 log2_p_fail: -64.0,
324 modulus_switch_type: parameters::HpuModulusSwitchType::Standard,
325};
326
327pub const MSG2_CARRY2_44B: HpuPBSParameters = HpuPBSParameters {
328 lwe_dimension: 724,
329 glwe_dimension: 2,
330 polynomial_size: 1024,
331 lwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(
332 1.259_780_968_897_627_7e-5_f64,
333 ),
334 glwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(2.2737367544323206e-13_f64),
335 pbs_base_log: 20,
336 pbs_level: 1,
337 ks_base_log: 2,
338 ks_level: 7,
339 message_width: 2,
340 carry_width: 2,
341 ciphertext_width: 44,
342 log2_p_fail: -64.0,
343 modulus_switch_type: parameters::HpuModulusSwitchType::Standard,
344};
345
346pub const MSG2_CARRY2_64B_FAKE: HpuPBSParameters = HpuPBSParameters {
347 lwe_dimension: 724,
348 glwe_dimension: 2,
349 polynomial_size: 1024,
350 lwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(
351 1.259_780_968_897_627_7e-5_f64,
352 ),
353 glwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(2.2737367544323206e-13_f64),
354 pbs_base_log: 20,
355 pbs_level: 1,
356 ks_base_log: 2,
357 ks_level: 7,
358 message_width: 2,
359 carry_width: 2,
360 ciphertext_width: 64,
361 log2_p_fail: -64.0,
362 modulus_switch_type: parameters::HpuModulusSwitchType::Standard,
363};
364
365pub const MSG2_CARRY2_GAUSSIAN: HpuPBSParameters = HpuPBSParameters {
366 lwe_dimension: 834,
367 glwe_dimension: 1,
368 polynomial_size: 2048,
369 lwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(
370 3.553_990_235_944_282_5e-6_f64,
371 ),
372 glwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(2.845267479601915e-15_f64),
373 pbs_base_log: 23,
374 pbs_level: 1,
375 ks_base_log: 3,
376 ks_level: 5,
377 message_width: 2,
378 carry_width: 2,
379 ciphertext_width: 64,
380 log2_p_fail: -64.0,
381 modulus_switch_type: parameters::HpuModulusSwitchType::Standard,
382};
383
384pub const MSG2_CARRY2_TUNIFORM: HpuPBSParameters = HpuPBSParameters {
385 lwe_dimension: 887,
386 glwe_dimension: 1,
387 polynomial_size: 2048,
388 lwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(
389 3.553_990_235_944_282_5e-6_f64,
390 ),
391 glwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(2.845267479601915e-15_f64),
392 pbs_base_log: 22,
393 pbs_level: 1,
394 ks_base_log: 3,
395 ks_level: 5,
396 message_width: 2,
397 carry_width: 2,
398 ciphertext_width: 64,
399 log2_p_fail: -64.0,
400 modulus_switch_type: parameters::HpuModulusSwitchType::Standard,
401};
402
403pub const MSG2_CARRY2_PFAIL64_132B_GAUSSIAN_1F72DBA: HpuPBSParameters = HpuPBSParameters {
404 lwe_dimension: 804,
405 glwe_dimension: 1,
406 polynomial_size: 2048,
407 lwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(5.963_599_673_924_788e-6_f64),
408 glwe_noise_distribution: HpuNoiseDistributionInput::GaussianStdDev(2.8452674713391114e-15_f64),
409 pbs_base_log: 23,
410 pbs_level: 1,
411 ks_base_log: 2,
412 ks_level: 8,
413 message_width: 2,
414 carry_width: 2,
415 ciphertext_width: 64,
416 log2_p_fail: -64.0,
417 modulus_switch_type: parameters::HpuModulusSwitchType::Standard,
418};
419
420pub const MSG2_CARRY2_PFAIL64_132B_TUNIFORM_7E47D8C: HpuPBSParameters = HpuPBSParameters {
421 lwe_dimension: 839,
422 glwe_dimension: 1,
423 polynomial_size: 2048,
424 lwe_noise_distribution: HpuNoiseDistributionInput::TUniformBound(4),
425 glwe_noise_distribution: HpuNoiseDistributionInput::TUniformBound(17),
426 pbs_base_log: 23,
427 pbs_level: 1,
428 ks_base_log: 2,
429 ks_level: 7,
430 message_width: 2,
431 carry_width: 2,
432 ciphertext_width: 64,
433 log2_p_fail: -64.0,
434 modulus_switch_type: parameters::HpuModulusSwitchType::Standard,
435};
436
437pub const MSG2_CARRY2_PFAIL128_132B_TUNIFORM_144A47: HpuPBSParameters = HpuPBSParameters {
438 lwe_dimension: 879,
439 glwe_dimension: 1,
440 polynomial_size: 2048,
441 lwe_noise_distribution: HpuNoiseDistributionInput::TUniformBound(3),
442 glwe_noise_distribution: HpuNoiseDistributionInput::TUniformBound(17),
443 pbs_base_log: 23,
444 pbs_level: 1,
445 ks_base_log: 2,
446 ks_level: 8,
447 message_width: 2,
448 carry_width: 2,
449 ciphertext_width: 64,
450 log2_p_fail: -128.0,
451 modulus_switch_type: parameters::HpuModulusSwitchType::CenteredMeanNoiseReduction,
452};
453
454impl FromRtl for HpuPBSParameters {
455 fn from_rtl(ffi_hw: &mut ffi::HpuHw, regmap: &FlatRegmap) -> Self {
456 let pbs_app = regmap
457 .register()
458 .get("info::application")
459 .expect("Unknown register, check regmap definition");
460 let pbs_app_val = ffi_hw.read_reg(*pbs_app.offset() as u64);
461
462 let field_code = pbs_app_val & (!0xFF_u32);
464 #[cfg(not(any(feature = "hw-xrt", feature = "hw-v80")))]
465 {
466 if (field_code == 0) && (pbs_app_val == SIMULATION_CODE) {
467 tracing::warn!("Run an simulation backend with custom SIMU parameters set");
468 return ffi_hw.get_pbs_parameters();
469 }
470 }
471 #[cfg(any(feature = "hw-xrt", feature = "hw-v80"))]
472 {
473 assert_eq!(
474 field_code, APPLICATION_NAME_OFS,
475 "Invalid register encoding. Check register map definition"
476 );
477 }
478
479 match pbs_app_val & 0xFF {
480 0 => CONCRETE_BOOLEAN,
481 1 => MSG2_CARRY2,
482 2 => {
483 let mut params = MSG2_CARRY2;
484 params.lwe_dimension = 2;
485 params
486 }
487 3 => MSG2_CARRY2_64B,
488 4 => MSG2_CARRY2_44B,
489 9 => MSG2_CARRY2_64B_FAKE,
490 10 => MSG2_CARRY2_GAUSSIAN,
491 11 => MSG2_CARRY2_TUNIFORM,
492 12 => MSG2_CARRY2_PFAIL64_132B_GAUSSIAN_1F72DBA,
493 13 => MSG2_CARRY2_PFAIL64_132B_TUNIFORM_7E47D8C,
494 14 => MSG2_CARRY2_PFAIL128_132B_TUNIFORM_144A47,
495 _ => panic!("Unknown TfheAppName encoding"),
496 }
497 }
498}