1use crate::VERIFY_UNITS;
60use crate::axi4::{AxiLiteIn, AxiLiteOut, ReadRequest, ReadResponse, WriteRequest, WriteResponse};
61use rhdl::prelude::*;
62
63pub const MAGIC: b32 = b32(0x3156_5344);
65pub const ABI_VERSION: b32 = b32(0x0001_0001);
67
68pub const ARG_RECORDS: usize = 0x010;
70pub const ARG_VERDICTS: usize = 0x018;
72pub const ARG_COUNT: usize = 0x090;
74pub const ARG_KEY: usize = 0x098;
76pub const REG_MAGIC: usize = 0x200;
78pub const REG_ABI: usize = 0x204;
80pub const REG_SHAPE: usize = 0x208;
82pub const REG_FAULT: usize = 0x20c;
84pub const REG_TICKS: usize = 0x210;
86pub const REG_START_TICK: usize = 0x218;
88pub const REG_DONE_TICK: usize = 0x220;
90pub const REG_KEY_TICK: usize = 0x228;
92pub const REG_VALID: usize = 0x230;
94pub const REG_CERT_CHECKS: usize = 0x234;
96pub const REG_CERT_FAILS: usize = 0x238;
98pub const REG_RETIRED: usize = 0x240;
100
101#[derive(Clone, Copy, Debug, PartialEq, Digital)]
103pub struct VerifyEngineInput {
104 pub axi: AxiLiteIn,
106 pub records: [ReadResponse; VERIFY_UNITS],
108 pub verdicts: [WriteResponse; VERIFY_UNITS],
110}
111
112#[derive(Clone, Copy, Debug, PartialEq, Digital)]
114pub struct VerifyEngineOutput {
115 pub axi: AxiLiteOut,
117 pub records: [ReadRequest; VERIFY_UNITS],
119 pub verdicts: [WriteRequest; VERIFY_UNITS],
121}
122
123use crate::engine::set_half_kernel;
126use crate::verify::certs::CertResult;
127use crate::verify::chains::{CONTEXTS, LANES};
128use crate::relay::{Delay, PipeIn, RelayPipe, ToggleLink};
129use crate::verify::certs::CertRequest;
130use crate::verify::unit::{UnitInput, VerifyUnit};
131use rhdl::core::ReplicatedSynchronous;
132use rhdl_fpga::core::dff::DFF;
133
134#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
136pub struct EdStatus {
137 pub ready: bool,
139 pub result_valid: bool,
141 pub result_ok: bool,
143 pub result_tag: b16,
145 pub load_key_ready: bool,
147 pub key_state: b2,
149 pub internal_error: bool,
151}
152
153#[derive(Clone, Copy, Debug, PartialEq, Digital)]
155pub struct EdCommand {
156 pub valid: bool,
158 pub message: [b64; 8],
160 pub signature: [b64; 8],
162 pub public_key: [b64; 4],
164 pub tag: b16,
166 pub load_key_valid: bool,
168}
169
170#[derive(Clone, Copy, Debug, PartialEq, Digital)]
172pub struct ClusterInput {
173 pub kernel: VerifyEngineInput,
175 pub ed: EdStatus,
177}
178
179#[derive(Clone, Copy, Debug, PartialEq, Digital)]
181pub struct ClusterOutput {
182 pub kernel: VerifyEngineOutput,
184 pub ed: EdCommand,
186}
187
188#[derive(Clone, Copy, Debug, PartialEq, Digital)]
190pub struct VerifyArgs {
191 pub records: [b64; VERIFY_UNITS],
193 pub verdicts: [b64; VERIFY_UNITS],
195 pub count: b32,
197 pub key: [b32; 8],
199}
200
201#[derive(Clone, Copy, Debug, PartialEq, Digital)]
203#[doc(hidden)]
204pub struct ClusterControl {
205 args: VerifyArgs,
207 running: bool,
209 done: bool,
211 done_unread: bool,
213 gie: bool,
215 ier: bool,
217 isr: bool,
219 ticks: b64,
221 start_tick: b64,
223 done_tick: b64,
225 key_tick: b64,
227 ticks_hi: b32,
229 key_sent: bool,
231 key_settled: bool,
233 next_unit: b3,
235 aw_addr: b12,
237 aw_have: bool,
239 w_data: b32,
241 w_have: bool,
243 b_valid: bool,
245 r_valid: bool,
247 r_data: b32,
249 ed_valid: bool,
251 ed_request: EdHeld,
253}
254
255#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
260#[doc(hidden)]
261pub struct EdHeld {
262 message: [b64; 8],
263 signature: [b64; 8],
264 public_key: [b64; 4],
265 tag: b16,
266}
267
268impl Default for ClusterControl {
269 fn default() -> Self {
271 Self {
272 args: VerifyArgs {
273 records: [b64(0); VERIFY_UNITS],
274 verdicts: [b64(0); VERIFY_UNITS],
275 count: b32(0),
276 key: [b32(0); 8],
277 },
278 running: false,
279 done: false,
280 done_unread: false,
281 gie: false,
282 ier: false,
283 isr: false,
284 ticks: b64(0),
285 start_tick: b64(0),
286 done_tick: b64(0),
287 key_tick: b64(0),
288 ticks_hi: b32(0),
289 key_sent: false,
290 key_settled: false,
291 next_unit: b3(0),
292 aw_addr: b12(0),
293 aw_have: false,
294 w_data: b32(0),
295 w_have: false,
296 b_valid: false,
297 r_valid: false,
298 r_data: b32(0),
299 ed_valid: false,
300 ed_request: EdHeld::default(),
301 }
302 }
303}
304
305#[derive(Clone, Copy, Debug, PartialEq, Digital)]
307pub struct ArItem {
308 pub araddr: b64,
310 pub arlen: b8,
312}
313
314#[derive(Clone, Copy, Debug, PartialEq, Digital)]
316pub struct RItem {
317 pub rvalid: bool,
319 pub rdata: [b8; 64],
321 pub rresp: b2,
323 pub rlast: bool,
325}
326
327#[derive(Clone, Copy, Debug, PartialEq, Digital)]
329pub struct AwItem {
330 pub awaddr: b64,
332 pub awlen: b8,
334}
335
336#[derive(Clone, Copy, Debug, PartialEq, Digital)]
338pub struct WItem {
339 pub wdata: [b8; 64],
341 pub wlast: bool,
343}
344
345#[derive(Clone, Copy, Debug, PartialEq, Digital)]
347pub struct BItem {
348 pub bvalid: bool,
350 pub bresp: b2,
352}
353
354#[derive(Clone, Copy, Debug, PartialEq, Digital)]
356pub struct UnitControl {
357 pub run: bool,
359 pub records_base: b64,
361 pub verdicts_base: b64,
363 pub count: b32,
365}
366
367#[derive(Clone, Copy, Debug, PartialEq, Digital)]
369pub struct UnitStatus {
370 pub retired: b32,
372 pub valid: b32,
374 pub cert_checks: b32,
376 pub cert_fails: b32,
378 pub done: bool,
380 pub error: b2,
382}
383
384#[derive(Clone, Debug, Synchronous, SynchronousDQ)]
396pub struct VerifyCluster<const TABLE_MASK: usize> {
397 control: DFF<ClusterControl>,
399 units: ReplicatedSynchronous<VerifyUnit<TABLE_MASK>, VERIFY_UNITS>,
401 ar: [RelayPipe<ArItem>; VERIFY_UNITS],
403 r: [Delay<RItem>; VERIFY_UNITS],
405 aw: [RelayPipe<AwItem>; VERIFY_UNITS],
407 w: [RelayPipe<WItem>; VERIFY_UNITS],
409 b: [Delay<BItem>; VERIFY_UNITS],
411 to_unit: [Delay<UnitControl>; VERIFY_UNITS],
413 requests: [ToggleLink<CertRequest>; VERIFY_UNITS],
415 results: [Delay<CertResult>; VERIFY_UNITS],
417 status: [Delay<UnitStatus>; VERIFY_UNITS],
419}
420
421impl<const TABLE_MASK: usize> Default for VerifyCluster<TABLE_MASK> {
422 fn default() -> Self {
424 Self {
425 control: DFF::new(ClusterControl::default()),
426 units: ReplicatedSynchronous::new(VerifyUnit::default()),
427 ar: core::array::from_fn(|_| RelayPipe::default()),
428 r: core::array::from_fn(|_| Delay::default()),
429 aw: core::array::from_fn(|_| RelayPipe::default()),
430 w: core::array::from_fn(|_| RelayPipe::default()),
431 b: core::array::from_fn(|_| Delay::default()),
432 to_unit: core::array::from_fn(|_| Delay::default()),
433 requests: core::array::from_fn(|_| ToggleLink::default()),
434 results: core::array::from_fn(|_| Delay::default()),
435 status: core::array::from_fn(|_| Delay::default()),
436 }
437 }
438}
439
440impl<const TABLE_MASK: usize> SynchronousIO for VerifyCluster<TABLE_MASK> {
441 type I = ClusterInput;
442 type O = ClusterOutput;
443 type Kernel = verify_cluster_kernel<TABLE_MASK>;
444}
445
446#[allow(clippy::needless_range_loop)]
448#[kernel]
449pub fn words64_kernel(bytes: [b8; 64]) -> [b64; 8] {
450 let mut words = [b64(0); 8];
451 for w in 0..8 {
452 words[w] = bytes[8 * w].resize::<64>()
453 | (bytes[8 * w + 1].resize::<64>() << 8)
454 | (bytes[8 * w + 2].resize::<64>() << 16)
455 | (bytes[8 * w + 3].resize::<64>() << 24)
456 | (bytes[8 * w + 4].resize::<64>() << 32)
457 | (bytes[8 * w + 5].resize::<64>() << 40)
458 | (bytes[8 * w + 6].resize::<64>() << 48)
459 | (bytes[8 * w + 7].resize::<64>() << 56);
460 }
461 words
462}
463
464const SHAPE: usize = VERIFY_UNITS | (LANES << 8) | ((CONTEXTS.trailing_zeros() as usize) << 12);
466
467#[allow(clippy::needless_range_loop, clippy::too_many_lines)]
469#[kernel]
470pub fn verify_cluster_kernel<const TABLE_MASK: usize>(
471 clock_reset: ClockReset,
472 input: ClusterInput,
473 q: VerifyClusterQ<TABLE_MASK>,
474) -> (ClusterOutput, VerifyClusterD<TABLE_MASK>) {
475 let resetting = clock_reset.reset.any();
476 let mut c = q.control;
477 let args = q.control.args;
478 c.ticks = q.control.ticks + b64(1);
479 let ed = input.ed;
480
481 let mut all_done = true;
483 let mut read_error = false;
484 let mut write_error = false;
485 let mut valid = b32(0);
486 let mut checks = b32(0);
487 let mut fails = b32(0);
488 for u in 0..VERIFY_UNITS {
489 let s = q.status[u];
490 all_done = all_done && s.done;
491 read_error = read_error || (s.error & b2(1)) != b2(0);
492 write_error = write_error || (s.error & b2(2)) != b2(0);
493 valid = valid + s.valid;
494 checks = checks + s.cert_checks;
495 fails = fails + s.cert_fails;
496 }
497 let key_bad = q.control.key_settled && ed.key_state == b2(3);
498 let fault_bits: b32 = (if read_error { b32(1) } else { b32(0) })
499 | (if write_error { b32(2) } else { b32(0) })
500 | (if ed.internal_error { b32(4) } else { b32(0) })
501 | (if key_bad { b32(8) } else { b32(0) });
502 let settled_start = q.control.ticks - q.control.start_tick > b64(16);
505 if q.control.running && all_done && q.control.key_settled && settled_start {
506 c.running = false;
507 c.done = true;
508 c.done_unread = true;
509 c.isr = true;
510 c.done_tick = q.control.ticks;
511 }
512
513 let mut key_words = [b64(0); 4];
515 for w in 0..4 {
516 key_words[w] = args.key[2 * w].resize::<64>() | (args.key[2 * w + 1].resize::<64>() << 32);
517 }
518 let load_key = q.control.running && !q.control.key_sent && ed.load_key_ready && !resetting;
519 if load_key {
520 c.key_sent = true;
521 }
522 if q.control.key_sent && !q.control.key_settled && (ed.key_state == b2(2) || ed.key_state == b2(3)) {
523 c.key_settled = true;
524 c.key_tick = q.control.ticks;
525 }
526
527 let mut pick_found = false;
531 let mut pick = b3(0);
532 for i in 0..VERIFY_UNITS {
533 let u = VERIFY_UNITS - 1 - i;
534 if q.requests[u].valid && b3(u as u128) >= q.control.next_unit {
535 pick_found = true;
536 pick = b3(u as u128);
537 }
538 }
539 if !pick_found {
540 for i in 0..VERIFY_UNITS {
541 let u = VERIFY_UNITS - 1 - i;
542 if q.requests[u].valid {
543 pick_found = true;
544 pick = b3(u as u128);
545 }
546 }
547 }
548 if q.control.ed_valid && ed.ready {
552 c.ed_valid = false;
553 }
554 let issue = pick_found && !q.control.ed_valid && q.control.key_settled && !resetting;
555 let mut request = q.requests[0].data;
556 for u in 0..VERIFY_UNITS {
557 if pick == b3(u as u128) {
558 request = q.requests[u].data;
559 }
560 }
561 let mut held = q.control.ed_request;
562 held.public_key = key_words;
563 if issue {
564 c.next_unit = if pick == b3((VERIFY_UNITS - 1) as u128) { b3(0) } else { pick + b3(1) };
565 c.ed_valid = true;
566 held.message = words64_kernel(request.commitment);
567 held.signature = words64_kernel(request.signature);
568 held.tag = (pick.resize::<16>() << 6) | request.entry.resize::<16>();
569 }
570 c.ed_request = held;
571
572 let axi = input.kernel.axi;
574 if axi.aw_valid && !q.control.aw_have {
575 c.aw_addr = axi.aw_addr;
576 c.aw_have = true;
577 }
578 if axi.w_valid && !q.control.w_have {
579 c.w_data = axi.w_data;
580 c.w_have = true;
581 }
582 if q.control.b_valid && axi.b_ready {
583 c.b_valid = false;
584 }
585 if q.control.aw_have && q.control.w_have && !q.control.b_valid {
586 let a = q.control.aw_addr;
587 let v = q.control.w_data;
588 c.aw_have = false;
589 c.w_have = false;
590 c.b_valid = true;
591 if a == b12(0x000) && (v & b32(1)) == b32(1) && !q.control.running && !q.control.done {
592 c.running = true;
593 c.start_tick = q.control.ticks;
594 }
595 if a == b12(0x004) {
596 c.gie = (v & b32(1)) == b32(1);
597 }
598 if a == b12(0x008) {
599 c.ier = (v & b32(1)) == b32(1);
600 }
601 if a == b12(0x00c) && (v & b32(1)) == b32(1) {
602 c.isr = !q.control.isr;
603 }
604 if !q.control.running && !q.control.done {
605 for u in 0..VERIFY_UNITS {
606 if a == b12((ARG_RECORDS + 16 * u) as u128) || a == b12((ARG_RECORDS + 16 * u + 4) as u128) {
607 c.args.records[u] = set_half_kernel(args.records[u], v, a == b12((ARG_RECORDS + 16 * u + 4) as u128));
608 }
609 if a == b12((ARG_VERDICTS + 16 * u) as u128) || a == b12((ARG_VERDICTS + 16 * u + 4) as u128) {
610 c.args.verdicts[u] = set_half_kernel(args.verdicts[u], v, a == b12((ARG_VERDICTS + 16 * u + 4) as u128));
611 }
612 }
613 if a == b12(ARG_COUNT as u128) {
614 c.args.count = v;
615 }
616 for w in 0..8 {
617 if a == b12((ARG_KEY + 4 * w) as u128) {
618 c.args.key[w] = v;
619 }
620 }
621 }
622 }
623
624 if q.control.r_valid && axi.r_ready {
626 c.r_valid = false;
627 }
628 let ar_ready = !q.control.r_valid;
629 if axi.ar_valid && ar_ready {
630 let a = axi.ar_addr;
631 let mut value = b32(0);
632 if a == b12(0x000) {
633 value = (if q.control.running { b32(1) } else { b32(0) })
634 | (if q.control.done_unread { b32(2) } else { b32(0) })
635 | (if !q.control.running { b32(4) } else { b32(0) })
636 | (if q.control.done_unread { b32(8) } else { b32(0) });
637 c.done_unread = false;
638 }
639 if a == b12(0x004) {
640 value = if q.control.gie { b32(1) } else { b32(0) };
641 }
642 if a == b12(0x008) {
643 value = if q.control.ier { b32(1) } else { b32(0) };
644 }
645 if a == b12(0x00c) {
646 value = if q.control.isr { b32(1) } else { b32(0) };
647 }
648 if a == b12(REG_MAGIC as u128) {
649 value = MAGIC;
650 }
651 if a == b12(REG_ABI as u128) {
652 value = ABI_VERSION;
653 }
654 if a == b12(REG_SHAPE as u128) {
655 value = b32((SHAPE | (TABLE_MASK << 16)) as u128);
656 }
657 if a == b12(REG_FAULT as u128) {
658 value = fault_bits;
659 }
660 if a == b12(REG_TICKS as u128) {
661 value = q.control.ticks.resize();
662 c.ticks_hi = (q.control.ticks >> 32).resize();
663 }
664 if a == b12((REG_TICKS + 4) as u128) {
665 value = q.control.ticks_hi;
666 }
667 if a == b12(REG_START_TICK as u128) {
668 value = q.control.start_tick.resize();
669 }
670 if a == b12((REG_START_TICK + 4) as u128) {
671 value = (q.control.start_tick >> 32).resize();
672 }
673 if a == b12(REG_DONE_TICK as u128) {
674 value = q.control.done_tick.resize();
675 }
676 if a == b12((REG_DONE_TICK + 4) as u128) {
677 value = (q.control.done_tick >> 32).resize();
678 }
679 if a == b12(REG_KEY_TICK as u128) {
680 value = q.control.key_tick.resize();
681 }
682 if a == b12((REG_KEY_TICK + 4) as u128) {
683 value = (q.control.key_tick >> 32).resize();
684 }
685 if a == b12(REG_VALID as u128) {
686 value = valid;
687 }
688 if a == b12(REG_CERT_CHECKS as u128) {
689 value = checks;
690 }
691 if a == b12(REG_CERT_FAILS as u128) {
692 value = fails;
693 }
694 for u in 0..VERIFY_UNITS {
695 if a == b12((REG_RETIRED + 4 * u) as u128) {
696 value = q.status[u].retired;
697 }
698 }
699 c.r_valid = true;
700 c.r_data = value;
701 }
702
703 let result_unit: b3 = (ed.result_tag >> 6).resize();
705 let mut units = [UnitInput {
706 run: false,
707 records_base: b64(0),
708 verdicts_base: b64(0),
709 count: b32(0),
710 records: input.kernel.records[0],
711 verdicts: input.kernel.verdicts[0],
712 cert_taken: false,
713 cert_result: CertResult::default(),
714 }; VERIFY_UNITS];
715 let mut ar = [PipeIn::<ArItem> {
716 data: ArItem { araddr: b64(0), arlen: b8(0) },
717 valid: false,
718 taken: false,
719 }; VERIFY_UNITS];
720 let mut r = [RItem {
721 rvalid: false,
722 rdata: [b8(0); 64],
723 rresp: b2(0),
724 rlast: false,
725 }; VERIFY_UNITS];
726 let mut aw = [PipeIn::<AwItem> {
727 data: AwItem { awaddr: b64(0), awlen: b8(0) },
728 valid: false,
729 taken: false,
730 }; VERIFY_UNITS];
731 let mut w = [PipeIn::<WItem> {
732 data: WItem { wdata: [b8(0); 64], wlast: false },
733 valid: false,
734 taken: false,
735 }; VERIFY_UNITS];
736 let mut b = [BItem { bvalid: false, bresp: b2(0) }; VERIFY_UNITS];
737 let mut to_unit = [UnitControl {
738 run: q.control.running,
739 records_base: args.records[0],
740 verdicts_base: args.verdicts[0],
741 count: args.count,
742 }; VERIFY_UNITS];
743 let mut requests = [PipeIn::<CertRequest> {
744 data: q.units[0].cert_request,
745 valid: false,
746 taken: false,
747 }; VERIFY_UNITS];
748 let mut results = [CertResult::default(); VERIFY_UNITS];
749 let mut status = [UnitStatus {
750 retired: b32(0),
751 valid: b32(0),
752 cert_checks: b32(0),
753 cert_fails: b32(0),
754 done: false,
755 error: b2(0),
756 }; VERIFY_UNITS];
757 let mut records = [input.kernel.records[0]; VERIFY_UNITS];
758 let mut verdicts = [input.kernel.verdicts[0]; VERIFY_UNITS];
759 let mut records_out = [q.units[0].records; VERIFY_UNITS];
760 let mut verdicts_out = [q.units[0].verdicts; VERIFY_UNITS];
761 for u in 0..VERIFY_UNITS {
762 let unit = q.units[u];
763 let port_r = input.kernel.records[u];
764 let port_w = input.kernel.verdicts[u];
765 records[u] = ReadResponse {
767 arready: q.ar[u].ready,
768 rvalid: q.r[u].rvalid,
769 rdata: q.r[u].rdata,
770 rresp: q.r[u].rresp,
771 rlast: q.r[u].rlast,
772 };
773 verdicts[u] = WriteResponse {
774 awready: q.aw[u].ready,
775 wready: q.w[u].ready,
776 bvalid: q.b[u].bvalid,
777 bresp: q.b[u].bresp,
778 };
779 let control = q.to_unit[u];
780 units[u] = UnitInput {
781 run: control.run,
782 records_base: control.records_base,
783 verdicts_base: control.verdicts_base,
784 count: control.count,
785 records: records[u],
786 verdicts: verdicts[u],
787 cert_taken: unit.cert_request.valid && q.requests[u].ready,
788 cert_result: q.results[u],
789 };
790 ar[u] = PipeIn::<ArItem> {
792 data: ArItem {
793 araddr: unit.records.araddr,
794 arlen: unit.records.arlen,
795 },
796 valid: unit.records.arvalid,
797 taken: q.ar[u].valid && port_r.arready,
798 };
799 aw[u] = PipeIn::<AwItem> {
800 data: AwItem {
801 awaddr: unit.verdicts.awaddr,
802 awlen: unit.verdicts.awlen,
803 },
804 valid: unit.verdicts.awvalid,
805 taken: q.aw[u].valid && port_w.awready,
806 };
807 w[u] = PipeIn::<WItem> {
808 data: WItem {
809 wdata: unit.verdicts.wdata,
810 wlast: unit.verdicts.wlast,
811 },
812 valid: unit.verdicts.wvalid,
813 taken: q.w[u].valid && port_w.wready,
814 };
815 records_out[u] = ReadRequest {
816 arvalid: q.ar[u].valid,
817 araddr: q.ar[u].data.araddr,
818 arlen: q.ar[u].data.arlen,
819 rready: true,
820 };
821 verdicts_out[u] = WriteRequest {
822 awvalid: q.aw[u].valid,
823 awaddr: q.aw[u].data.awaddr,
824 awlen: q.aw[u].data.awlen,
825 wvalid: q.w[u].valid,
826 wdata: q.w[u].data.wdata,
827 wlast: q.w[u].data.wlast,
828 bready: true,
829 };
830 r[u] = RItem {
832 rvalid: port_r.rvalid,
833 rdata: port_r.rdata,
834 rresp: port_r.rresp,
835 rlast: port_r.rlast,
836 };
837 b[u] = BItem {
838 bvalid: port_w.bvalid,
839 bresp: port_w.bresp,
840 };
841 to_unit[u] = UnitControl {
843 run: q.control.running,
844 records_base: args.records[u],
845 verdicts_base: args.verdicts[u],
846 count: args.count,
847 };
848 requests[u] = PipeIn::<CertRequest> {
849 data: unit.cert_request,
850 valid: unit.cert_request.valid,
851 taken: issue && pick == b3(u as u128),
852 };
853 results[u] = CertResult {
854 valid: ed.result_valid && result_unit == b3(u as u128),
855 entry: ed.result_tag.resize(),
856 ok: ed.result_ok,
857 };
858 status[u] = UnitStatus {
859 retired: unit.retired,
860 valid: unit.valid,
861 cert_checks: unit.cert_checks,
862 cert_fails: unit.cert_fails,
863 done: unit.done,
864 error: unit.error,
865 };
866 }
867 let d = VerifyClusterD::<TABLE_MASK> {
868 control: c,
869 units,
870 ar,
871 r,
872 aw,
873 w,
874 b,
875 to_unit,
876 requests,
877 results,
878 status,
879 };
880 (
881 ClusterOutput {
882 kernel: VerifyEngineOutput {
883 axi: AxiLiteOut {
884 aw_ready: !q.control.aw_have,
885 w_ready: !q.control.w_have,
886 b_valid: q.control.b_valid,
887 b_resp: b2(0),
888 ar_ready,
889 r_valid: q.control.r_valid,
890 r_data: q.control.r_data,
891 r_resp: b2(0),
892 interrupt: q.control.gie && q.control.ier && q.control.isr,
893 },
894 records: records_out,
895 verdicts: verdicts_out,
896 },
897 ed: EdCommand {
898 valid: q.control.ed_valid,
899 message: q.control.ed_request.message,
900 signature: q.control.ed_request.signature,
901 public_key: q.control.ed_request.public_key,
902 tag: q.control.ed_request.tag,
903 load_key_valid: load_key,
904 },
905 },
906 d,
907 )
908}
909
910const _: () = assert!(VERIFY_UNITS <= 8, "unit numbers are 3 bits");
911
912use rhdl_ed25519_live::sha_ring::{ShaDone, ShaRingOut};
915use rhdl_ed25519_live::verify_core::{KnownKeyVerifyCore, VerifyIn};
916use rhdl_ed25519_live::wire::{ScalarWords, VerifyRequest, Words512};
917
918pub type CertCore = KnownKeyVerifyCore<1, 1, 1, 0>;
922
923#[derive(Clone, Debug, Synchronous, SynchronousDQ)]
925pub struct VerifyEngine<const TABLE_MASK: usize> {
926 cluster: VerifyCluster<TABLE_MASK>,
928 ed: CertCore,
930}
931
932impl<const TABLE_MASK: usize> Default for VerifyEngine<TABLE_MASK> {
933 fn default() -> Self {
935 Self {
936 cluster: VerifyCluster::default(),
937 ed: CertCore::default(),
938 }
939 }
940}
941
942impl<const TABLE_MASK: usize> SynchronousIO for VerifyEngine<TABLE_MASK> {
943 type I = VerifyEngineInput;
944 type O = VerifyEngineOutput;
945 type Kernel = verify_engine_kernel<TABLE_MASK>;
946}
947
948#[kernel]
950pub fn verify_engine_kernel<const TABLE_MASK: usize>(
951 _clock_reset: ClockReset,
952 input: VerifyEngineInput,
953 q: VerifyEngineQ<TABLE_MASK>,
954) -> (VerifyEngineOutput, VerifyEngineD<TABLE_MASK>) {
955 let ed = q.ed;
956 let command = q.cluster.ed;
957 let d = VerifyEngineD::<TABLE_MASK> {
958 cluster: ClusterInput {
959 kernel: input,
960 ed: EdStatus {
961 ready: ed.ready,
962 result_valid: ed.valid,
963 result_ok: ed.ok,
964 result_tag: ed.tag,
965 load_key_ready: ed.load_key_ready,
966 key_state: ed.key_state[0],
967 internal_error: ed.internal_error,
968 },
969 },
970 ed: VerifyIn {
971 valid: command.valid,
972 request: VerifyRequest {
973 message: Words512 { words: command.message },
974 public_key: ScalarWords { words: command.public_key },
975 signature: Words512 { words: command.signature },
976 tag: command.tag,
977 },
978 load_key_valid: command.load_key_valid,
979 load_key: ScalarWords { words: command.public_key },
980 load_slot: b3(0).resize(),
981 sha_ext: ShaRingOut {
982 ready: false,
983 done: ShaDone {
984 valid: false,
985 tag: b16(0),
986 state: [b64(0); 8],
987 },
988 },
989 },
990 };
991 (q.cluster.kernel, d)
992}