rhdl_dsig_scalable_core/ubft/
card.rs1use super::Axis512;
34use super::engine::{CfgWrite, UbftEngine, UbftInput, UbftOutput};
35use super::probe::{ProbeArgs, ProbeIn, UbftProbe};
36use crate::axi4::{AxiLiteIn, AxiLiteOut, WriteRequest, WriteResponse};
37use crate::engine::set_half_kernel;
38use crate::hbm_writer::{HbmWriter, WriterInput};
39use rhdl::prelude::*;
40use rhdl_fpga::core::dff::DFF;
41
42pub const ARG_PROBE_COUNT: usize = 0x800;
44pub const ARG_PROBE_GAP: usize = 0x804;
46pub const ARG_PROBE_SLOT: usize = 0x808;
48pub const ARG_PROBE_TAMPER: usize = 0x80c;
50pub const ARG_PROBE_GO: usize = 0x810;
52pub const ARG_PROBE_ANNOUNCE: usize = 0x814;
54pub const ARG_FRAMES: usize = 0x818;
56pub const REG_PROBE_DONE: usize = 0x840;
58pub const REG_PROBE_MATCHED: usize = 0x844;
60pub const REG_PROBE_MISMATCHED: usize = 0x848;
62pub const REG_PROBE_FIRST_BAD: usize = 0x84c;
64pub const REG_FRAMES_WRITTEN: usize = 0x854;
66pub const REG_WRITE_ERROR: usize = 0x858;
68
69#[derive(Clone, Copy, Debug, PartialEq, Digital)]
71pub struct CardInput {
72 pub axi: AxiLiteIn,
74 pub frames: WriteResponse,
76}
77
78#[derive(Clone, Copy, Debug, PartialEq, Digital)]
80pub struct CardOutput {
81 pub axi: AxiLiteOut,
83 pub frames: WriteRequest,
85}
86
87#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
89#[doc(hidden)]
90pub struct CardControl {
91 args: ProbeArgs,
92 announce: bool,
94 ann_phase: b2,
96 frames_base: b64,
97 aw_have: bool,
98 aw_addr: b12,
99 w_have: bool,
100 w_data: b32,
101 b_valid: bool,
102 r_valid: bool,
103 r_data: b32,
104 w_busy: bool,
106 fwd_aw: bool,
108 fwd_w: bool,
110 r_busy: bool,
112 fwd_ar: bool,
114 ar_addr: b12,
115}
116
117#[derive(Clone, Debug, Synchronous, SynchronousDQ)]
119pub struct UbftCard<const TABLE_MASK: usize> {
120 control: DFF<CardControl>,
122 engine: UbftEngine<TABLE_MASK>,
124 probe: UbftProbe,
126 writer: HbmWriter,
128}
129
130impl<const TABLE_MASK: usize> Default for UbftCard<TABLE_MASK> {
131 fn default() -> Self {
133 Self {
134 control: DFF::new(CardControl::default()),
135 engine: UbftEngine::default(),
136 probe: UbftProbe::default(),
137 writer: HbmWriter::default(),
138 }
139 }
140}
141
142impl<const TABLE_MASK: usize> SynchronousIO for UbftCard<TABLE_MASK> {
143 type I = CardInput;
144 type O = CardOutput;
145 type Kernel = ubft_card_kernel<TABLE_MASK>;
146}
147
148#[allow(clippy::too_many_lines)]
150#[kernel]
151pub fn ubft_card_kernel<const TABLE_MASK: usize>(
152 _clock_reset: ClockReset,
153 input: CardInput,
154 q: UbftCardQ<TABLE_MASK>,
155) -> (CardOutput, UbftCardD<TABLE_MASK>) {
156 let mut c = q.control;
157 let axi = input.axi;
158 let eng: UbftOutput = q.engine;
159 let probe = q.probe;
160
161 if axi.aw_valid && !q.control.aw_have {
163 c.aw_addr = axi.aw_addr;
164 c.aw_have = true;
165 }
166 if axi.w_valid && !q.control.w_have {
167 c.w_data = axi.w_data;
168 c.w_have = true;
169 }
170 if q.control.b_valid && axi.b_ready {
171 c.b_valid = false;
172 }
173 let mut eng_axi = AxiLiteIn {
174 aw_valid: q.control.fwd_aw,
175 aw_addr: q.control.aw_addr,
176 w_valid: q.control.fwd_w,
177 w_data: q.control.w_data,
178 w_strb: b4(0xf),
179 b_ready: true,
180 ar_valid: q.control.fwd_ar,
181 ar_addr: q.control.ar_addr,
182 r_ready: true,
183 };
184 if q.control.fwd_aw && eng.axi.aw_ready {
185 c.fwd_aw = false;
186 }
187 if q.control.fwd_w && eng.axi.w_ready {
188 c.fwd_w = false;
189 }
190 if q.control.w_busy && eng.axi.b_valid {
191 c.w_busy = false;
192 c.b_valid = true;
193 c.aw_have = false;
194 c.w_have = false;
195 }
196 if q.control.aw_have && q.control.w_have && !q.control.b_valid && !q.control.w_busy {
197 let a = q.control.aw_addr;
198 let v = q.control.w_data;
199 if (a & b12(0x800)) != b12(0) {
200 if a == b12(0x800) {
201 c.args.count = v;
202 }
203 if a == b12(0x804) {
204 c.args.gap = v;
205 }
206 if a == b12(0x808) {
207 c.args.slot = v.resize();
208 }
209 if a == b12(0x80c) {
210 c.args.tamper_every = v;
211 }
212 if a == b12(0x810) {
213 c.args.go = (v & b32(1)) == b32(1);
214 }
215 if a == b12(0x814) {
216 c.announce = (v & b32(1)) == b32(1);
217 }
218 if a == b12(0x818) || a == b12(0x81c) {
219 c.frames_base = set_half_kernel(q.control.frames_base, v, a == b12(0x81c));
220 }
221 c.b_valid = true;
222 c.aw_have = false;
223 c.w_have = false;
224 } else {
225 c.w_busy = true;
226 c.fwd_aw = true;
227 c.fwd_w = true;
228 }
229 }
230
231 if q.control.r_valid && axi.r_ready {
233 c.r_valid = false;
234 }
235 if q.control.fwd_ar && eng.axi.ar_ready {
236 c.fwd_ar = false;
237 }
238 if q.control.r_busy && eng.axi.r_valid {
239 c.r_busy = false;
240 c.r_valid = true;
241 c.r_data = eng.axi.r_data;
242 }
243 let ar_ready = !q.control.r_valid && !q.control.r_busy;
244 if axi.ar_valid && ar_ready {
245 let a = axi.ar_addr;
246 if (a & b12(0x800)) != b12(0) {
247 let mut value = b32(0);
248 if a == b12(0x840) {
249 value = probe.done;
250 }
251 if a == b12(0x844) {
252 value = probe.matched;
253 }
254 if a == b12(0x848) {
255 value = probe.mismatched;
256 }
257 if a == b12(0x84c) {
258 value = probe.first_bad.resize();
259 }
260 if a == b12(0x850) {
261 value = (probe.first_bad >> 32).resize();
262 }
263 if a == b12(0x854) {
264 value = q.writer.frames_written;
265 }
266 if a == b12(0x858) {
267 value = if q.writer.error { b32(1) } else { b32(0) };
268 }
269 c.r_valid = true;
270 c.r_data = value;
271 } else {
272 c.r_busy = true;
273 c.fwd_ar = true;
274 c.ar_addr = a;
275 }
276 }
277 eng_axi.ar_addr = q.control.ar_addr;
279
280 let mut cert_in = Axis512 {
284 valid: false,
285 data: [b8(0); 64],
286 last: false,
287 };
288 let mut cert_out_ready = true;
289 if q.control.announce {
290 cert_out_ready = false;
291 if q.control.ann_phase == b2(0) {
292 if eng.cert_out.valid {
293 cert_in.valid = true;
294 cert_in.data[0] = q.control.args.slot.resize();
295 if eng.cert_in_ready {
296 c.ann_phase = b2(1);
297 }
298 }
299 } else {
300 cert_in = eng.cert_out;
301 cert_out_ready = eng.cert_in_ready;
302 if eng.cert_out.valid && eng.cert_in_ready {
303 c.ann_phase = if eng.cert_out.last { b2(0) } else { b2(2) };
304 }
305 }
306 }
307
308 let d = UbftCardD::<TABLE_MASK> {
309 control: c,
310 engine: UbftInput {
311 cfg: CfgWrite {
312 valid: false,
313 addr: b12(0),
314 data: b32(0),
315 },
316 axi: eng_axi,
317 sign: probe.sign,
318 frame_ready: probe.frame_ready,
319 verify: probe.verify,
320 verdict_ready: probe.verdict_ready,
321 cert_in,
322 cert_out_ready,
323 },
324 probe: ProbeIn {
325 args: q.control.args,
326 sign_ready: eng.sign_ready,
327 frame: eng.frame,
328 verify_ready: eng.verify_ready,
329 verdict: eng.verdict,
330 writer_ready: q.writer.beat_ready,
331 },
332 writer: WriterInput {
333 base: q.control.frames_base,
334 beat: probe.beat,
335 memory: input.frames,
336 },
337 };
338 (
339 CardOutput {
340 axi: AxiLiteOut {
341 aw_ready: !q.control.aw_have,
342 w_ready: !q.control.w_have,
343 b_valid: q.control.b_valid,
344 b_resp: b2(0),
345 ar_ready,
346 r_valid: q.control.r_valid,
347 r_data: q.control.r_data,
348 r_resp: b2(0),
349 interrupt: eng.axi.interrupt,
350 },
351 frames: q.writer.memory,
352 },
353 d,
354 )
355}