1use rhdl::prelude::*;
85use rhdl_fpga::core::{
86 dff::DFF,
87 ram::synchronous::{In as SyncBramIn, SyncBRAM, Write as SyncBramWrite},
88};
89use rhdl_primitives::NoResetDff;
90use sha256_rhdl::lane::{CompressionInput, CompressionOutput};
91
92use crate::{
93 blocks::{
94 ChainBlockInput, EndpointPairInput, HashBytes, HashWords, PrfBlockInput, SecretDataInput,
95 chain_block_kernel, endpoint_final_block_kernel, endpoint_pair_block_kernel,
96 hash_words_to_bytes_kernel, initial_state_words_kernel, prf_block_kernel,
97 private_seed_block_kernel, secret_data_block_kernel, secret_padding_block_kernel,
98 },
99 digits::{MessageBytes, MessageDigitArray, message_digits_kernel},
100 tag::{TagFields, decode_tag_kernel, encode_tag_kernel, tag_is_well_formed_kernel},
101 tasks::TOTAL_TASKS,
102};
103
104pub const ENGINE_SEGMENTS: usize = 67;
106pub const SEGMENTS_PER_GROUP: usize = 8;
108pub const SEGMENT_GROUPS: usize = 9;
110pub const PUBLIC_KEY_FOCUS_BLOCKS: usize = 8;
112pub const PRIVATE_KEY_CONSUMERS: usize = 68;
114pub const STATE_BANK_ADDRESS_BITS: usize = 6;
116pub const STATE_BANK_DEPTH: usize = 1 << STATE_BANK_ADDRESS_BITS;
118pub const MASK_ADDRESS_BITS: usize = 4;
120pub const MASK_DEPTH: usize = 1 << MASK_ADDRESS_BITS;
122pub const SIGNATURE_ADDRESS_BITS: usize = 6;
124pub const SIGNATURE_DEPTH: usize = 1 << SIGNATURE_ADDRESS_BITS;
126
127pub const STATE_STORAGE_BITS: usize = 2 * STATE_BANK_DEPTH * 8 * 32;
129pub const MASK_STORAGE_BITS: usize = MASK_DEPTH * 8 * 32;
131pub const SIGNATURE_STORAGE_BITS: usize = 2 * SIGNATURE_DEPTH * 8 * 32;
133pub const CONTEXT_LOGICAL_RAM_BITS: usize =
135 STATE_STORAGE_BITS + MASK_STORAGE_BITS + SIGNATURE_STORAGE_BITS;
136
137pub const SEGMENT_STAGE_PRF: u8 = 0;
139pub const SEGMENT_STAGE_SECRET_DATA: u8 = 1;
141pub const SEGMENT_STAGE_SECRET_PADDING: u8 = 2;
143pub const SEGMENT_STAGE_CHAIN_FIRST: u8 = 3;
145pub const SEGMENT_STAGE_CHAIN_LAST: u8 = 17;
147pub const SEGMENT_STAGE_ENDPOINT: u8 = 18;
149
150pub type SegmentGroups = [b8; SEGMENT_GROUPS];
152pub type SegmentStages = [b5; ENGINE_SEGMENTS];
154
155const _: () = {
156 assert!(SEGMENT_GROUPS * SEGMENTS_PER_GROUP >= ENGINE_SEGMENTS);
157 assert!(STATE_BANK_DEPTH == 64);
158 assert!(MASK_DEPTH == 16);
159 assert!(SIGNATURE_DEPTH == 64);
160 assert!(STATE_STORAGE_BITS == 32_768);
161 assert!(MASK_STORAGE_BITS == 4_096);
162 assert!(SIGNATURE_STORAGE_BITS == 32_768);
163 assert!(CONTEXT_LOGICAL_RAM_BITS == 69_632);
164 assert!(TOTAL_TASKS == 1_258);
165 assert!(PRIVATE_KEY_CONSUMERS < 128);
166};
167
168#[allow(clippy::struct_excessive_bools)] #[derive(Clone, Copy, Debug, Digital, Eq, PartialEq)]
171pub struct EngineControl {
172 pub active: bool,
174 pub credit_reserved: bool,
176 pub result_valid: bool,
178 pub fault: bool,
180 pub seed_ready: bool,
182 pub seed_inflight: bool,
184 pub public_seed_ready: bool,
186 pub public_seed_inflight: bool,
188 pub public_seed_done: bool,
190 pub private_key_consumers_remaining: b7,
192 pub mask_ready: b16,
194 pub mask_inflight: b16,
196 pub mask_done: b16,
198 pub segment_ready: SegmentGroups,
200 pub segment_inflight: SegmentGroups,
202 pub segment_stage: SegmentStages,
204 pub endpoint_done: SegmentGroups,
206 pub segment_group_cursor: b4,
208 pub public_key_block: b6,
210 pub public_key_inflight: bool,
212 pub public_key_state_ready: bool,
214 pub total_issued: b11,
216 pub total_retired: b11,
218 pub prefetch_pending: bool,
220 pub prefetch_tag: b32,
222 pub request_valid: bool,
224 pub context: b4,
226 pub generation: b8,
228 pub result_read_pending: bool,
230 pub result_read_pair: b6,
232}
233
234impl Default for EngineControl {
235 fn default() -> Self {
236 Self {
237 active: false,
238 credit_reserved: false,
239 result_valid: false,
240 fault: false,
241 seed_ready: false,
242 seed_inflight: false,
243 public_seed_ready: false,
244 public_seed_inflight: false,
245 public_seed_done: false,
246 private_key_consumers_remaining: b7(0),
247 mask_ready: b16(0),
248 mask_inflight: b16(0),
249 mask_done: b16(0),
250 segment_ready: [b8(0); SEGMENT_GROUPS],
251 segment_inflight: [b8(0); SEGMENT_GROUPS],
252 segment_stage: [b5(0); ENGINE_SEGMENTS],
253 endpoint_done: [b8(0); SEGMENT_GROUPS],
254 segment_group_cursor: b4(0),
255 public_key_block: b6(0),
256 public_key_inflight: false,
257 public_key_state_ready: false,
258 total_issued: b11(0),
259 total_retired: b11(0),
260 prefetch_pending: false,
261 prefetch_tag: b32(0),
262 request_valid: false,
263 context: b4(0),
264 generation: b8(0),
265 result_read_pending: false,
266 result_read_pair: b6(0),
267 }
268 }
269}
270
271#[allow(clippy::struct_excessive_bools)] #[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
274pub struct ContextEngineInput {
275 pub start_valid: bool,
277 pub private_seed: HashBytes,
279 pub message: MessageBytes,
281 pub context: b4,
283 pub context_enabled: bool,
285 pub generation: b8,
287 pub output_credit_available: bool,
289 pub request_ready: bool,
291 pub response: CompressionOutput,
293 pub result_taken: bool,
295 pub result_read_enable: bool,
297 pub result_read_pair: b6,
299}
300
301#[allow(clippy::struct_excessive_bools)] #[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
304pub struct ContextEngineOutput {
305 pub start_ready: bool,
307 pub start_rejected: bool,
309 pub active: bool,
311 pub output_credit_reserved: bool,
313 pub request: CompressionInput,
315 pub response_ready: bool,
317 pub response_rejected: bool,
319 pub fault: bool,
321 pub done: bool,
324 pub output_credit_release: bool,
326 pub result_valid: bool,
328 pub public_seed: HashBytes,
330 pub public_key_hash: HashBytes,
332 pub result_read_valid: bool,
334 pub result_read_pair: b6,
336 pub signature_first: HashBytes,
338 pub signature_second: HashBytes,
340 pub result_read_second_valid: bool,
342 pub endpoint_first: HashBytes,
344 pub endpoint_second: HashBytes,
346 pub total_issued: b11,
348 pub total_retired: b11,
350 pub public_key_block: b6,
352 pub private_key_consumers_remaining: b7,
354}
355
356#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
358pub struct SegmentSelection {
359 pub valid: bool,
361 pub segment: b7,
363 pub next_group: b4,
365}
366
367#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
369pub struct PrepareRequestInput {
370 pub fields: TagFields,
372 pub private_seed: HashBytes,
374 pub private_key: HashWords,
376 pub public_seed: HashWords,
378 pub public_key_state: HashWords,
380 pub state_even: HashWords,
382 pub state_odd: HashWords,
384 pub mask: HashWords,
386}
387
388#[derive(Clone, Copy, Debug, Digital, PartialEq)]
390pub struct SignatureBanksInput {
391 pub read_addr: b6,
393 pub even_write: SyncBramWrite<HashWords, SIGNATURE_ADDRESS_BITS>,
395 pub odd_write: SyncBramWrite<HashWords, SIGNATURE_ADDRESS_BITS>,
397}
398
399#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
401pub struct SignatureBanksOutput {
402 pub even: HashWords,
404 pub odd: HashWords,
406}
407
408#[derive(Clone, Debug, Default, Synchronous, SynchronousDQ)]
411pub struct SignatureBanks {
412 even: SyncBRAM<HashWords, SIGNATURE_ADDRESS_BITS>,
413 odd: SyncBRAM<HashWords, SIGNATURE_ADDRESS_BITS>,
414}
415
416impl SynchronousIO for SignatureBanks {
417 type I = SignatureBanksInput;
418 type O = SignatureBanksOutput;
419 type Kernel = signature_banks_kernel;
420}
421
422#[allow(clippy::used_underscore_binding)] #[kernel]
425pub fn signature_banks_kernel(
426 _clock_reset: ClockReset,
427 input: SignatureBanksInput,
428 q: SignatureBanksQ,
429) -> (SignatureBanksOutput, SignatureBanksD) {
430 (
431 SignatureBanksOutput {
432 even: q.even,
433 odd: q.odd,
434 },
435 SignatureBanksD {
436 even: SyncBramIn::<HashWords, SIGNATURE_ADDRESS_BITS> {
437 read_addr: input.read_addr,
438 write: input.even_write,
439 },
440 odd: SyncBramIn::<HashWords, SIGNATURE_ADDRESS_BITS> {
441 read_addr: input.read_addr,
442 write: input.odd_write,
443 },
444 },
445 )
446}
447
448#[kernel]
450pub fn increment_segment_group_kernel(group: b4) -> b4 {
451 if group == b4(8) { b4(0) } else { group + b4(1) }
452}
453
454#[kernel]
456pub fn segment_bit_kernel(groups: SegmentGroups, segment: b7) -> bool {
457 let group: b4 = (segment >> 3).resize();
458 let offset: b3 = segment.resize();
459 let word = match group {
460 Bits::<4>(0) => groups[0],
461 Bits::<4>(1) => groups[1],
462 Bits::<4>(2) => groups[2],
463 Bits::<4>(3) => groups[3],
464 Bits::<4>(4) => groups[4],
465 Bits::<4>(5) => groups[5],
466 Bits::<4>(6) => groups[6],
467 Bits::<4>(7) => groups[7],
468 _ => groups[8],
469 };
470 word & (b8(1) << offset) != b8(0)
471}
472
473#[kernel]
475pub fn set_segment_bit_kernel(
476 mut groups: SegmentGroups,
477 segment: b7,
478 value: bool,
479) -> SegmentGroups {
480 let group: b4 = (segment >> 3).resize();
481 let offset: b3 = segment.resize();
482 let bit = b8(1) << offset;
483 match group {
484 Bits::<4>(0) => {
485 groups[0] = if value {
486 groups[0] | bit
487 } else {
488 groups[0] & !bit
489 };
490 }
491 Bits::<4>(1) => {
492 groups[1] = if value {
493 groups[1] | bit
494 } else {
495 groups[1] & !bit
496 };
497 }
498 Bits::<4>(2) => {
499 groups[2] = if value {
500 groups[2] | bit
501 } else {
502 groups[2] & !bit
503 };
504 }
505 Bits::<4>(3) => {
506 groups[3] = if value {
507 groups[3] | bit
508 } else {
509 groups[3] & !bit
510 };
511 }
512 Bits::<4>(4) => {
513 groups[4] = if value {
514 groups[4] | bit
515 } else {
516 groups[4] & !bit
517 };
518 }
519 Bits::<4>(5) => {
520 groups[5] = if value {
521 groups[5] | bit
522 } else {
523 groups[5] & !bit
524 };
525 }
526 Bits::<4>(6) => {
527 groups[6] = if value {
528 groups[6] | bit
529 } else {
530 groups[6] & !bit
531 };
532 }
533 Bits::<4>(7) => {
534 groups[7] = if value {
535 groups[7] | bit
536 } else {
537 groups[7] & !bit
538 };
539 }
540 _ => {
541 groups[8] = if value {
542 groups[8] | bit
543 } else {
544 groups[8] & !bit
545 };
546 }
547 }
548 groups
549}
550
551#[kernel]
553pub fn exclude_segment_groups_kernel(
554 ready: SegmentGroups,
555 excluded: SegmentGroups,
556) -> SegmentGroups {
557 [
558 ready[0] & !excluded[0],
559 ready[1] & !excluded[1],
560 ready[2] & !excluded[2],
561 ready[3] & !excluded[3],
562 ready[4] & !excluded[4],
563 ready[5] & !excluded[5],
564 ready[6] & !excluded[6],
565 ready[7] & !excluded[7],
566 ready[8] & !excluded[8] & b8(0x07),
567 ]
568}
569
570#[kernel]
576pub fn select_ready_segment_kernel(ready: SegmentGroups, cursor: b4) -> SegmentSelection {
577 let mut selection = SegmentSelection {
578 next_group: cursor,
579 ..SegmentSelection::default()
580 };
581 let mut scan_group = cursor;
582 for _scan in 0..SEGMENT_GROUPS {
583 let word = match scan_group {
584 Bits::<4>(0) => ready[0],
585 Bits::<4>(1) => ready[1],
586 Bits::<4>(2) => ready[2],
587 Bits::<4>(3) => ready[3],
588 Bits::<4>(4) => ready[4],
589 Bits::<4>(5) => ready[5],
590 Bits::<4>(6) => ready[6],
591 Bits::<4>(7) => ready[7],
592 _ => ready[8] & b8(0x07),
593 };
594 let mut offset = b3(0);
595 let mut found_in_group = false;
596 if word & b8(0x01) != b8(0) {
597 offset = b3(0);
598 found_in_group = true;
599 } else if word & b8(0x02) != b8(0) {
600 offset = b3(1);
601 found_in_group = true;
602 } else if word & b8(0x04) != b8(0) {
603 offset = b3(2);
604 found_in_group = true;
605 } else if word & b8(0x08) != b8(0) {
606 offset = b3(3);
607 found_in_group = true;
608 } else if word & b8(0x10) != b8(0) {
609 offset = b3(4);
610 found_in_group = true;
611 } else if word & b8(0x20) != b8(0) {
612 offset = b3(5);
613 found_in_group = true;
614 } else if word & b8(0x40) != b8(0) {
615 offset = b3(6);
616 found_in_group = true;
617 } else if word & b8(0x80) != b8(0) {
618 offset = b3(7);
619 found_in_group = true;
620 }
621 if !selection.valid && found_in_group {
622 let group_wide: b7 = scan_group.resize();
623 let offset_wide: b7 = offset.resize();
624 selection.valid = true;
625 selection.segment = (group_wide << 3) + offset_wide;
626 selection.next_group = increment_segment_group_kernel(scan_group);
627 }
628 scan_group = increment_segment_group_kernel(scan_group);
629 }
630 selection
631}
632
633#[kernel]
635pub fn segment_task_fields_kernel(
636 stage: b5,
637 segment: b7,
638 context: b4,
639 generation: b8,
640) -> TagFields {
641 let mut fields = TagFields {
642 context,
643 segment,
644 generation,
645 ..TagFields::default()
646 };
647 match stage {
648 Bits::<5>(0) => {
649 fields.kind = b3(3);
650 }
651 Bits::<5>(1) => {
652 fields.kind = b3(4);
653 }
654 Bits::<5>(2) => {
655 fields.kind = b3(5);
656 fields.block_index = b6(1);
657 }
658 _ => {
659 fields.kind = b3(6);
660 fields.chain_step = (stage - b5(2)).resize();
661 }
662 }
663 fields
664}
665
666#[kernel]
672pub fn segment_required_mask_kernel(stage: b5) -> b4 {
673 if stage == b5(1) {
674 b4(0)
675 } else if stage >= b5(3) && stage <= b5(17) {
676 (stage - b5(2)).resize()
677 } else {
678 b4(0)
679 }
680}
681
682#[kernel]
684pub fn public_key_endpoints_ready_kernel(endpoint_done: SegmentGroups, block: b6) -> bool {
685 let mut ready = false;
686 if block < b6(33) {
687 let block_wide: b7 = block.resize();
688 let first = block_wide << 1;
689 ready = segment_bit_kernel(endpoint_done, first)
690 && segment_bit_kernel(endpoint_done, first + b7(1));
691 } else if block == b6(33) {
692 ready = segment_bit_kernel(endpoint_done, b7(66));
693 }
694 ready
695}
696
697#[allow(clippy::assign_op_pattern)] #[kernel]
707pub fn select_public_key_focus_segment_kernel(
708 ready: SegmentGroups,
709 public_key_block: b6,
710 public_key_inflight: bool,
711) -> SegmentSelection {
712 let mut focus_block = public_key_block;
713 if public_key_inflight && public_key_block < b6(33) {
714 focus_block = public_key_block + b6(1);
715 }
716 let mut selection = SegmentSelection::default();
717 for _lookahead in 0..PUBLIC_KEY_FOCUS_BLOCKS {
718 if !selection.valid && focus_block < b6(33) {
719 let block_wide: b7 = focus_block.resize();
720 let first = block_wide << 1;
721 let second = first + b7(1);
722 if segment_bit_kernel(ready, first) {
723 selection.valid = true;
724 selection.segment = first;
725 } else if segment_bit_kernel(ready, second) {
726 selection.valid = true;
727 selection.segment = second;
728 }
729 } else if !selection.valid && focus_block == b6(33) && segment_bit_kernel(ready, b7(66)) {
730 selection.valid = true;
731 selection.segment = b7(66);
732 }
733 if focus_block < b6(33) {
734 focus_block = focus_block + b6(1);
735 }
736 }
737 selection
738}
739
740#[allow(clippy::needless_range_loop)] #[kernel]
743pub fn wake_segments_for_mask_kernel(
744 stages: SegmentStages,
745 mut ready: SegmentGroups,
746 inflight: SegmentGroups,
747 retired_mask: b4,
748) -> SegmentGroups {
749 for segment in 0..ENGINE_SEGMENTS {
750 let segment_index = b7(segment as u128);
751 let stage = stages[segment];
752 let waiting = !segment_bit_kernel(ready, segment_index)
753 && !segment_bit_kernel(inflight, segment_index);
754 let needs_retired_mask = (stage == b5(1) && retired_mask == b4(0))
755 || (stage >= b5(3)
756 && stage <= b5(17)
757 && segment_required_mask_kernel(stage) == retired_mask);
758 if waiting && needs_retired_mask {
759 ready = set_segment_bit_kernel(ready, segment_index, true);
760 }
761 }
762 ready
763}
764
765#[kernel]
767pub fn state_pair_exclusion_kernel(segment: b7) -> SegmentGroups {
768 let mut excluded = [b8(0); SEGMENT_GROUPS];
769 excluded = set_segment_bit_kernel(excluded, segment, true);
770 if segment & b7(1) == b7(0) {
771 if segment < b7(66) {
772 excluded = set_segment_bit_kernel(excluded, segment + b7(1), true);
773 }
774 } else {
775 excluded = set_segment_bit_kernel(excluded, segment - b7(1), true);
776 }
777 excluded
778}
779
780#[kernel]
782pub fn union_segment_groups_kernel(left: SegmentGroups, right: SegmentGroups) -> SegmentGroups {
783 [
784 left[0] | right[0],
785 left[1] | right[1],
786 left[2] | right[2],
787 left[3] | right[3],
788 left[4] | right[4],
789 left[5] | right[5],
790 left[6] | right[6],
791 left[7] | right[7],
792 (left[8] | right[8]) & b8(0x07),
793 ]
794}
795
796#[kernel]
798pub fn prepare_request_kernel(input: PrepareRequestInput) -> CompressionInput {
799 let initial = initial_state_words_kernel(b1(0));
800 let private_key = hash_words_to_bytes_kernel(input.private_key);
801 let public_seed = hash_words_to_bytes_kernel(input.public_seed);
802 let state_words = if input.fields.segment & b7(1) == b7(0) {
803 input.state_even
804 } else {
805 input.state_odd
806 };
807 let state = hash_words_to_bytes_kernel(state_words);
808 let mask = hash_words_to_bytes_kernel(input.mask);
809 let mut chaining = initial;
810 let mut block = private_seed_block_kernel(input.private_seed);
811
812 match input.fields.kind {
813 Bits::<3>(0) => {}
814 Bits::<3>(1) => {
815 block = prf_block_kernel(PrfBlockInput {
816 seed: private_key,
817 index: b16(0),
818 });
819 }
820 Bits::<3>(2) => {
821 block = prf_block_kernel(PrfBlockInput {
822 seed: public_seed,
823 index: input.fields.segment.resize(),
824 });
825 }
826 Bits::<3>(3) => {
827 let segment_index: b16 = input.fields.segment.resize();
828 block = prf_block_kernel(PrfBlockInput {
829 seed: private_key,
830 index: segment_index + b16(1),
831 });
832 }
833 Bits::<3>(4) => {
834 block = secret_data_block_kernel(SecretDataInput {
835 function_key: mask,
836 secret_prf: state,
837 });
838 }
839 Bits::<3>(5) => {
840 chaining = state_words;
841 block = secret_padding_block_kernel(b1(0));
842 }
843 Bits::<3>(6) => {
844 block = chain_block_kernel(ChainBlockInput { state, mask });
845 }
846 _ => {
847 if input.fields.block_index == b6(0) {
848 chaining = initial;
849 } else {
850 chaining = input.public_key_state;
851 }
852 if input.fields.block_index == b6(33) {
853 block = endpoint_final_block_kernel(hash_words_to_bytes_kernel(input.state_even));
854 } else {
855 block = endpoint_pair_block_kernel(EndpointPairInput {
856 first: hash_words_to_bytes_kernel(input.state_even),
857 second: hash_words_to_bytes_kernel(input.state_odd),
858 });
859 }
860 }
861 }
862
863 CompressionInput {
864 chaining,
865 block,
866 tag: encode_tag_kernel(input.fields),
867 valid: true,
868 }
869}
870
871#[derive(Clone, Debug, Synchronous, SynchronousDQ)]
873#[rhdl(dq_no_prefix)]
874pub struct SingleContextWorkEngine {
875 control: DFF<EngineControl>,
876 request: NoResetDff<CompressionInput>,
877 private_seed: NoResetDff<HashBytes>,
878 message_digits: NoResetDff<MessageDigitArray>,
879 private_key: NoResetDff<HashWords>,
880 public_seed: NoResetDff<HashWords>,
881 public_key_state: NoResetDff<HashWords>,
882 state_even: SyncBRAM<HashWords, STATE_BANK_ADDRESS_BITS>,
883 state_odd: SyncBRAM<HashWords, STATE_BANK_ADDRESS_BITS>,
884 masks: SyncBRAM<HashWords, MASK_ADDRESS_BITS>,
885 signature: SignatureBanks,
886}
887
888impl Default for SingleContextWorkEngine {
889 fn default() -> Self {
890 Self {
891 control: DFF::new(EngineControl::default()),
892 request: NoResetDff::new(),
893 private_seed: NoResetDff::new(),
894 message_digits: NoResetDff::new(),
895 private_key: NoResetDff::new(),
896 public_seed: NoResetDff::new(),
897 public_key_state: NoResetDff::new(),
898 state_even: SyncBRAM::default(),
899 state_odd: SyncBRAM::default(),
900 masks: SyncBRAM::default(),
901 signature: SignatureBanks::default(),
902 }
903 }
904}
905
906impl SynchronousIO for SingleContextWorkEngine {
907 type I = ContextEngineInput;
908 type O = ContextEngineOutput;
909 type Kernel = single_context_work_engine_kernel;
910}
911
912#[allow(clippy::assign_op_pattern, clippy::match_same_arms)] #[kernel]
915pub fn single_context_work_engine_kernel(
916 clock_reset: ClockReset,
917 input: ContextEngineInput,
918 q: Q,
919) -> (ContextEngineOutput, D) {
920 let resetting = clock_reset.reset.any();
921 let zero_bytes = [b8(0); 32];
922 let zero_words = [b32(0); 8];
923 let mut control = q.control;
924 let mut next_request = q.request;
925 let mut next_private_seed = q.private_seed;
926 let mut next_message_digits = q.message_digits;
927 let mut next_private_key = q.private_key;
928 let mut next_public_seed = q.public_seed;
929 let mut next_public_key_state = q.public_key_state;
930
931 let mut state_read_addr = b6(0);
932 let mut mask_read_addr = b4(0);
933 let mut signature_read_addr = b6(0);
934 let mut state_even_write = SyncBramWrite::<HashWords, STATE_BANK_ADDRESS_BITS> {
935 addr: b6(0),
936 value: zero_words,
937 enable: false,
938 };
939 let mut state_odd_write = SyncBramWrite::<HashWords, STATE_BANK_ADDRESS_BITS> {
940 addr: b6(0),
941 value: zero_words,
942 enable: false,
943 };
944 let mut mask_write = SyncBramWrite::<HashWords, MASK_ADDRESS_BITS> {
945 addr: b4(0),
946 value: zero_words,
947 enable: false,
948 };
949 let mut signature_even_write = SyncBramWrite::<HashWords, SIGNATURE_ADDRESS_BITS> {
950 addr: b6(0),
951 value: zero_words,
952 enable: false,
953 };
954 let mut signature_odd_write = SyncBramWrite::<HashWords, SIGNATURE_ADDRESS_BITS> {
955 addr: b6(0),
956 value: zero_words,
957 enable: false,
958 };
959
960 let start_ready = !resetting
961 && !q.control.active
962 && !q.control.result_valid
963 && input.output_credit_available
964 && input.context_enabled;
965 let start_accepted = input.start_valid && start_ready;
966 let start_rejected = !resetting
967 && input.start_valid
968 && !q.control.active
969 && !q.control.result_valid
970 && input.output_credit_available
971 && !input.context_enabled;
972
973 let credit_release =
974 !resetting && !q.control.active && q.control.result_valid && input.result_taken;
975
976 if credit_release {
977 control.result_valid = false;
978 control.credit_reserved = false;
979 control.fault = false;
980 control.result_read_pending = false;
981 control.private_key_consumers_remaining = b7(0);
982 next_private_seed = zero_bytes;
983 next_private_key = zero_words;
984 }
985
986 if start_accepted {
987 control.active = true;
988 control.credit_reserved = true;
989 control.result_valid = false;
990 control.fault = false;
991 control.seed_ready = true;
992 control.seed_inflight = false;
993 control.public_seed_ready = false;
994 control.public_seed_inflight = false;
995 control.public_seed_done = false;
996 control.private_key_consumers_remaining = b7(68);
997 control.mask_ready = b16(0);
998 control.mask_inflight = b16(0);
999 control.mask_done = b16(0);
1000 control.segment_ready = [b8(0); SEGMENT_GROUPS];
1001 control.segment_inflight = [b8(0); SEGMENT_GROUPS];
1002 control.segment_stage = [b5(0); ENGINE_SEGMENTS];
1003 control.endpoint_done = [b8(0); SEGMENT_GROUPS];
1004 control.segment_group_cursor = b4(0);
1005 control.public_key_block = b6(0);
1006 control.public_key_inflight = false;
1007 control.public_key_state_ready = true;
1008 control.total_issued = b11(0);
1009 control.total_retired = b11(0);
1010 control.prefetch_pending = false;
1011 control.request_valid = false;
1012 control.context = input.context;
1013 control.generation = input.generation;
1014 control.result_read_pending = false;
1015 next_private_seed = input.private_seed;
1016 next_message_digits = message_digits_kernel(input.message);
1017 }
1018
1019 let request_accepted =
1022 !resetting && q.control.active && q.control.request_valid && input.request_ready;
1023 if request_accepted {
1024 let issued_fields = decode_tag_kernel(q.request.tag);
1025 control.request_valid = false;
1026 control.total_issued = q.control.total_issued + b11(1);
1027 match issued_fields.kind {
1028 Bits::<3>(0) => {
1029 control.seed_ready = false;
1030 control.seed_inflight = true;
1031 next_private_seed = zero_bytes;
1034 }
1035 Bits::<3>(1) => {
1036 control.public_seed_ready = false;
1037 control.public_seed_inflight = true;
1038 }
1039 Bits::<3>(2) => {
1040 let bit = b16(1) << issued_fields.segment;
1041 control.mask_ready = q.control.mask_ready & !bit;
1042 control.mask_inflight = q.control.mask_inflight | bit;
1043 }
1044 Bits::<3>(3) => {
1045 control.segment_ready =
1046 set_segment_bit_kernel(q.control.segment_ready, issued_fields.segment, false);
1047 control.segment_inflight =
1048 set_segment_bit_kernel(q.control.segment_inflight, issued_fields.segment, true);
1049 }
1050 Bits::<3>(4) => {
1051 control.segment_ready =
1052 set_segment_bit_kernel(q.control.segment_ready, issued_fields.segment, false);
1053 control.segment_inflight =
1054 set_segment_bit_kernel(q.control.segment_inflight, issued_fields.segment, true);
1055 }
1056 Bits::<3>(5) => {
1057 control.segment_ready =
1058 set_segment_bit_kernel(q.control.segment_ready, issued_fields.segment, false);
1059 control.segment_inflight =
1060 set_segment_bit_kernel(q.control.segment_inflight, issued_fields.segment, true);
1061 }
1062 Bits::<3>(6) => {
1063 control.segment_ready =
1064 set_segment_bit_kernel(q.control.segment_ready, issued_fields.segment, false);
1065 control.segment_inflight =
1066 set_segment_bit_kernel(q.control.segment_inflight, issued_fields.segment, true);
1067 }
1068 _ => {
1069 control.public_key_inflight = true;
1070 control.public_key_state_ready = false;
1071 }
1072 }
1073 let private_key_consumer = issued_fields.kind == b3(1) || issued_fields.kind == b3(3);
1074 if private_key_consumer {
1075 if q.control.private_key_consumers_remaining == b7(0) {
1076 control.fault = true;
1080 } else {
1081 control.private_key_consumers_remaining =
1082 q.control.private_key_consumers_remaining - b7(1);
1083 if q.control.private_key_consumers_remaining == b7(1) {
1084 next_private_key = zero_words;
1085 }
1086 }
1087 }
1088 }
1089
1090 let response_fields = decode_tag_kernel(input.response.tag);
1091 let response_common = !resetting
1092 && q.control.active
1093 && input.response.valid
1094 && tag_is_well_formed_kernel(input.response.tag)
1095 && response_fields.context == q.control.context
1096 && response_fields.generation == q.control.generation;
1097
1098 let seed_response = response_common && response_fields.kind == b3(0) && q.control.seed_inflight;
1099 let public_seed_response =
1100 response_common && response_fields.kind == b3(1) && q.control.public_seed_inflight;
1101 let bounded_response_segment = if response_fields.segment < b7(67) {
1102 response_fields.segment
1103 } else {
1104 b7(0)
1105 };
1106 let bounded_mask_index = if response_fields.segment < b7(16) {
1107 response_fields.segment
1108 } else {
1109 b7(0)
1110 };
1111 let mask_response_bit = b16(1) << bounded_mask_index;
1112 let mask_response = response_common
1113 && response_fields.kind == b3(2)
1114 && q.control.mask_inflight & mask_response_bit != b16(0);
1115 let segment_response_inflight =
1116 segment_bit_kernel(q.control.segment_inflight, bounded_response_segment);
1117 let segment_response_expected = segment_task_fields_kernel(
1118 q.control.segment_stage[bounded_response_segment],
1119 bounded_response_segment,
1120 q.control.context,
1121 q.control.generation,
1122 );
1123 let segment_response = response_common
1124 && response_fields.kind >= b3(3)
1125 && response_fields.kind <= b3(6)
1126 && segment_response_inflight
1127 && input.response.tag == encode_tag_kernel(segment_response_expected);
1128 let public_key_response = response_common
1129 && response_fields.kind == b3(7)
1130 && q.control.public_key_inflight
1131 && response_fields.block_index == q.control.public_key_block;
1132 let response_accepted = seed_response
1133 || public_seed_response
1134 || mask_response
1135 || segment_response
1136 || public_key_response;
1137 let response_rejected = !resetting && input.response.valid && !response_accepted;
1138 let mut done = false;
1139 let mut response_cycle_excluded = [b8(0); SEGMENT_GROUPS];
1140 let mut public_key_response_guard = false;
1141
1142 if response_rejected {
1143 control.fault = true;
1144 }
1145
1146 if response_accepted {
1147 control.total_retired = q.control.total_retired + b11(1);
1148 }
1149
1150 if seed_response {
1151 next_private_key = input.response.digest;
1152 control.seed_inflight = false;
1153 control.public_seed_ready = true;
1154 control.segment_ready = [
1155 b8(0xff),
1156 b8(0xff),
1157 b8(0xff),
1158 b8(0xff),
1159 b8(0xff),
1160 b8(0xff),
1161 b8(0xff),
1162 b8(0xff),
1163 b8(0x07),
1164 ];
1165 }
1168
1169 if public_seed_response {
1170 next_public_seed = input.response.digest;
1171 control.public_seed_inflight = false;
1172 control.public_seed_done = true;
1173 control.mask_ready = b16(0xffff);
1174 }
1175
1176 if mask_response {
1177 control.mask_inflight = control.mask_inflight & !mask_response_bit;
1178 control.mask_done = control.mask_done | mask_response_bit;
1179 mask_write = SyncBramWrite::<HashWords, MASK_ADDRESS_BITS> {
1180 addr: response_fields.segment.resize(),
1181 value: input.response.digest,
1182 enable: true,
1183 };
1184 let retired_mask: b4 = response_fields.segment.resize();
1185 let ready_before_wake = control.segment_ready;
1186 control.segment_ready = wake_segments_for_mask_kernel(
1187 control.segment_stage,
1188 control.segment_ready,
1189 control.segment_inflight,
1190 retired_mask,
1191 );
1192 response_cycle_excluded = union_segment_groups_kernel(
1193 response_cycle_excluded,
1194 exclude_segment_groups_kernel(control.segment_ready, ready_before_wake),
1195 );
1196 }
1197
1198 if segment_response {
1199 let segment = response_fields.segment;
1200 let segment_addr: b6 = (segment >> 1).resize();
1201 control.segment_inflight = set_segment_bit_kernel(control.segment_inflight, segment, false);
1202 response_cycle_excluded = union_segment_groups_kernel(
1206 response_cycle_excluded,
1207 state_pair_exclusion_kernel(segment),
1208 );
1209 if segment & b7(1) == b7(0) {
1210 state_even_write = SyncBramWrite::<HashWords, STATE_BANK_ADDRESS_BITS> {
1211 addr: segment_addr,
1212 value: input.response.digest,
1213 enable: true,
1214 };
1215 } else {
1216 state_odd_write = SyncBramWrite::<HashWords, STATE_BANK_ADDRESS_BITS> {
1217 addr: segment_addr,
1218 value: input.response.digest,
1219 enable: true,
1220 };
1221 }
1222
1223 let current_stage = q.control.segment_stage[segment];
1224 let mut next_stage = b5(18);
1225 let mut dependent_ready = false;
1226 if current_stage == b5(0) {
1227 next_stage = b5(1);
1228 dependent_ready = control.mask_done & b16(1) != b16(0);
1229 } else if current_stage == b5(1) {
1230 next_stage = b5(2);
1231 dependent_ready = true;
1232 } else if current_stage == b5(2) {
1233 next_stage = b5(3);
1234 dependent_ready = control.mask_done & b16(2) != b16(0);
1235 let digit = q.message_digits[segment];
1236 if digit == b4(0) {
1237 signature_even_write = SyncBramWrite::<HashWords, SIGNATURE_ADDRESS_BITS> {
1238 addr: (segment >> 1).resize(),
1239 value: input.response.digest,
1240 enable: true,
1241 };
1242 if segment & b7(1) != b7(0) {
1243 signature_even_write.enable = false;
1244 signature_odd_write = SyncBramWrite::<HashWords, SIGNATURE_ADDRESS_BITS> {
1245 addr: (segment >> 1).resize(),
1246 value: input.response.digest,
1247 enable: true,
1248 };
1249 }
1250 }
1251 } else if current_stage >= b5(3) && current_stage < b5(17) {
1252 next_stage = current_stage + b5(1);
1253 let required = segment_required_mask_kernel(next_stage);
1254 dependent_ready = control.mask_done & (b16(1) << required) != b16(0);
1255 let digit = q.message_digits[segment];
1256 let completed_step: b4 = (current_stage - b5(2)).resize();
1257 if digit == completed_step {
1258 signature_even_write = SyncBramWrite::<HashWords, SIGNATURE_ADDRESS_BITS> {
1259 addr: (segment >> 1).resize(),
1260 value: input.response.digest,
1261 enable: true,
1262 };
1263 if segment & b7(1) != b7(0) {
1264 signature_even_write.enable = false;
1265 signature_odd_write = SyncBramWrite::<HashWords, SIGNATURE_ADDRESS_BITS> {
1266 addr: (segment >> 1).resize(),
1267 value: input.response.digest,
1268 enable: true,
1269 };
1270 }
1271 }
1272 } else {
1273 control.endpoint_done = set_segment_bit_kernel(q.control.endpoint_done, segment, true);
1274 public_key_response_guard = true;
1275 let digit = q.message_digits[segment];
1276 if digit == b4(15) {
1277 signature_even_write = SyncBramWrite::<HashWords, SIGNATURE_ADDRESS_BITS> {
1278 addr: (segment >> 1).resize(),
1279 value: input.response.digest,
1280 enable: true,
1281 };
1282 if segment & b7(1) != b7(0) {
1283 signature_even_write.enable = false;
1284 signature_odd_write = SyncBramWrite::<HashWords, SIGNATURE_ADDRESS_BITS> {
1285 addr: (segment >> 1).resize(),
1286 value: input.response.digest,
1287 enable: true,
1288 };
1289 }
1290 }
1291 }
1292 control.segment_stage[segment] = next_stage;
1293 if dependent_ready {
1294 control.segment_ready = set_segment_bit_kernel(control.segment_ready, segment, true);
1295 response_cycle_excluded =
1296 set_segment_bit_kernel(response_cycle_excluded, segment, true);
1297 }
1298 }
1299
1300 if public_key_response {
1301 next_public_key_state = input.response.digest;
1302 control.public_key_inflight = false;
1303 control.public_key_state_ready = true;
1304 if q.control.public_key_block == b6(33) {
1305 let exact_final = q.control.total_issued == b11(1258)
1306 && q.control.total_retired == b11(1257)
1307 && q.control.private_key_consumers_remaining == b7(0)
1308 && q.control.endpoint_done[0] == b8(0xff)
1309 && q.control.endpoint_done[1] == b8(0xff)
1310 && q.control.endpoint_done[2] == b8(0xff)
1311 && q.control.endpoint_done[3] == b8(0xff)
1312 && q.control.endpoint_done[4] == b8(0xff)
1313 && q.control.endpoint_done[5] == b8(0xff)
1314 && q.control.endpoint_done[6] == b8(0xff)
1315 && q.control.endpoint_done[7] == b8(0xff)
1316 && q.control.endpoint_done[8] == b8(0x07);
1317 if exact_final {
1318 control.active = false;
1319 control.credit_reserved = true;
1320 control.result_valid = true;
1321 control.prefetch_pending = false;
1322 control.request_valid = false;
1323 done = true;
1324 } else {
1325 control.fault = true;
1326 }
1327 } else {
1328 control.public_key_block = q.control.public_key_block + b6(1);
1329 }
1330 }
1331
1332 if !resetting && q.control.active && q.control.prefetch_pending && !q.control.request_valid {
1335 next_request = prepare_request_kernel(PrepareRequestInput {
1336 fields: decode_tag_kernel(q.control.prefetch_tag),
1337 private_seed: q.private_seed,
1338 private_key: q.private_key,
1339 public_seed: q.public_seed,
1340 public_key_state: q.public_key_state,
1341 state_even: q.state_even,
1342 state_odd: q.state_odd,
1343 mask: q.masks,
1344 });
1345 control.prefetch_pending = false;
1346 control.request_valid = true;
1347 }
1348
1349 let request_slot_free = !control.request_valid && !control.prefetch_pending;
1352 let visible_segment_ready =
1353 exclude_segment_groups_kernel(control.segment_ready, response_cycle_excluded);
1354 let segment_selection =
1355 select_ready_segment_kernel(visible_segment_ready, control.segment_group_cursor);
1356 let focus_selection = select_public_key_focus_segment_kernel(
1357 visible_segment_ready,
1358 control.public_key_block,
1359 control.public_key_inflight,
1360 );
1361 let public_key_ready = !public_key_response_guard
1362 && !control.public_key_inflight
1363 && control.public_key_state_ready
1364 && public_key_endpoints_ready_kernel(control.endpoint_done, control.public_key_block);
1365 let mut selected_valid = false;
1366 let mut selected_fields = TagFields {
1367 context: control.context,
1368 generation: control.generation,
1369 ..TagFields::default()
1370 };
1371
1372 if control.active && request_slot_free {
1373 if public_key_ready {
1374 selected_valid = true;
1375 selected_fields.kind = b3(7);
1376 selected_fields.block_index = control.public_key_block;
1377 } else if control.seed_ready {
1378 selected_valid = true;
1379 selected_fields.kind = b3(0);
1380 } else if control.public_seed_ready {
1381 selected_valid = true;
1382 selected_fields.kind = b3(1);
1383 } else if control.mask_ready != b16(0) {
1384 selected_valid = true;
1385 selected_fields.kind = b3(2);
1386 if control.mask_ready & b16(0x0001) != b16(0) {
1387 selected_fields.segment = b7(0);
1388 } else if control.mask_ready & b16(0x0002) != b16(0) {
1389 selected_fields.segment = b7(1);
1390 } else if control.mask_ready & b16(0x0004) != b16(0) {
1391 selected_fields.segment = b7(2);
1392 } else if control.mask_ready & b16(0x0008) != b16(0) {
1393 selected_fields.segment = b7(3);
1394 } else if control.mask_ready & b16(0x0010) != b16(0) {
1395 selected_fields.segment = b7(4);
1396 } else if control.mask_ready & b16(0x0020) != b16(0) {
1397 selected_fields.segment = b7(5);
1398 } else if control.mask_ready & b16(0x0040) != b16(0) {
1399 selected_fields.segment = b7(6);
1400 } else if control.mask_ready & b16(0x0080) != b16(0) {
1401 selected_fields.segment = b7(7);
1402 } else if control.mask_ready & b16(0x0100) != b16(0) {
1403 selected_fields.segment = b7(8);
1404 } else if control.mask_ready & b16(0x0200) != b16(0) {
1405 selected_fields.segment = b7(9);
1406 } else if control.mask_ready & b16(0x0400) != b16(0) {
1407 selected_fields.segment = b7(10);
1408 } else if control.mask_ready & b16(0x0800) != b16(0) {
1409 selected_fields.segment = b7(11);
1410 } else if control.mask_ready & b16(0x1000) != b16(0) {
1411 selected_fields.segment = b7(12);
1412 } else if control.mask_ready & b16(0x2000) != b16(0) {
1413 selected_fields.segment = b7(13);
1414 } else if control.mask_ready & b16(0x4000) != b16(0) {
1415 selected_fields.segment = b7(14);
1416 } else {
1417 selected_fields.segment = b7(15);
1418 }
1419 } else if focus_selection.valid {
1420 selected_valid = true;
1421 selected_fields = segment_task_fields_kernel(
1422 control.segment_stage[focus_selection.segment],
1423 focus_selection.segment,
1424 control.context,
1425 control.generation,
1426 );
1427 } else if segment_selection.valid {
1428 selected_valid = true;
1429 selected_fields = segment_task_fields_kernel(
1430 control.segment_stage[segment_selection.segment],
1431 segment_selection.segment,
1432 control.context,
1433 control.generation,
1434 );
1435 control.segment_group_cursor = segment_selection.next_group;
1436 }
1437 }
1438
1439 if selected_valid {
1440 control.prefetch_pending = true;
1441 control.prefetch_tag = encode_tag_kernel(selected_fields);
1442 if selected_fields.kind >= b3(3) && selected_fields.kind <= b3(6) {
1443 state_read_addr = (selected_fields.segment >> 1).resize();
1444 } else if selected_fields.kind == b3(7) {
1445 state_read_addr = selected_fields.block_index;
1446 }
1447 if selected_fields.kind == b3(4) {
1448 mask_read_addr = b4(0);
1449 } else if selected_fields.kind == b3(6) {
1450 mask_read_addr = selected_fields.chain_step;
1451 }
1452 }
1453
1454 control.result_read_pending = false;
1457 if !resetting
1458 && q.control.result_valid
1459 && input.result_read_enable
1460 && input.result_read_pair < b6(34)
1461 && !input.result_taken
1462 {
1463 state_read_addr = input.result_read_pair;
1464 signature_read_addr = input.result_read_pair;
1465 control.result_read_pending = true;
1466 control.result_read_pair = input.result_read_pair;
1467 }
1468
1469 if resetting {
1472 state_even_write.enable = false;
1473 state_odd_write.enable = false;
1474 mask_write.enable = false;
1475 signature_even_write.enable = false;
1476 signature_odd_write.enable = false;
1477 }
1478
1479 let mut request = q.request;
1480 request.valid = !resetting && q.control.request_valid;
1481 let output = ContextEngineOutput {
1482 start_ready,
1483 start_rejected,
1484 active: !resetting && q.control.active,
1485 output_credit_reserved: !resetting && q.control.credit_reserved,
1486 request,
1487 response_ready: response_accepted,
1488 response_rejected,
1489 fault: !resetting && q.control.fault,
1490 done,
1491 output_credit_release: credit_release,
1492 result_valid: !resetting && q.control.result_valid,
1493 public_seed: hash_words_to_bytes_kernel(q.public_seed),
1494 public_key_hash: hash_words_to_bytes_kernel(q.public_key_state),
1495 result_read_valid: !resetting && q.control.result_valid && q.control.result_read_pending,
1496 result_read_pair: q.control.result_read_pair,
1497 signature_first: hash_words_to_bytes_kernel(q.signature.even),
1498 signature_second: hash_words_to_bytes_kernel(q.signature.odd),
1499 result_read_second_valid: !resetting
1500 && q.control.result_valid
1501 && q.control.result_read_pending
1502 && q.control.result_read_pair < b6(33),
1503 endpoint_first: hash_words_to_bytes_kernel(q.state_even),
1504 endpoint_second: hash_words_to_bytes_kernel(q.state_odd),
1505 total_issued: q.control.total_issued,
1506 total_retired: q.control.total_retired,
1507 public_key_block: q.control.public_key_block,
1508 private_key_consumers_remaining: q.control.private_key_consumers_remaining,
1509 };
1510
1511 let d = D {
1512 control,
1513 request: next_request,
1514 private_seed: next_private_seed,
1515 message_digits: next_message_digits,
1516 private_key: next_private_key,
1517 public_seed: next_public_seed,
1518 public_key_state: next_public_key_state,
1519 state_even: SyncBramIn::<HashWords, STATE_BANK_ADDRESS_BITS> {
1520 read_addr: state_read_addr,
1521 write: state_even_write,
1522 },
1523 state_odd: SyncBramIn::<HashWords, STATE_BANK_ADDRESS_BITS> {
1524 read_addr: state_read_addr,
1525 write: state_odd_write,
1526 },
1527 masks: SyncBramIn::<HashWords, MASK_ADDRESS_BITS> {
1528 read_addr: mask_read_addr,
1529 write: mask_write,
1530 },
1531 signature: SignatureBanksInput {
1532 read_addr: signature_read_addr,
1533 even_write: signature_even_write,
1534 odd_write: signature_odd_write,
1535 },
1536 };
1537 (output, d)
1538}